我有一个 Pandas 数据框,我想根据其他列的值添加一个新列。下面是一个说明我的用例的最小示例。
df = pd.DataFrame([[4,5,19],[1,2,0],[2,5,9],[8,2,5]], columns=['a','b','c'])
df
a b c
---------------
0 4 5 19
1 1 2 0
2 2 5 9
3 8 2 5
x = df.sample(n=2)
x
a b c
---------------
3 8 2 5
1 1 2 0
def get_new(row):
a, b, c = row
return random.choice(df[(df['a'] != a) & (df['b'] == b) & (df['c'] != c)]['c'].values)
y = x.apply(lambda row: get_new(row), axis=1)
x['new'] = y
x
a b c new
--------------------
3 8 2 5 0
1 1 2 0 5
注意:原始数据框有约 400 万行和约 6 列。示例中的行数可能在 50 到 500 之间变化。我在具有 8 GB RAM 的 64 位计算机上运行。
上面的工作,除了它很慢(对我来说大约需要 15 秒)。我还尝试使用 x.itertuples()
而不是 apply
并且在这种情况下没有太大的改进。
apply(with axis=1) 似乎很慢,因为它没有使用矢量化操作。有什么方法可以更快地实现这一目标吗?
过滤(在
get_new
函数中)是否可以修改或比使用条件 bool 变量更有效,就像我目前所做的那样?我可以在这里以某种方式使用 numpy 来提高速度吗?
编辑:df.sample()
也很慢,我无法使用 .iloc
或 .loc
,因为我正在进一步修改采样并且不希望这影响原始数据帧。
最佳答案
我看到通过使用 .loc
而不是链式索引可以合理地提高性能:
import random, pandas as pd, numpy as np
df = pd.DataFrame([[4,5,19],[1,2,0],[2,5,9],[8,2,5]], columns=['a','b','c'])
df = pd.concat([df]*1000000)
x = df.sample(n=2)
def get_new(row):
a, b, c = row
return random.choice(df[(df['a'] != a) & (df['b'] == b) & (df['c'] != c)]['c'].values)
def get_new2(row):
a, b, c = row
return random.choice(df.loc[(df['a'] != a) & (df['b'] == b) & (df['c'] != c), 'c'].values)
%timeit x.apply(lambda row: get_new(row), axis=1) # 159ms
%timeit x.apply(lambda row: get_new2(row), axis=1) # 119ms
关于python - 应用的 Pandas 替代方案 - 基于多列创建新列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49053252/