本文探讨如何在Python Pandas中,根据上一行值高效创建并累加新列。 问题并非简单地使用apply
函数就能解决,需要结合Pandas特性巧妙实现。
假设数据包含三列('col1', 'col2', 'col3'),目标是根据'col1'创建'col4'列:'col1'值在(3, 5)之间则'col4'为1,否则为0;且'col4'中值为1的连续数值进行累加。
直接使用循环遍历方法虽然清晰,但效率低:
values = [[5.5, 2.5, 10.0], [2.0, 4.5, 1.0], [2.5, 5.2, 8.0], [4.5, 5.8, 4.8], [4.6, 6.3, 9.6], [4.1, 6.4, 9.0], [5.1, 2.3, 11.1], [4.8, 2.3, 4.8], [4.8, 2.3, 4.8]] df = pd.DataFrame(values, columns=['col1', 'col2', 'col3'], index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'y']) col4 = [] index = 1 for one in df['col1']: if 3 < one < 5: index += 1 col4.append(index) else: index = 0 col4.append(index) df['col4'] = col4
自定义函数结合apply
方法虽然有所改进,但不够简洁高效。
更高效的方案是利用numpy.where
和cumsum
函数:
df['col4'] = pd.Series(np.where((df['col1'] > 3) & (df['col1'] < 5), 1, np.nan)).cumsum().fillna(0).astype(int)
此方法先根据条件创建包含1和NaN的Series,再用cumsum
累加,最后用fillna
将NaN替换为0。
更稳健的版本,能处理各种情况,包括中间出现不符合条件的情况:
v = df.apply(lambda x: 1 if 3 < x['col1'] < 5 else 0, axis=1) df['col4'] = (v.cumsum() - (v != v.shift()).cumsum() + (v != v.shift()) * v).fillna(0).astype(int)
此方法通过更复杂的逻辑处理中间不满足条件的情况,确保累加结果准确。 对比这些方法,选择合适的方法能显著提升代码效率和可读性。