两列匹配列表的两个元素

时间:2019-12-18 10:48:33

标签: python pandas numpy

我有一个包含两列的数据框:

import pandas as pd
data={'A':['x','y','z','r','x','z'],'B':[1,2,3,4,1,7]}
df=pd.DataFrame(data)

那让我:

A | B
x | 1
y | 2
z | 3
r | 4
x | 1
z | 7

然后是一个包含两个元素的列表的 n 列表:

list_of_lists=[['x',1],['x',4],['z',3],['y',1]]

我想确定每个子列表的 1st 元素是否与 A 列匹配,而第二个元素与 B 列匹配,像这样:

A | B | Match
x | 1 | True
y | 2 | False
z | 3 | True
r | 4 | False
x | 1 | True
z | 7 | False

应该为列表的每个元素创建两个列表,并在两个条件下都执行类似np.where的操作,但是必须有一种更简洁的方法。

5 个答案:

答案 0 :(得分:3)

您可以尝试:

>>> df2 = pd.DataFrame(data = list_of_lists, columns = df.columns)
# less readable but slightly faster
# df2 = pd.DataFrame(dict(zip(['A','B'],zip(*list_of_lists))))
>>> df['Match'] = np.isin(df, df2).all(1)
>>> df
   A  B  Match
0  x  1   True
1  y  2  False
2  z  3   True
3  r  4  False
4  x  1   True
5  z  7  False

答案 1 :(得分:3)

DataFrame.merge与辅助函数DataFrame一起使用,并使用左联接和indicator = True参数,然后比较值both

df1 = df.merge(pd.DataFrame(list_of_lists, columns=df.columns), how='left', indicator=True)

df['Match'] = df1['_merge'].eq('both')
print (df)
   A  B  Match
0  x  1   True
1  y  2  False
2  z  3   True
3  r  4  False
4  x  1   True
5  z  7  False

答案 2 :(得分:2)

您可以使用apply方法:

df['Match'] = df.apply(lambda r: r.tolist() in list_of_lists, axis=1)
df
   A  B   Match
0  x  1   True
1  y  2  False
2  z  3   True
3  r  4  False
4  x  1   True
5  z  7  False

要了解这一点,您可以执行一个中间步骤并检查结果:

df['temp'] = df.apply(lambda r: r.tolist(), axis=1)
df

   A  B    temp
0  x  1  [x, 1]
1  y  2  [y, 2]
2  z  3  [z, 3]
3  r  4  [r, 4]
4  x  1  [x, 1]
5  z  7  [z, 7]

然后

df['Match'] = df.apply(lambda r: r['temp'] in list_of_lists, axis=1)
df
   A  B    temp  Match
0  x  1  [x, 1]   True
1  y  2  [y, 2]  False
2  z  3  [z, 3]   True
3  r  4  [r, 4]  False
4  x  1  [x, 1]   True
5  z  7  [z, 7]  False

答案 3 :(得分:2)

尝试一下:

 df.apply(list, axis=1).apply(lambda x: True if x in list_of_lists else False) 

0     True
1    False
2     True
3    False
4     True
5    False
dtype: bool

答案 4 :(得分:1)

我的方法:

  • 创建匹配的数据框
  • 合并原始数据
  • 不匹配项将丢失,因此我们需要为缺失值填写False

我相信,即使匹配列表很大,这种方法也可以扩展(因此,逐个元素apply可能很耗时,但是左联接是可以管理的)

# data
data='''A|B
x|1
y|2
z|3
r|4
x|1
z|7'''
with open("a.txt", 'w') as f:
    print(data, file=f)
df1 = pd.read_csv("a.txt", sep="|")
list_of_lists=[['x',1],['x',4],['z',3],['y',1]]


# First, create a data frame of matches
matches = pd.DataFrame(list_of_lists, columns=['A', 'B'])
matches['Match'] = True

# left join with the original data, non-matches will be missing, so fill with False
df1.merge(matches, on=['A', 'B'], how='left').fillna(False)

输出:

   A  B  Match
0  x  1   True
1  y  2  False
2  z  3   True
3  r  4  False
4  x  1   True
5  z  7  False
相关问题