【问题标题】:Pandas - Searching Column of Data Frame from List EfficientlyPandas - 有效地从列表中搜索数据框的列
【发布时间】:2017-08-31 17:29:26
【问题描述】:

我正在尝试找出在 Pandas 中使用其他值的列表(数据框)搜索数据框的最有效方法,而无需使用蛮力方法。有没有办法对其进行矢量化?我知道我可以循环列表(或数据框)的每个元素并使用 loc 方法提取数据,但希望更快。我有一个包含 100 万行的数据框,我需要在其中搜索以提取 600,000 行的索引。

例子:

import pandas as pd
import numpy as np

df = pd.DataFrame({'WholeList': np.round(1000000*(np.random.rand(1000000)),0)})
df2 = pd.DataFrame({'ThingsToFind': np.arange(50000)+50000})
df.loc[1:10,:]
#Edited, now that I think about it, the 'arange' method would have been better to populate the arrays.

我想要最有效的方法来获取 df2 在 df 中的索引,它存在于 df 中。

谢谢!

【问题讨论】:

  • 所以,输出的长度是1 million?
  • 另外,如果df中的df2不匹配,输出什么?
  • 您是否尝试过使用 isin() DataFrame 方法?
  • 现在我想,无论哪种长度都可以。
  • @Andrew L 我主要尝试通过 loc 方法进行暴力破解,但我认为这是最耗时的方法。

标签: python performance pandas numpy processing-efficiency


【解决方案1】:

Pandas 数据帧有一个 isin() 方法,效果非常好:

df[df.WholeList.isin(df2.ThingsToFind)]

它在我的 MBP 上似乎表现不错:

CPU times: user 3 µs, sys: 5 µs, total: 8 µs
Wall time: 11 µs

【讨论】:

  • 但是,我们需要得到匹配对应的df2的索引,对吧?
  • 我想我不明白你的意思。 df2 中没有明确的索引。您在寻找行号索引吗?嗯,就是df[df.WholeList.isin(df2.ThingsToFind)].index
  • @Divaker 我会说,只要我可以轻松地在 WholeList(我们的函数将提供的索引)=ThingsToFind 的位置获得它,那么我会很高兴。我正在考虑一个我喜欢的 MATLAB 命令并尝试在 Python 中实现它。对不起,如果这是一个新手问题,但我只在语言的第 2 个月。
  • 我试试看。谢谢!
【解决方案2】:

这是np.searchsorted 的一种方法,因为似乎第二个数据框的元素已排序且唯一 -

def find_index(a,b, invalid_specifier = -1):
    idx = np.searchsorted(b,a)
    idx[idx==b.size] = 0
    idx[b[idx] != a] = invalid_specifier
    return idx

def process_dfs(df, df2):
    a = df.WholeList.values.ravel()
    b = df2.ThingsToFind.values.ravel()
    return find_index(a,b, invalid_specifier=-1)

在数组上运行示例 -

In [200]: a
Out[200]: array([ 3,  5,  8,  4,  3,  2,  5,  2, 12,  6,  3,  7])

In [201]: b
Out[201]: array([2, 3, 5, 6, 7, 8, 9])

In [202]: find_index(a,b, invalid_specifier=-1)
Out[202]: array([ 1,  2,  5, -1,  1,  0,  2,  0, -1,  3,  1,  4])

在数据帧上运行示例 -

In [188]: df
Out[188]: 
    WholeList
0           3
1           5
2           8
3           4
4           3
5           2
6           5
7           2
8          12
9           6
10          3
11          7

In [189]: df2
Out[189]: 
   ThingsToFind
0             2
1             3
2             5
3             6
4             7
5             8
6             9

In [190]: process_dfs(df, df2)
Out[190]: array([ 1,  2,  5, -1,  1,  0,  2,  0, -1,  3,  1,  4])

【讨论】:

  • 谢谢!这是一种有趣的方法。
  • 这很好用。 isin() 没有给我想要的东西,但这很棒。谢谢!
【解决方案3】:

我同意@JDLong - IMO Pandas 非常快:

In [49]: %timeit df[df.WholeList.isin(df2.ThingsToFind)]
1 loop, best of 3: 819 ms per loop

In [50]: %timeit df.loc[df.WholeList.isin(df2.ThingsToFind)]
1 loop, best of 3: 814 ms per loop

In [51]: %timeit df.query("WholeList in @df2.ThingsToFind")
1 loop, best of 3: 837 ms per loop

【讨论】:

  • 谢谢。我认为除了蛮力+ loc方法之外还有其他方法。我试试看。
猜你喜欢
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-29
  • 2017-07-24
  • 2020-06-20
  • 2020-05-13
相关资源
最近更新 更多