在Python中使用Lambda过滤数据帧

在Python中使用Lambda过滤数据帧,python,pandas,lambda,Python,Pandas,Lambda,我在python中有两个数据帧:df和list: data1 = [[0, ("a","b")], [1, ("d","e")], [2, ("a","e")],[3,("f", "g")],[4,("c","h")]] df = pd.DataFrame(data1, columns = ['Row', 'Letters']) data2 = [[0,"a"],[1,"b"],[2,"c"]] list = pd.DataFrame(data2, columns = ['Row', 'Lett

我在python中有两个数据帧:df和list:

data1 = [[0, ("a","b")], [1, ("d","e")], [2, ("a","e")],[3,("f", "g")],[4,("c","h")]]
df = pd.DataFrame(data1, columns = ['Row', 'Letters'])
data2 = [[0,"a"],[1,"b"],[2,"c"]]
list = pd.DataFrame(data2, columns = ['Row', 'Letters'])
我现在只想过滤df中的行,这样df['Letters']中的任何项目都可以在列表['Letters'中找到

Any函数对单个行运行良好:

any(item in df["Letters"][1] for item in list['Letters'])
any(item in df["Letters"][2] for item in list['Letters'])
正确地分别返回False和True

现在如何过滤整个数据帧

我尝试了以下代码:

new_df = df[df.apply(lambda x : any(item in x["Letters"] for item in list), axis=1)]
当我只想返回第0、2和4行时,它返回一个空数据帧


任何帮助都将不胜感激。

您可以将数据帧构造函数与堆栈一起使用,然后将series.isin与任何for level=0进行比较

注意:我已经更改了将列表保存为list_uu的列表变量,因为您不应该拥有与内置函数相同的变量名

更大数据帧的基准测试:

m = pd.concat([df]*10000,ignore_index=True)
%%timeit
m[pd.DataFrame(m['Letters'].tolist()).stack().isin(list_['Letters']).any(level=0)]
#25.3 ms ± 1.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
m.loc[~m['Letters'].apply(lambda x: set(x).isdisjoint(set(list_['Letters'])))]
#644 ms ± 8.38 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
m[m.Letters.apply(lambda x : any(item in list_.Letters.to_numpy().tolist() for item in x))]
#665 ms ± 13.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
m.loc[m['Letters'].apply(lambda x: len(set(x).intersection(set(list_['Letters']))) > 0)]
#707 ms ± 56.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

您可以将dataframe构造函数与stack一起使用,然后使用series.isin与级别为0的任意值进行比较

注意:我已经更改了将列表保存为list_uu的列表变量,因为您不应该拥有与内置函数相同的变量名

更大数据帧的基准测试:

m = pd.concat([df]*10000,ignore_index=True)
%%timeit
m[pd.DataFrame(m['Letters'].tolist()).stack().isin(list_['Letters']).any(level=0)]
#25.3 ms ± 1.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
m.loc[~m['Letters'].apply(lambda x: set(x).isdisjoint(set(list_['Letters'])))]
#644 ms ± 8.38 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
m[m.Letters.apply(lambda x : any(item in list_.Letters.to_numpy().tolist() for item in x))]
#665 ms ± 13.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
m.loc[m['Letters'].apply(lambda x: len(set(x).intersection(set(list_['Letters']))) > 0)]
#707 ms ± 56.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

下面是一种使用集合交集的方法,我们将每个元组转换为集合,并检查集合交集的len是否大于1:

您还可以使用来获得结果

df.loc[~df['Letters'].apply(lambda x: set(x).isdisjoint(set(lst['Letters'])))]

下面是一种使用集合交集的方法,我们将每个元组转换为集合,并检查集合交集的len是否大于1:

您还可以使用来获得结果

df.loc[~df['Letters'].apply(lambda x: set(x).isdisjoint(set(lst['Letters'])))]
您可以这样做:

data1 = [[0, ("a","b")], [1, ("d","e")], [2, ("a","e")],[3,("f", "g")],[4,("c","h")]]
df = pd.DataFrame(data1, columns = ['Row', 'Letters'])
data2 = [[0,"a"],[1,"b"],[2,"c"]]
list1 = pd.DataFrame(data2, columns = ['Row', 'Letters'])

new_df = df[df.Letters.apply(lambda x : any(item in list1.Letters.to_numpy().tolist() for item in x))]
print(new_df)
输出

您可以这样做:

data1 = [[0, ("a","b")], [1, ("d","e")], [2, ("a","e")],[3,("f", "g")],[4,("c","h")]]
df = pd.DataFrame(data1, columns = ['Row', 'Letters'])
data2 = [[0,"a"],[1,"b"],[2,"c"]]
list1 = pd.DataFrame(data2, columns = ['Row', 'Letters'])

new_df = df[df.Letters.apply(lambda x : any(item in list1.Letters.to_numpy().tolist() for item in x))]
print(new_df)
输出


不要使用列表作为变量名。不要使用列表作为变量名。这很有效,非常感谢。不会想到的。这很有效,非常感谢。不会想到的。太棒了!这也很有效。另一个有趣的方法。我很感激花时间看代码。太棒了!这也很有效。另一个有趣的方法。我很感谢你花了这么多时间看代码。非常感谢。我尝试了这个,但我得到了错误:AttributeError:“Series”对象没有属性“to_numpy”。也许我在更新方面落后了?@SM_Erd可能是的,试试.values,而不是to_numpy,那样做了。工作得很有魅力。再次感谢,非常感谢。我尝试了这个,但我得到了错误:AttributeError:“Series”对象没有属性“to_numpy”。也许我在更新方面落后了?@SM_Erd可能是的,试试.values,而不是to_numpy,那样做了。工作得很有魅力。再次感谢。
   Row Letters
0    0  (a, b)
2    2  (a, e)
4    4  (c, h)