将isin()用于具有列表值的列

时间:2019-06-15 13:17:03

标签: python pandas

我有两个数据框。数据框A具有由list个ID值(命名项)组成的列。数据框B包含int个ID值(名为ID)列。

数据框A:

date       |    items
2019-06-05 | [121, 123, 124]
2019-06-06 | [109, 125]
2019-06-07 | [108, 126]

数据框B:

name  | id
item1 | 121
item2 | 122
item3 | 123
item4 | 124
item5 | 125
item6 | 126

我想过滤数据帧A,并仅将数据行B的items列中所有id的值都存在的行保留。

根据以上示例,结果应为:

数据框C:

date       |    items
2019-06-05 | [121, 123, 124]

(因为数据框B没有id == 108和id == 109的行)

如果itemsint列,则可以使用:

dataframe_a[dataframe_a.items.isin(dataframe_b.id)]

如何在list列中实现这一目标?

3 个答案:

答案 0 :(得分:3)

您可以定义自定义函数,以搜索列表的所有元素是否在B数据框中,并将其与apply一起使用。

这里df1是您的数据框架A,df2是您的数据框架B:

sel = df1.apply(lambda x : all([i in df2['id'].unique() for i in x['items']]), axis=1)
finaldf = df1.loc[sel]

finaldf是:

         date            items
0  2019-06-05  [121, 123, 124]

答案 1 :(得分:3)

我们可以使用issubset

l=[set(x).issubset(dfb.id.tolist())for x in df['items']]
Out[64]: [True, False, False]

然后

df=df[l]

答案 2 :(得分:2)

Valentino击败了我,所以想法是一样的

dataframe_a[dataframe_a['items'].apply(lambda lst: all(x in dataframe_b.id.values for x in lst))]

以下是您目前使用的方法的另外几句话:

  • pd.Series.isin检查每个元素(在您的情况下为每个列表)是否以其他顺序整体存在。虽然您的列表是无序列表,但是对于一系列元组而言,顺序很重要,并且检查整体是否存在是正确/预期的行为。
  • 另一个问题是调用isin(dataframe_b.id),与调用isin(dataframe_b.id.index)相同。 pd.Series就像字典,in / contains属性检查loc / index(或字典术语中的键),而不是值本身。如果您的位置/索引包含恰好与您的ID重叠的整数,则isin(dataframe_b.id)可能会意外返回 true
In [17]: dataframe_b
Out[17]:
    id
0  121
1  122
2  123
3  124

In [18]: 121 in dataframe_b.id
Out[18]: False

In [19]: 121 in dataframe_b.id.index
Out[19]: False

In [20]: 121 in dataframe_b.id.values
Out[20]: True

In [21]: 1 in dataframe_b.id
Out[21]: True