Local Workflow Template
Upload the right file. Run the housed Python. Get the export.
This is the live shell for custom iterFact workflows that run in the desktop PWA or browser tab. The script travels with the template; the user only supplies files in the expected shape.
Ready
RuntimePyodide
ExecutionLocal browser
Python packagepandas
Runtime assetsiterFact cached + CDN fallback
Input
Template files
Source CSV
CSV shaped like the customer revenue file this template expects.
Selected fileNone yet
Template script
CSV profile and clean export
import pandas as pd
def transform(inputs, output_dir):
source_path = inputs["source_csv"]["path"]
df = pd.read_csv(source_path)
original_columns = list(df.columns)
df.columns = [
str(column).strip().lower().replace(" ", "_")
for column in df.columns
]
df = df.dropna(how="all")
warnings = []
required_columns = {"customer", "region", "revenue"}
missing_columns = sorted(required_columns.difference(set(df.columns)))
if missing_columns:
warnings.append("Missing expected columns: " + ", ".join(missing_columns))
if "region" not in df.columns:
df["region"] = "Unassigned"
if "revenue" in df.columns:
revenue_text = (
df["revenue"]
.astype(str)
.str.replace("$", "", regex=False)
.str.replace(",", "", regex=False)
)
df["revenue"] = pd.to_numeric(revenue_text, errors="coerce").fillna(0)
else:
df["revenue"] = 0
summary = (
df.groupby("region", dropna=False)
.agg(
rows=("region", "size"),
total_revenue=("revenue", "sum"),
average_revenue=("revenue", "mean"),
)
.reset_index()
.sort_values("total_revenue", ascending=False)
)
summary["total_revenue"] = summary["total_revenue"].round(2)
summary["average_revenue"] = summary["average_revenue"].round(2)
cleaned_path = f"{output_dir}/cleaned-data.csv"
profile_path = f"{output_dir}/region-profile.csv"
df.to_csv(cleaned_path, index=False)
summary.to_csv(profile_path, index=False)
return {
"summary": {
"input_rows": int(len(df)),
"input_columns": int(len(original_columns)),
"regions": int(summary.shape[0]),
},
"tables": {
"region_profile": summary.fillna("").astype(str).to_dict(orient="records"),
"cleaned_preview": df.head(20).fillna("").astype(str).to_dict(orient="records"),
},
"files": {
"cleaned_csv": {
"path": cleaned_path,
"filename": "cleaned-data.csv",
"mimeType": "text/csv",
},
"profile_csv": {
"path": profile_path,
"filename": "region-profile.csv",
"mimeType": "text/csv",
},
},
"warnings": warnings,
}
Output
Preview and downloads
No run yet.Upload a matching CSV or use the sample file to produce exports.