Pandas:检查是否存在具有特定值的行

75

我有一个二维(或更多)的Pandas DataFrame,就像这样:

>>> import pandas as pd
>>> df = pd.DataFrame([[0,1],[2,3],[4,5]], columns=['A', 'B'])
>>> df
   A  B
0  0  1
1  2  3
2  4  5

现在假设我有一个numpy数组,如np.array([2,3]),并且想要检查是否存在与数组内容匹配的任何行在df中。这里答案显然是真的,但例如np.array([1,2])应该返回false,因为没有一行同时包含列A中的1和列B中的2。

当然,这很简单,但现在不太清楚。


有一行和一列都有数字1、2,你所说的“不存在”是什么意思? - John Ruddell
你尝试过类似 df.isin([1,2]) 的东西吗?它会输出你需要找到完全匹配和部分匹配的行的布尔值。 - ZJS
@JohnRuddell:但是没有一行包含列A中的1和列B中的2。我正在寻找类似于SQL中WHERE子句的语义。 - Robin
7个回答

104

原来这很容易,以下操作可以达到目的:

>>> ((df['A'] == 2) & (df['B'] == 3)).any()
True
>>> ((df['A'] == 1) & (df['B'] == 2)).any()
False

或许有人能提出更好的解决方案,允许直接传入数组和要匹配的列的列表。

请注意,围绕 df['A'] == 2 的括号是必需的,因为 & 运算符与 == 运算符的优先级一样强。


9
这个解决方案本身不错,但是当数据量很大时,性能确实非常差。试试这样做:df.loc[(df['A'] == 2) & (df['B'] == 3)]。我在一个数据集上测试了一下,我的解决方案的性能为918毫秒,而那个方案需要2.12秒。 - Navy
3
@Navy 你的解决方案无法评估为True/False,你需要对结果DF进行一些操作。 - fgblomqvist
@Navy 如果有一种方法可以评估为布尔值,我很想看到它作为答案。 - Xgongiveittoya
2
@fgblomqvist @Xgongiveittoya 添加一个any()和一个all()调用以接收布尔值。像这样:df.loc[(df['A'] == 2) & (df['B'] == 3)].any().all() - Jan Willem

35

更简单的方法是:

a = np.array([2,3])
(df == a).all(1).any()

这仅在维度相同时才有效,对吧?也就是说,如果匹配应基于五列DataFrame的前两列,那么这样会失败吗? - Robin
5
那很简单。用 df[df.columns[:2]] 替换掉 df - acushner
以防您在不同的数据结构上尝试,请同时尝试(df == a).all(0).any() - questionto42

14

如果您还想返回匹配发生的索引:

index_list = df[(df['A'] == 2)&(df['B'] == 3)].index.tolist()

1
正是我所需要的,谢谢。 - cestpasmoi

2

查找其中某一列等于特定值的行:

df[df['column name'] == value]

要查找多个列等于不同值的行,请注意内部括号():

df[(df["Col1"] == Value1 & df["Col2"] == Value2 & ....)]

虽然这是一个正确的答案,但为您的代码添加上下文将使其他人更容易理解!还要注意OP可能正在考虑多列和值。 - moeabdol

1

使用字典的简单解决方案

def check_existance(dict_of_values, df):
    v = df.iloc[:, 0] == df.iloc[:, 0]
    for key, value in dict_of_values.items():
        v &= (df[key] == value)
    return v.any()

import pandas as pd
df = pd.DataFrame([[0,1],[2,3],[4,5]], columns=['A', 'B'])

this_row_exists = {'A':2, 'B':3}
check_existance(this_row_exists, df)
# True

this_row_does_not_exist = {'A':2, 'B':5}
check_existance(this_row_does_not_exist, df)
# False

0

一个适用于大型数据框的答案,因此您不需要手动检查每个列:

import pandas as pd
import numpy as np

#define variables
df = pd.DataFrame([[0,1],[2,3],[4,5]], columns=['A', 'B'])
a = np.array([2,3])

def check_if_np_array_is_in_df(df, a):
    # transform a into a dataframe
    da = pd.DataFrame(np.expand_dims(a,axis=0), columns=['A','B'])

    # drop duplicates from df
    ddf=df.drop_duplicates()

    result = pd.concat([ddf,da]).shape[0] - pd.concat([ddf,da]).drop_duplicates().shape[0]
    return result

print(check_if_np_array_is_in_df(df, a))
print(check_if_np_array_is_in_df(df, [1,3]))


0
如果您想返回匹配发生的行:
resulting_row = df[(df['A'] == 2)&(df['B'] == 3)].values

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接