Ravindra BagaleCourses & study guides मराठी Track your progress

22. Exporting and Sharing Your Analysis

22.2 to_csv and to_excel with Blinkit Summaries

Why. CSV is universal. Excel (.xlsx) is what many Indian ops leads still open first. pandas can write both. Excel needs the openpyxl package once.

What.

  • DataFrame.to_csv(path, index=False) — text table.
  • DataFrame.to_excel(path, index=False, sheet_name=...) — Excel sheet.
  • ExcelWriter — several sheets in one workbook.

How.

Export a city summary

  1. pip install openpyxl inside your venv (once).
  2. Aggregate: g = df.groupby(["city", "status"], as_index=False)["amount"].agg(orders="count", gmv="sum").
  3. Sort for humans: highest GMV first.
  4. g.to_csv("outputs/city_status.csv", index=False).
  5. g.to_excel("outputs/city_status.xlsx", index=False, sheet_name="city_status").
  6. Open the file outside Jupyter and check ₹ totals match df["amount"].sum() for Delivered if that is your rule.

Worked example A — Build and export (fictional).

import pandas as pd
from pathlib import Path

Path("outputs").mkdir(exist_ok=True)

df = pd.DataFrame({
    "order_id": [
        "BLK-261022-001", "BLK-261022-002", "BLK-261022-003",
        "AMN-261022-004", "BLK-261022-005", "BLK-261022-006",
        "BLK-261022-007", "AMN-261022-008", "BLK-261022-009",
    ],
    "city": [
        "Pune", "Pune", "Solapur", "Nashik", "Kolhapur",
        "Nagpur", "Sambhaji Nagar", "Pune", "Nashik",
    ],
    "status": [
        "Delivered", "Cancelled", "Delivered", "Delivered", "Delivered",
        "Returned", "Delivered", "Delivered", "Delivered",
    ],
    "amount": [189, 90, 120, 95, 210, 150, 340, 72, 88],
    "customer": [
        "Ruhi Bagale", "Amir", "Zoya", "Salman", "Ravina",
        "Raja", "Rani", "Shraddha Bagale", "Shahrukh",
    ],
})

summary = (
    df.groupby(["city", "status"], as_index=False)
      .agg(orders=("order_id", "count"), gmv_inr=("amount", "sum"))
      .sort_values(["gmv_inr", "city"], ascending=[False, True])
)
summary.to_csv("outputs/city_status.csv", index=False)
summary.to_excel("outputs/city_status.xlsx", index=False, sheet_name="city_status")
print(summary)
print("delivered gmv check", df.loc[df["status"].eq("Delivered"), "amount"].sum())

What you should see. A tidy sheet: one row per city×status, columns orders and gmv_inr. Pune Delivered should not include the Cancelled ₹90.

Worked example B — Multi-sheet workbook for Ravindra.

daily = (
    df.assign(day="22-10-2026")
      .groupby(["day", "city"], as_index=False)
      .agg(orders=("order_id", "count"), gmv_inr=("amount", "sum"))
)
notes = pd.DataFrame({
    "note": [
        "Fictional sample for learning only.",
        "GMV = sum of amount; confirm status filter with ops.",
        "Contact for questions: analyst@example.com",
    ]
})
with pd.ExcelWriter("outputs/blinkit_friday_pack.xlsx", engine="openpyxl") as xlw:
    summary.to_excel(xlw, sheet_name="city_status", index=False)
    daily.to_excel(xlw, sheet_name="daily_city", index=False)
    notes.to_excel(xlw, sheet_name="notes", index=False)

Worked example C — CSV for systems; Excel for people.

# UTF-8 CSV for pipelines / pandas peers
summary.to_csv("outputs/city_status_utf8.csv", index=False, encoding="utf-8")
# Excel-friendly CSV on some Windows setups (only if a peer asks)
summary.to_csv("outputs/city_status_utf8_sig.csv", index=False, encoding="utf-8-sig")

Prefer utf-8 by default. Use utf-8-sig when a colleague’s Excel mangles Marathi city notes (if you ever add them).

Practice task

Add a delivered_only sheet that filters status == "Delivered" before aggregating. Confirm sheet GMV equals the Delivered sum in Python.