Most small-business software exports one file per month. Sales, invoices, time sheets: July is one CSV, August is another.
Then the quarterly review comes around, and someone opens all three, pastes them under each other, deletes the header row that got pasted in twice, and hopes nothing was skipped. If the totals look off, they start again.
pandas does that stacking in one line, with no repeated headers and nothing skipped. Here's the version from my free lesson. It runs in Google Colab with a free Google account, nothing to install.
Three small monthly tables
Lakeside Office Supply is a made-up shop with two orders a month. In a new Colab notebook, run import pandas as pd, then in the next cell:
july = pd.DataFrame({'customer': ['Maple Dental', 'Cobalt Legal'], 'amount': [1250, 860]})
august = pd.DataFrame({'customer': ['Cobalt Legal', 'Harbor Accounting'], 'amount': [2310, 640]})
september = pd.DataFrame({'customer': ['Northside Realty', 'Maple Dental'], 'amount': [1890, 980]})
Typing the tables keeps the example small. With real exports, each line is july = pd.read_csv('july.csv') after you upload the files in Colab's Files panel.
Step 1: label each month before you stack
july['month'] = 'Jul'
august['month'] = 'Aug'
september['month'] = 'Sep'
This is the step people skip. Once three months are in one table, nothing says which row came from which file. A month column with the same value on every row keeps that, so you can still total by month, filter one month, or notice that a month is missing.
Step 2: stack them
quarter = pd.concat([july, august, september], ignore_index=True)
quarter
Output:
customer amount month
0 Maple Dental 1250 Jul
1 Cobalt Legal 860 Jul
2 Cobalt Legal 2310 Aug
3 Harbor Accounting 640 Aug
4 Northside Realty 1890 Sep
5 Maple Dental 980 Sep
pd.concat puts tables with the same columns under each other. ignore_index=True numbers the rows 0 to 5. Leave it out and you get 0, 1, 0, 1, 0, 1, which bites later when you look a row up by its number.
If you need to match two different tables side by side, the way VLOOKUP does, that's merge, not concat.
Step 3: total each month
quarter.groupby('month', sort=False)['amount'].sum()
month
Jul 2110
Aug 2950
Sep 2870
Name: amount, dtype: int64
sort=False matters here. By default groupby sorts the groups A to Z, which puts Aug before Jul. I ran it both ways: without sort=False you get Aug 2950, Jul 2110, Sep 2870. The numbers are right, but the review slide reads wrong.
Step 4: total each customer
quarter.groupby('customer')['amount'].sum()
customer
Cobalt Legal 3170
Harbor Accounting 640
Maple Dental 2230
Northside Realty 1890
Name: amount, dtype: int64
That's $7,930 for the quarter, and the same total whether you add up the months or the customers. That cross-check is the quickest way to know nothing got lost.
I re-ran every line with pandas 2.2.3 today, and the output matches the lesson.
Three things that trip people up
-
The columns must match. If August's export calls it
Customerand July's calls itcustomer, concat makes two columns and fills the gaps with NaN. Rename first:august = august.rename(columns={'Customer': 'customer'}). -
Amounts read as text. If the export has
$1,250, pandas reads text andsum()glues strings together. Clean it with.str.replace('[$,]', '', regex=True).astype(float)before totaling. Module 3 of the course cleans a messy export like that, plus stray spaces in names and a duplicate row. -
Twelve months, not three. Use
globto read every file in a folder and add the month from each file name in a loop. The idea is the same: label, then stack.
Why this beats the spreadsheet
The same six lines work on 6 orders or 60,000. Next quarter you drop in three new files and run the notebook again. Nobody deletes header rows, and the cross-check tells you right away if a month went missing.
Practice it step by step
The lesson, Python: Combine Monthly Sales Exports into One Quarter, has you type every line yourself on real Colab screens, and it checks each step. It's module 2 of the free Python for Spreadsheet Work course, which starts with totaling a sales export by customer. There's also a one-page Python cheat sheet for the whole course.
Practice it step by step, free: https://learn.ynteractive.com/content/python-combine-exports

Top comments (0)