一个方括号 [‘c’:‘g’]:切片,按索引顺序连续取,首尾都包含。

两个方括号 [[’d’,‘f’,‘b’]]:花式索引,按你给的任意顺序、任意集合取,不要求连续,结果顺序跟你写的列表一致。

场景 单 [] 切片 双 [] 花式
要连续区间 ✅ ❌
要指定顺序 ❌ ✅
要取的标签不连续 ❌ ✅
要取的标签不存在 会 KeyError 会给 NaN
要重复同一条 ❌ ✅(写两次即可)

单括号:既能取单个值(标量),也能做切片(连续),还能布尔过滤。

双括号:一定是“花式/列表索引”,返回 Series,顺序、重复、缺值都照你说的来。切片规则跟 Python 列表一样:start:stop:step。

一、为什么 [‘销售额’,‘利润’] 要用两个方括号?

核心原因:第一层方括号是 DataFrame 的列选择语法,第二层方括号是列表(表示选择多列),两者缺一不可。

1. 单括号 vs 双括号

写法 含义 返回类型 能否 .agg() 多列聚合
df[‘销售额’] 选「销售额」单列 Series ❌ 只能单列聚合
df[[‘销售额’,‘利润’]] 选「销售额、利润」多列 DataFrame ✅ 可多列同时聚合

2. 分步拆解

3. 易错点

  • 只写单括号 df.groupby(‘地区’)[‘销售额’,‘利润’]:Python 会把 ‘销售额’,‘利润’ 当成两个独立参数传给列选择器,触发 KeyError;

  • 正确的多列选择只能是双括号包列表:[[‘列1’,‘列2’]]。

二、reset_index() 是不是“重新按顺序建索引”?

不完全是,更精准的解释是:将分组后的索引(如「地区」列)还原为普通列,并重新生成从 0 开始的连续整数索引。

1. 不加 reset_index:分组列是索引

  • 「地区」是索引列(不是普通数据列);行索引不是连续整数,列还是多层索引。

2. 加 reset_index:索引还原为普通列

  • 「地区」从索引变回普通数据列;行索引重置为 0、1 的连续整数。

3. 关键参数

参数 作用
drop=True 不保留原索引列直接删除,只生成新整数索引(慎用,会丢分组列)
inplace=True 直接改原 DataFrame,不返回新对象:df.reset_index(inplace=True)

drop=True 的效果:分组列「地区」被直接删掉,只剩数值列。

三、核心总结

  1. 双括号 [[‘销售额’,‘利润’]]:外层是 DataFrame 列选择器,内层是列表表示选多列;单括号只能选单列,双括号才能选多列并保持 DataFrame 类型;

  2. reset_index():不是简单“重新排序索引”,而是把分组生成的自定义索引(如地区)还原为普通列,并生成从 0 开始的连续整数行索引,让结果更符合常规 DataFrame 结构、便于后续处理。