Pandas 替代应用 - 基于多列创建新列

swa*_*his 6 python numpy apply dataframe pandas

我有一个 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
Run Code Online (Sandbox Code Playgroud)

注意:原始数据框有约 400 万行和约 6 列。示例中的行数可能在 50 到 500 之间变化。我在具有 8 GB RAM 的 64 位机器上运行。

上述工作,除了它很慢(对我来说大约需要 15 秒)。我也尝试使用x.itertuples()而不是,apply在这种情况下没有太大的改进。

  1. 似乎 apply(with axis=1) 很慢,因为它没有使用矢量化操作。有什么方法可以更快地实现这一目标吗?

  2. get_new与使用条件布尔变量相比,过滤(在函数中)是否可以修改或提高效率,就像我目前所拥有的那样?

  3. 我可以以某种方式在这里使用 numpy 来加速吗?

编辑:df.sample()也很慢,我无法使用,.iloc或者.loc因为我正在进一步修改示例并且不希望这影响原始数据帧。

jpp*_*jpp 1

.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
Run Code Online (Sandbox Code Playgroud)