Data analysis cheat sheet
The analyst's toolkit on a few screens: Excel and Google Sheets formulas for what you want to do, pivot tables, cleaning steps, pandas equivalents, which chart to pick, dashboard rules and a few Power BI measures. Keep it open next to your spreadsheet or notebook.
Before you touch the data
Write the question as a decision: "Should we extend evening delivery slots in the two busiest cities?" beats "look at delivery data". Then write what answer would change the decision, where the data lives, and when you will stop (Asking questions).
- Who will act on the answer, and by when?
- Which number, at what grain: per order, per store per day, per customer per month?
- What is the comparison: last year, another city, a target?
- What would make you distrust the data: missing days, test orders, refunds?
Spreadsheet formulas: "I want to..."
Formulas marked 365 need Microsoft 365 or Excel 2021 and later; Google Sheets supports most of them under the same names. In Sheets, separators may be ; instead of , depending on your locale. Examples use a Mangrove sales table with columns Store, Date, SKU and Amount (Data cleaning, Pivot tables).
| I want to... | Formula | Lesson |
|---|---|---|
| Look up a value by key | =XLOOKUP(A2, Articles[SKU], Articles[Name], "not found") (365, Sheets) | Data cleaning |
| Look up in any Excel version | =INDEX(Articles[Name], MATCH(A2, Articles[SKU], 0)) | Data cleaning |
| Sum with conditions | =SUMIFS(Sales[Amount], Sales[Store], "S-014", Sales[Date], ">="&DATE(2026,10,1)) | Pivot tables |
| Count with conditions | =COUNTIFS(Orders[Status], "cut", Orders[City], H1) | Pivot tables |
| Average with conditions | =AVERAGEIFS(Orders[Minutes], Orders[Slot], "Now") | Pivot tables |
| List the distinct values | =UNIQUE(Sales[Store]) (365, Sheets) | Data cleaning |
| Keep rows that match | =FILTER(Sales, Sales[Store]="S-014", "none") (365, Sheets) | Data cleaning |
| Sort by a column, largest first | =SORT(Table1, 4, -1) (365, Sheets) | Pivot tables |
| Name a step inside one formula | =LET(t, SUM(B2:B99), c, COUNT(B2:B99), t/c) (365, Sheets) | Data cleaning |
| Show a blank instead of an error | =IFERROR(B2/C2, "") | Data cleaning |
| Trim spaces and fix case | =PROPER(TRIM(A2)); =CLEAN(A2) removes non-printing characters | Data cleaning |
| Split text on a delimiter | =TEXTSPLIT(A2, "-") (Microsoft 365, Excel 2024); Sheets: =SPLIT(A2, "-") | Data cleaning |
| Join text | =TEXTJOIN(", ", TRUE, A2:A9) (2019+, Sheets) | Data cleaning |
| Turn text that looks like a number into a number | =VALUE(A2), or multiply by 1 | Data cleaning |
| Month of a date, for grouping | =EOMONTH(B2, -1) + 1 (first day of the month), or =TEXT(B2, "yyyy-mm") | Pivot tables |
| Working days between two dates | =NETWORKDAYS(B2, C2, Holidays) | Data cleaning |
| Change versus last period | =(C2 - B2) / B2, formatted as a percentage | Charts |
| Rank within a list | =RANK.EQ(D2, D$2:D$321) | Pivot tables |
| Group and total without a pivot | =GROUPBY(Sales[Store], Sales[Amount], SUM) (Microsoft 365, added 2024) | Pivot tables |
| Query a range like SQL (Sheets) | =QUERY(A1:D, "select A, sum(D) where A is not null group by A", 1) | Pivot tables |
Spreadsheet habits that save hours
- Turn every data range into a table (
Ctrl+Tin Excel). Formulas then readSales[Amount], and new rows join charts and pivots on their own. - Keep raw data on one sheet, untouched. Do cleaning in new columns or in Power Query, so you can redo it when next month's file arrives.
- Lock a reference with
$:$B$1fixed,B$1row fixed. PressF4in Excel for Windows to cycle through them while editing. - One fact per cell, one record per row, one header row. No merged cells in data.
- Paste as values before you send a file someone will sort, so formulas do not break.
- Store IDs and SKUs as text so leading zeros survive; format the column as Text before you paste.
Pivot tables
A pivot table is a GROUP BY you build with the mouse. Start from a clean table with one row per event (Pivot tables).
| I want to... | In the pivot | Lesson |
|---|---|---|
| Revenue per store | Store in Rows, Amount in Values (Sum) | Pivot tables |
| Stores by month | Store in Rows, Date in Columns, then group the dates by Months and Years | Pivot tables |
| Count orders, not sum them | Value Field Settings, Summarize by Count | Pivot tables |
| Count distinct customers (Excel) | Tick "Add this data to the Data Model" when creating, then use Distinct Count | Pivot tables |
| Each city's share of the total | Show Values As, % of Column Total | Pivot tables |
| Change versus last month | Show Values As, % Difference From, Base item: (previous) | Pivot tables |
| Let others filter by city | Insert Slicer (or a Timeline for dates) | Pivot tables |
| Pick up new data | Refresh; Refresh All is Ctrl+Alt+F5 in Excel for Windows. Pivots never update on their own | Pivot tables |
| See the rows behind a number | Double-click the value cell (Excel drills down to a new sheet) | Pivot tables |
Cleaning checklist
Run these on every new file before you trust a total (Data cleaning).
| Check | Spreadsheet | pandas |
|---|---|---|
| Row count matches the source | Status bar count | len(df) |
| Duplicate rows or keys | Conditional formatting, Duplicate Values; Remove Duplicates | df.duplicated(["order_id"]).sum() |
| Blanks per column | =COUNTBLANK(Sales[Amount]) | df.isna().sum() |
| Numbers stored as text | Green triangle; =ISNUMBER(B2) | df.dtypes, then pd.to_numeric(..., errors="coerce") |
| Dates parsed right (day and month not swapped) | Check a date after the 12th of the month | pd.to_datetime(s, format="%d/%m/%Y") |
| Odd spellings of one value | Filter dropdown on the column | df["city"].value_counts() |
| Impossible values | Sort ascending and descending | df.describe() |
| Test, staff and cancelled orders | Filter them out and write down the rule | df.query("is_test == False") |
| Totals tie to a known number | Compare with finance's report | df["amount_cents"].sum() |
Power Query in one breath
In Excel, Data, Get Data (Get & Transform, Excel 2016 and later) loads a file or folder into Power Query, where every cleaning step you click is recorded: remove columns, change type, split column, trim, fill down, unpivot, merge queries (a join), append queries (stack files). Next month, drop the new file in the folder and press Refresh; every step runs again. Power BI uses the same editor (Data cleaning, Warehouse models).
pandas: "I want to..."
Written for pandas 2.x. Import with import pandas as pd. The spreadsheet column shows the same move in Excel (Python and pandas).
| I want to... | pandas | Spreadsheet |
|---|---|---|
| Load a CSV with dates | df = pd.read_csv("sales.csv", parse_dates=["sold_at"], dtype={"site_id": "string"}) | Data, From Text/CSV |
| Load an Excel sheet | pd.read_excel("file.xlsx", sheet_name="Sales") (needs openpyxl) | Open the file |
| Get a feel for it | df.head(), df.info(), df.describe() | Scroll and sort |
| Pick columns and rows | df.loc[df["site_id"] == "S-014", ["sold_at", "amount_cents"]] | Filter |
| Filter with a readable condition | df.query("amount_cents > 5000 and city == 'North'") | Filter |
| Add a column | df["amount"] = df["amount_cents"] / 100 | New column formula |
| Total per group | df.groupby("site_id")["amount_cents"].sum() | Pivot or SUMIFS |
| Several totals per group, named | df.groupby("site_id").agg(orders=("order_id", "nunique"), revenue=("amount_cents", "sum")) | Pivot with several values |
| A pivot table | df.pivot_table(index="site_id", columns="month", values="amount_cents", aggfunc="sum", fill_value=0) | Pivot table |
| Join two tables | df.merge(articles, on="sku", how="left", validate="m:1") | XLOOKUP |
| Find rows that did not match | merge(..., indicator=True), then _merge == "left_only" | XLOOKUP returning "not found" |
| Wide to long | df.melt(id_vars="site_id", var_name="month", value_name="revenue") | Power Query, Unpivot |
| Daily totals from timestamps | df.resample("D", on="sold_at")["amount_cents"].sum() | Group dates in a pivot |
| 7-day rolling average | daily.rolling(7).mean() | =AVERAGE over the last 7 rows |
| Change versus previous row | s.pct_change(), s.shift(1) | =(C3-C2)/C2 |
| Bucket a number | pd.cut(df["basket"], bins=[0, 1000, 5000, 1e9]); pd.qcut(s, 4) for quartiles | Nested IF or XLOOKUP on bands |
| Top 10 | s.nlargest(10) | Sort, keep 10 |
| Save the result | out.to_csv("out.csv", index=False); to_excel needs openpyxl | Save As |
pandas traps
- Chained assignment such as
df[df.x > 0]["y"] = 1may change a copy and notdf. Use onedf.loc[df.x > 0, "y"] = 1. groupbydrops rows whose key is NaN unless you passdropna=False.- A merge on a key that repeats on both sides multiplies rows.
validate="m:1"raises an error instead of giving you a wrong total. mean()skips NaN, so an average over a column with gaps describes only the rows that have a value.- IDs read as numbers lose leading zeros. Pass
dtypefor them when reading.
Which chart
Pick the chart from the question, then remove everything that does not help answer it. Title the chart with the finding, not the metric name (Charts, Dashboard design).
| Question | Chart | Avoid |
|---|---|---|
| How did it change over time? | Line chart | Bars for 30+ time points |
| Which is bigger? | Horizontal bar, sorted | Pie with more than 3 slices |
| What share of the whole? | Stacked bar, or a single 100% bar | 3D anything |
| How is it spread out? | Histogram or box plot | Only an average |
| Do two numbers move together? | Scatter plot | Two lines on two y-axes |
| Where does the funnel leak? | Funnel or bar per step with conversion rates | A table of raw counts |
| One number that matters | Big number with its comparison (vs target, vs last week) | A gauge |
| Many stores by many weeks | Heatmap | A line per store |
Dashboard rules
A dashboard answers a few recurring questions for a named audience (Dashboard design, Agreed metrics).
- Top left holds the most important number. Read order: headline numbers, then trends, then breakdowns, then detail.
- Every number has a comparison and a definition one click away: what counts, which time zone, refreshed when.
- Five to nine tiles per page. More means two audiences; split it.
- Use one metric definition across the company (a metric layer or certified dataset), so the store team and finance see the same "net sales".
- Show when the data last refreshed, and alert the owner when a load fails (Data reliability).
- Start every axis for bars at zero. Lines may zoom, but say so.
- Colour means something: one highlight colour for the thing to look at, grey for the rest.
Power BI measures (DAX)
A measure is computed at query time for whatever filters the visual has; a calculated column is computed once per row. Prefer measures for totals and ratios (Warehouse models, Agreed metrics).
Net Sales = SUM ( Sales[AmountCents] ) / 100
Orders = DISTINCTCOUNT ( Sales[OrderId] )
Avg Basket = DIVIDE ( [Net Sales], [Orders] )
Sales S-014 = CALCULATE ( [Net Sales], Site[SiteId] = "S-014" )
Sales LY = CALCULATE ( [Net Sales], SAMEPERIODLASTYEAR ( 'Date'[Date] ) )
Sales YTD = TOTALYTD ( [Net Sales], 'Date'[Date] )
Growth % = DIVIDE ( [Net Sales] - [Sales LY], [Sales LY] )DIVIDE returns blank instead of an error on zero. Time intelligence needs a separate date table marked as a date table, joined to the fact table.
Star schema in one breath
Fact tables hold events with numbers (one row per sale line, per order, per delivery). Dimension tables describe them (store, article, date, customer). Facts join to dimensions by key, and dimensions never join to each other through the fact. Decide the grain of each fact table first and write it down: "one row per order line" (Reporting model, Warehouse models).
Using AI for analysis
AI assistants are fast at writing formulas, pandas code and first-draft summaries, and they make confident mistakes (AI analysis).
- Give the column names, types and three sample rows; never paste customer personal data into a tool your company has not approved.
- Ask for code, then run it yourself, so every number comes from the data and not from the model.
- Check one result by hand: pick one store and one day and recompute it.
- Ask the model to list its assumptions about the data, then check each one.
Telling the story
Lead with the answer, then the evidence, then what you recommend and what you do not know. One page, one chart per point (Data story).
Answer: Evening "Now" orders in the North and East cities grew 31% since July;
one extra rider shift from 6 to 9 pm would cut late orders by about half.
Evidence: chart of late orders by hour; table of riders on shift vs orders.
Ask: approve a 4-week trial in 20 stores, review on 30 November.
Caveats: July had two festival weekends; refunds are not yet in the data.Glossary
Plain definitions, with the lesson that explains each one.
- Aggregation
- Turning many rows into one number, such as a sum, count or average. Pivot tables
- Calculated column
- A column computed once per row and stored in the model. Warehouse models
- Data model
- Tables and the relationships between them that a pivot or BI tool reads. Reporting model
- Dimension
- A table or field you slice by: store, date, article, city. Reporting model
- Dynamic array
- An Excel formula result that spills into several cells, such as
UNIQUEorFILTER. Data cleaning - ETL and ELT
- Extract, transform, load: cleaning data before loading it, or loading raw data first and transforming it in the warehouse. Warehouse models
- Fact table
- A table of events with numbers, at one declared grain. Warehouse models
- Grain
- What one row means, such as one order line or one store per day. Reporting model
- KPI
- Key performance indicator: one of the few numbers a team agrees to steer by. Agreed metrics
- Measure
- A calculation evaluated for whatever filters are in place, such as net sales. Agreed metrics
- Metric definition
- A written rule for a number: what counts, what is excluded, which time zone, who owns it. Agreed metrics
- Outlier
- A value far from the rest, which is either an error to fix or a story to tell. Data cleaning
- Pivot table
- An interactive summary table that groups rows and totals values. Pivot tables
- Power Query
- Excel's and Power BI's recorded, repeatable cleaning steps. Data cleaning
- Self-service BI
- Letting business users build their own reports on top of certified, well-named datasets. Self-service
- Slicer
- A clickable filter on a pivot table or dashboard. Pivot tables
- Star schema
- Fact tables in the middle, joined to dimension tables around them. Warehouse models
- Tidy data
- One variable per column, one observation per row, one value per cell. Python and pandas
- Unpivot (melt)
- Turning month columns into rows of month and value, so tools can group them. Python and pandas
- Year over year (YoY)
- Comparing a period with the same period last year, which removes seasonality. Charts
Courses on Kolom
- Data Analysis with Excel, Python & AI: questions, cleaning, pivots, charts, pandas, AI help and the final story.
- Dashboards and Business Intelligence: reporting models, agreed metrics, dashboard design and data reliability.
- SQL & Data Modeling: pull your own data instead of waiting for an export.
- Statistics for Data Work: know when a difference is real.
- Metrics & Product Analytics: funnels, retention and experiments for product questions.
What to read next
- Storytelling with Data by Cole Nussbaumer Knaflic. Choosing and decluttering charts for a business audience.
- Python for Data Analysis by Wes McKinney, the creator of pandas, free online at wesmckinney.com/book.
- The pandas user guide at pandas.pydata.org. The "10 minutes to pandas" page is the fastest start.
- Microsoft's Excel function reference at support.microsoft.com/excel, which notes which version each function needs.
- The Data Warehouse Toolkit by Ralph Kimball and Margy Ross. The classic on star schemas and dimensional modeling.