【问题标题】:Pandas: for each row in a DataFrame, count the number of rows matching a conditionPandas:对于 DataFrame 中的每一行,计算匹配条件的行数
【发布时间】:2017-06-10 23:41:04
【问题描述】:

我有一个 DataFrame,我想为每一行计算有多少其他行与给定条件匹配(例如,C 列中的值小于该行的值的行数)。遍历每一行太慢(我有大约 1B 行),尤其是当列 dtype 是日期时间时,但这是可以在带有标记为 C 的列的 DataFrame df 上运行的方式:

df['newcol'] = 0
for row in df.itertuples():
    df.loc[row.Index, 'newcol'] = len(df[df.C < row.C])

有没有办法将其矢量化?

谢谢!

【问题讨论】:

  • 循环缓慢的主要原因似乎是因为我正在更新我正在迭代的同一个表。将结果存储在 dict 中,然后将其与原始数据帧合并,大大提高了性能。
  • 请用该解决方案回答您自己的问题,以帮助未来的读者。

标签: python pandas dataframe


【解决方案1】:

准备工作:

import numpy as np
import pandas as pd
count = 5000

np.random.seed(100)
data = np.random.randint(100, size=count)

df = pd.DataFrame({'Col': list('ABCDE') * (count/5),
                   'Val': data})

建议:

u, c = np.unique(data, return_counts=True)
values = np.cumsum(c)
dictionary = dict(zip(u[1:], values[:-1]))
dictionary[u[0]] = 0
df['newcol'] = [dictionary[x] for x in data]

它与您的示例完全相同。 如果没有帮助。写出更详细的问题。

建议:

page 上的 numba 提供 Pandas 矢量化和 jit 编译。

如果您使用一维数组 - 使用 numpy.在许多情况下,它的工作速度更快。比较一下:

熊猫

%timeit df['newcol2'] = df.apply(lambda x: sum(df['Val'] < x.Val), axis=1)

1 次循环,最佳 3 次:每个循环 51.1 秒 204.34800005

Numpy

%timeit df['newcol3'] = [np.sum(data<x) for x in data]

10 个循环,3 个循环中的最佳:每个循环 61.3 毫秒 2.5490000248

使用 numpy.sum 代替 sum!

【讨论】:

    【解决方案2】:

    考虑使用 lambda 表达式 pandas.DataFrame.apply 来计算符合您条件的行数。诚然,apply 是一个循环,运行大约 10 亿行可能需要一些时间来处理。

    import numpy as np
    import pandas as pd
    
    np.random.seed(161)
    
    df = pd.DataFrame({'Col': list('ABCDE') * 3,
                       'Val': np.random.randint(100, size=15)})
    
    df['newcol'] = df.apply(lambda x: sum(df['Val'] < x.Val), axis=1)
    
    #    Col  Val  Count
    # 0    A   78     13
    # 1    B   11      2
    # 2    C   51      8
    # 3    D   31      5
    # 4    E   29      4
    # 5    A   99     14
    # 6    B   65     10
    # 7    C   16      3
    # 8    D   43      7
    # 9    E   10      1
    # 10   A   67     11
    # 11   B   36      6
    # 12   C    1      0
    # 13   D   73     12
    # 14   E   64      9
    

    【讨论】:

    • 谢谢! Apply 仍然太慢,还有一个问题是它不会显示进度(使用循环时,我会不时打印出进度)。我正在寻找的是对过程进行矢量化的可能性(不确定是否有可能没有一些技巧)。
    猜你喜欢
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 2022-01-24
    相关资源
    最近更新 更多