在pandas DataFrame中有效地搜索列表值的组合

时间:2018-12-24 15:30:26

标签: python pandas list dataframe combinations

我正在遍历多个熊猫数据帧,在每次迭代中我提取2个列表。 然后,对于每个2个列表组合,我需要在另一个数据框中找到该行,其中出现2个列表中所有值的每种组合。

简化示例:

df如下所示(任何D_val P_val只能出现一次):

D_val | P_val | D_PCode  
A     | 1     | 25  
D     | 1     | 21  
C     | 2     | 32  
B     | 4     | 35  
D     | 2     | 126  
B     | 1     | 3  
C     | 1     | 312  

对于具有以下列表的单次迭代-

list1 = [1,2]  
list2 = [A,B,C]  

我希望获得以下列表:
    [25,3,312,32]

说明:

for [A,1] - 25  
for [A,2] - nothing  
For [B,1] - 3  

我使用嵌套循环来实现它,但是由于多次迭代,大型数据帧和长列表,它花费的时间太长。

任何建议如何有效实施?如果需要,我很高兴使用其他数据结构。

3 个答案:

答案 0 :(得分:2)

您可以使用itertools.product生成所有可能的值,然后使用isin

packages.config

输出

from itertools import product

import pandas as pd

data = [['A', 1, 25],
        ['D', 1, 21],
        ['C', 2, 32],
        ['B', 4, 35],
        ['D', 2, 126],
        ['B', 1, 3],
        ['C', 1, 312]]

df = pd.DataFrame(data=data, columns=['D_val', 'P_val', 'D_PCode'])

list1 = [1, 2]
list2 = ['A', 'B', 'C']
lookup = set(product(list2, list1))

mask = df[['D_val', 'P_val']].apply(tuple, axis=1).isin(lookup)
result = df[mask].D_PCode

print(result)

或者直接在两个列上直接使用isin,例如:

0     25
2     32
5      3
6    312
Name: D_PCode, dtype: int64

输出

list1 = [1, 2]
list2 = ['A', 'B', 'C']

result = df[df.D_val.isin(list2) & df.P_val.isin(list1)].D_PCode
print(result)

答案 1 :(得分:2)

我们仅两次使用isin

df1=df.loc[df.D_val.isin(list2)&df.P_val.isin(list1)]
df1
Out[211]: 
  D_val  P_val  D_PCode
0     A      1       25
2     C      2       32
5     B      1        3
6     C      1      312

答案 2 :(得分:1)

这是一个MultiIndex问题,最好通过reindex解决。

df = df.set_index(['D_val', 'P_val'])
idx = pd.MultiIndex.from_product([list2, list1])

df.reindex(idx)

     D_PCode
A 1     25.0
  2      NaN
B 1      3.0
  2      NaN
C 1    312.0
  2     32.0

如果要使用匹配项的字典,请使用reindex + Series.to_dict

df.reindex(idx).D_PCode.to_dict()

{('A', 1): 25.0,
 ('A', 2): nan,
 ('B', 1): 3.0,
 ('B', 2): nan,
 ('C', 1): 312.0,
 ('C', 2): 32.0}

如果只希望存在的行,请使用intersection来有效地计算相交的索引:

df.loc[df.index.intersection(idx)]

     D_PCode
A 1       25
B 1        3
C 1      312
  2       32