Ciaren

Sales Data Analysis

Sales Data Analysis

A common first task: take a messy export of orders and turn it into a clean revenue summary by region. This walkthrough cleans the data, then groups and aggregates it.

You'll use: File Input → Drop Columns → Change Types → Drop Nulls → Filter Rows → Fill Nulls → Group by + Aggregate → Rename → Sort → File Output.

File Input
sales.csv
input
Drop Columns
remove internal_note
clean
Change Types
amount→float · ordered_at→datetime
clean
Drop Nulls
subset: amount
clean
Filter Rows
amount > 0 (remove refunds)
clean
Replace Values
normalise region casing
clean
Fill Nulls
region → "Unknown"
clean
Group By + Aggregate
region · sum(amount) · count(order_id)
transform
Rename Columns
amount→total_sales · order_id→num_orders
clean
Sort Rows
total_sales desc
clean
File Output
sales_summary.csv
output

Sample data

Save this as sales.csv and upload it on the Datasets page (📥 download sales.csv):

order_id,region,amount,ordered_at,internal_note
1001,North,120.50,2024-01-03,batch-a
1002,south,89.00,2024-01-03,batch-a
1003,North,,2024-01-04,batch-b
1004,South,-5.00,2024-01-04,refund
1005,,42.25,2024-01-05,batch-b
1006,north,210.00,2024-01-06,batch-c

Notice the problems: an internal column we don't want, mixed-case regions, a missing amount, a negative (refund) amount, and a missing region.

Build the flow

  1. File Input — File type CSV, select the sales.csv dataset.
  2. Drop Columnscolumns: ["internal_note"].
  3. Change Typescasts: { "amount": "float", "ordered_at": "datetime" }.
  4. Drop Nullssubset: ["amount"] (drop rows with no amount).
  5. Filter Rowscolumn: "amount", operator: ">", value: 0 (drop refunds).
  6. Replace Values — tidy region casing, e.g. column: "region", to_replace: "north", value: "North" (add a second node for "south" → "South").
  7. Fill Nullsstrategy: "constant", value: "Unknown", columns: ["region"].
  8. Group by + Aggregategroup_by: ["region"], aggregations: { "amount": "sum", "order_id": "count" }.
  9. Rename Columnsmapping: { "amount": "total_sales", "order_id": "num_orders" }.
  10. Sort Rowscolumns: ["total_sales"], ascending: false.
  11. File Outputformat: csv (name sales_summary).

Use the live preview after each node to watch the data take shape, then Run the flow.

Exported Python

Click Export → Python. The generated pandas script is standalone — the input frame is named after your dataset, and on a straight chain like this one, consecutive steps fuse into fluent method chains on that single variable:

import pandas as pd

df_sales = pd.read_csv('sales.csv')

df_sales = (
    df_sales.drop(columns=['internal_note'])
    .assign(amount=lambda _d: _d['amount'].astype('float64'), ordered_at=lambda _d: pd.to_datetime(_d['ordered_at']))
    .dropna(subset='amount')
    .loc[lambda _d: _d['amount'] > 0]
    .assign(region=lambda _d: _d['region'].replace('north', 'North'))
    .assign(region=lambda _d: _d['region'].replace('south', 'South'))
    .fillna({'region': 'Unknown'})
    .groupby('region')
    .agg({'amount': 'sum', 'order_id': 'count'})
    .reset_index()
    .rename(columns={'amount': 'total_sales', 'order_id': 'num_orders'})
    .sort_values('total_sales', ascending=False)
)

df_sales.to_csv('sales_summary.csv', index=False)

Ciaren also generates the polars equivalent — pick whichever you prefer.

Result

The flow transforms the raw messy CSV into a clean revenue summary.

Before
order_idregionamountordered_atinternal_note
1001North120.52024-01-03batch-a
1002south892024-01-03batch-a
1003Northnull2024-01-04batch-b
1004South-52024-01-04refund
1005null42.252024-01-05batch-b
1006north2102024-01-06batch-c
6 rows · 5 cols
Full flow
After
regiontotal_salesnewnum_ordersnew
North330.52
South891
Unknown42.251
3 rows · 3 cols

The refund row (amount = -5) and the missing-amount row were filtered out; the row with no region became Unknown.

Variations

  • Want revenue per day? Add Extract Date Parts on ordered_at and group by the new ordered_at_day column.
  • Want a recurring summary? Attach a schedule to run this flow every morning.

Next steps