Pandas分组后将列表列拆分至现有DataFrame的实现方法
直接在Pandas Groupby后将列表列拆分为多列并添加到现有DataFrame
我明白你想要的是在生成g12的过程中,直接把自定义聚合函数返回的列表拆成独立列,而不是先存成一个列表列再通过新DataFrame合并。这里有两种简洁的实现方式,完全不需要额外的合并步骤:
方法1:修改自定义函数返回Series(推荐)
让你的聚合函数直接返回带列名的pd.Series,这样分组聚合后会自动生成多列,你可以直接合并到原DataFrame中:
import numpy as np import pandas as pd # 数据生成 df = pd.DataFrame(data= {'ticker': ['AAPL','AAPL','AAPL','IBM','IBM','IBM'], 'side': ['B','B','S','S','S','B'], 'size': [100, 200, 300, 400, 100, 200], 'price': [10.12, 10.13, 10.14, 20.3, 20.2, 20.1]}) # 修改函数,返回带索引的Series,指定拆分后的列名 def fnpercentiles(a): return pd.Series( [np.percentile(a, 25), np.percentile(a, 75)], index=['price_p25', 'price_p75'] # 自定义列名,清晰直观 ) # 分组操作 g = df.groupby(['ticker', 'side']) g12 = pd.DataFrame() g12['price/mean'] = g['size'].mean() / g['price'].sum() # 直接将聚合后的多列合并到g12 g12 = pd.concat([g12, g['price'].agg(fnpercentiles)], axis=1)
这样操作后,g12会直接包含price/mean、price_p25和price_p75三列,完全不需要处理列表转DataFrame的步骤。
方法2:保持原函数不变,用apply(pd.Series)展开列表
如果你不想修改原有的fnpercentiles函数,可以直接对聚合后的列表列使用apply(pd.Series),将其拆分为多列并直接赋值给g12的新列:
import numpy as np import pandas as pd # 数据生成 df = pd.DataFrame(data= {'ticker': ['AAPL','AAPL','AAPL','IBM','IBM','IBM'], 'side': ['B','B','S','S','S','B'], 'size': [100, 200, 300, 400, 100, 200], 'price': [10.12, 10.13, 10.14, 20.3, 20.2, 20.1]}) # 保持原函数不变 def fnpercentiles(a): return [np.percentile(a, 25), np.percentile(a, 75)] # 分组操作 g = df.groupby(['ticker', 'side']) g12 = pd.DataFrame() g12['price/mean'] = g['size'].mean() / g['price'].sum() # 直接将列表列拆分为多列并赋值给g12 g12[['price_p25', 'price_p75']] = g['price'].agg(fnpercentiles).apply(pd.Series)
为什么你之前的尝试无效?
你之前用g['price'].agg([fnpercentiles]).tolist()[0]的问题在于,tolist()[0]只会提取第一个分组的列表值,而不是每个分组对应的列表,导致赋值时长度不匹配。而apply(pd.Series)会遍历每个分组的列表,将其转换为对应行的列值,完美匹配原DataFrame的索引。
执行上述任意一种方法后,g12的结果如下:
price/mean price_p25 price_p75 ticker side AAPL B 0.099256 10.125 10.125 S 0.098907 10.140 10.140 IBM B 0.049751 20.100 20.100 S 0.074627 20.250 20.250
内容的提问来源于stack exchange,提问作者user13874
相关产品推荐
相关产品推荐

