A grouped dataframe is the result of calling `groupby` on a pandas DataFrame. It partitions rows by one or more key columns, then provides operations that work on each partition. Think of a store inventory split into departments: the grouped object holds the department subsets until you ask for counts, averages, or another grouped result. section 6.4
Grouping alone produces a `DataFrameGroupBy` object, not an immediately summarized table. Apply an aggregation such as `count`, `mean`, `std`, `min`, `max`, or `sum` to obtain per-group values. The result’s index contains the distinct grouping values; selecting one column before aggregation produces a Series rather than computing unwanted results for every column. section 6.4
Summarize products by department
To find the average retail price in each department, group on `department`, select `retail_price`, and call `mean`: `df.groupby('department')['retail_price'].mean()` To calculate several summaries with clear output names, aggregate selected columns in one operation. Grouping first and selecting columns before aggregation avoids doing work for columns that will be discarded. section 6.4
A grouped dataframe also supports operations that preserve or selectively return original rows:
- Use `filter` with a function that receives one group DataFrame and returns `True` or `False`; all rows of accepted groups remain in the result. section 7.8 section 7.10
- Use multiple grouping columns when one label is ambiguous, such as cities that share a name but belong to different states. section 7.10
- Use `transform` to calculate a group-based value while returning an output aligned to the original rows, such as each precipitation measurement’s proportion of its city total or each student’s yearly maximum. section 7.10 section 7.8
Filter whole groups by an aggregate condition
If every student in a year should be retained only when that year’s mean score exceeds 90, group by `year` and pass `filter` a predicate that tests `df['score'].mean()`. The predicate runs once per year on that year’s subset; a true result keeps all rows from that year, rather than only the rows with high individual scores. section 7.8
df.groupby('department').agg(mean_price=('retail_price', 'mean'),
std_price=('retail_price', 'std'),
max_sales=('sales', 'max'))
Compare several department-level summaries in one named aggregation: mean and standard deviation of retail price, plus maximum sales. section 6.4
Grouped results can feed directly into visualization. Grouping taxi rides by pickup year and month, then summing `total_amount` or counting `passenger_count`, creates indexed values that a bar plot uses for its axes. Selecting several fare-component columns before `sum` supports stacked bar plots. section 11.10

