Apr 24, 2026 2.0 KB octet-stream
1"""
2CSV analysis: reads all .csv files, produces summary statistics and a report.
3"""
4import modal
5
6app = modal.App("csv-analysis")
7image = modal.Image.debian_slim().pip_install("pandas")
8
9@app.function(image=image)
10def analyze():
11 import os
12 import pandas as pd
13
14 csv_files = sorted(f for f in os.listdir(".") if f.endswith(".csv"))
15 if not csv_files:
16 print("No CSV files found")
17 return
18
19 all_frames = []
20 for fname in csv_files:
21 df = pd.read_csv(fname)
22 df["_source"] = fname
23 all_frames.append(df)
24
25 combined = pd.concat(all_frames, ignore_index=True)
26
27 # summary stats
28 report = ["# csv analysis report\n"]
29 for fname in csv_files:
30 subset = combined[combined["_source"] == fname]
31 report.append(f"## {fname}")
32 report.append(f"- rows: {len(subset)}")
33 report.append(f"- columns: {', '.join(c for c in subset.columns if c != '_source')}")
34 for col in subset.select_dtypes(include="number").columns:
35 report.append(f"- {col}: sum={subset[col].sum():.2f}, mean={subset[col].mean():.2f}")
36 report.append("")
37
38 # pivot table if quantity and product columns exist
39 if "product" in combined.columns and "quantity" in combined.columns:
40 pivot = combined.pivot_table(index="product", values="quantity", aggfunc="sum")
41 report.append("## totals by product\n")
42 for product, row in pivot.iterrows():
43 report.append(f"- {product}: {int(row['quantity'])} units")
44 report.append("")
45
46 if "product" in combined.columns and "quantity" in combined.columns and "price" in combined.columns:
47 combined["revenue"] = combined["quantity"] * combined["price"]
48 total = combined["revenue"].sum()
49 report.append(f"## total revenue: ${total:,.2f}\n")
50
51 with open("report.md", "w") as f:
52 f.write("\n".join(report))
53
54 # also export cleaned combined csv
55 combined.drop(columns=["_source"]).to_csv("combined.csv", index=False)
56
57 print(f"Done: analyzed {len(csv_files)} files, {len(combined)} total rows")