【问题标题】:Pandas alternative to apply - to create new column based on multiple columnsPandas 替代应用 - 基于多列创建新列
【发布时间】:2018-08-09 17:33:13
【问题描述】:

我有一个 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,在这种情况下并没有太大的改进。

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

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

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

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

【问题讨论】:

  • dask 呢?
  • @Pierluigi - 在查看其他库之前,我希望在 Pandas 或 Numpy 中已经有更好(和有效)的方法来执行此操作。但感谢您指出这一点。一定会看看的。
  • 我创建了 tabel,作为 pandas 的简化版本。它完全基于 numpy,但抽象出处理多种数据类型的细节。并且 numpy 在像你这样的获取/设置场景中通常更快。 pypi.org/project/tabel

标签: python pandas numpy dataframe apply


【解决方案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

【讨论】:

  • 试过了,但不幸的是我的情况没有改善。它仍然需要相同的时间。
  • @swathis。那很有意思。您能否复制粘贴我的代码并确认这是否与您的数据与我的数据不同有关?
  • 您的代码块有效。使用 .loc 也可以让我加速约 50 毫秒。我的问题可能是因为我根据其他一些条件在函数中多次进行索引?另外,df.sample 对我来说真的很慢。
  • @swathis,是的,也许这甚至不是瓶颈。我建议将您的代码拆分为许多小函数,并通过分析器运行您的代码以查明性能下降的原因。您可以使用cProfile.run 进行分析,并按功能提供输出。
  • 使用 cProfile 很有用。 PyCharm 甚至还有一个插件让它变得更容易。谢谢:-)
猜你喜欢
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-24
  • 2020-11-09
  • 1970-01-01
相关资源
最近更新 更多