如何为Pandas DataFrame添加分组前序颜色列表新列?
解决Pandas分组生成历史值列表的问题
需求:给Pandas DataFrame新增colors列,该列值为同一year和item分组中当前行之前所有行的color值组成的列表。
示例输入
import pandas as pd df = pd.DataFrame({ 'id': [0, 1, 2, 3], 'item': ['shirt', 'shoes', 'shirt', 'shirt'], 'year': [2021, 2022, 2021, 2021], 'color': ['yellow', 'pink', 'green', 'black'] })
原始数据展示:
id item year color 0 shirt 2021 yellow 1 shoes 2022 pink 2 shirt 2021 green 3 shirt 2021 black
期望输出
注:原示例中第1行的[pink]不符合逻辑(当前行是分组内第一行,无前置数据),修正后的正确期望输出为:
id item year color colors 0 shirt 2021 yellow [] 1 shoes 2022 pink [] 2 shirt 2021 green [yellow] 3 shirt 2021 black [yellow, green]
你的代码问题分析
- 第一段代码
apply(list()):错误地直接执行了list(),应该传递函数对象而非执行结果。就算改成lambda x: list(x),也会把整个分组的color列表赋值给每一行,无法实现“当前行之前”的要求。 - 第二段代码:存在语法错误(缺少闭合括号),且
x.shift()会将分组内的color整体下移,转成列表后每行都是整个移位后的数组,不是累积的历史列表。
正确解决方案
方案1:自定义遍历函数(直观易懂)
def build_history(col): history = [] result = [] for val in col: # 先把当前历史(之前的元素)加入结果 result.append(history.copy()) # 再把当前值加入历史 history.append(val) return result # 分组处理后展开对齐原数据 df['colors'] = df.groupby(['year', 'item'])['color'].apply(build_history).explode()
方案2:用expanding窗口(更简洁)
df['colors'] = df.groupby(['year', 'item'])['color'].expanding().apply( lambda x: list(x[:-1]) if len(x) > 1 else [] ).reset_index(level=0, drop=True)
expanding()会生成包含当前行及之前所有行的窗口,x[:-1]取窗口中除当前行外的所有元素,第一行窗口只有自己,返回空列表。reset_index用来移除分组索引,对齐原DataFrame的行。
最终结果
运行上述代码后,df将符合预期:
id item year color colors 0 0 shirt 2021 yellow [] 1 1 shoes 2022 pink [] 2 2 shirt 2021 green [yellow] 3 3 shirt 2021 black [yellow, green]
内容的提问来源于stack exchange,提问作者agent_anon
相关产品推荐
相关产品推荐

