agg runs several calculations on each group at once. Give it a list of function names:
df.groupby("region")["revenue"].agg(["sum", "mean", "count"])
To choose the names of the result columns, and use a different column for each, use named aggregation, written new_name=(column, function):
df.groupby("region").agg(
total_revenue=("revenue", "sum"),
orders=("order_id", "count"),
)
A dictionary works when the names can stay as they are: .agg({"units": "sum", "revenue": "max"}).
After a groupby, the group labels sit in the index, not in a column. That's handy for looking things up but awkward for merging or exporting. .reset_index() moves them back into a regular column, and groupby("region", as_index=False) does the same from the start.