如何用更优雅的方式通过DataFrame.apply生成新DataFrame?
优化DataFrame apply后拼接的优雅写法
现有如下函数,传入DataFrame的一行后返回一个小DataFrame:
def func(row): if row['col1'] == 1: return pd.DataFrame({'a': [1], 'b': [11]}) else: return pd.DataFrame({'a': [-1, -2], 'b': [-11, -22]})
给定初始DataFrame:
df = pd.DataFrame({'col1': [1,2,3], 'col2': [11,22,33]})
期望通过apply该函数得到如下结果:
pd.DataFrame({ 'a': [1,-1,-2,-1,-2], 'b': [11,-11,-22,-11,-22] })
当前实现方式为:
pd.concat([mini[1] for mini in df.apply(func, axis=1).iteritems()])
该写法不够优雅,以下是两种更优的实现方式:
方法1:简化concat调用
df.apply(func, axis=1)返回的是一个Series,每个元素是小DataFrame,直接将这个Series传入pd.concat即可,无需手动遍历:
pd.concat(df.apply(func, axis=1), ignore_index=True)
添加ignore_index=True可以重置结果的索引,与期望输出的索引保持一致。
方法2:用explode替代apply(性能更优)
如果函数逻辑可以拆分,先通过映射生成包含列表的列,再用explode展开,这种方式避免了频繁创建小DataFrame,在数据量大时性能更出色:
# 映射生成对应列表 df['a'] = df['col1'].map(lambda x: [1] if x == 1 else [-1, -2]) df['b'] = df['col1'].map(lambda x: [11] if x == 1 else [-11, -22]) # 展开列表得到结果 result = df[['a', 'b']].explode(['a', 'b'], ignore_index=True)
内容的提问来源于stack exchange,提问作者Ottpocket
相关产品推荐
相关产品推荐

