【问题标题】:How to check if all the elements in list in one pandas column are present in another pandas column如何检查一个熊猫列中列表中的所有元素是否存在于另一个熊猫列中
【发布时间】:2020-06-12 22:02:11
【问题描述】:

我在数据框df1 的一列中有一个列表,我想检查每一行是否该列表的所有元素都在第二个数据框df2 中的另一列中。

这两个数据框是这样的:

df1                                          df2

id | members      |                          num  |  available           |
1  |['a',b']      |                          one  | ['a','b','c','d','e']|
2  |['b']         |                          two  | ['a','b']            |
3  |['a','b','c'] |                          three| ['b','d','e']        |

我正在尝试提出一种方法,该方法可以为我提供df2 中的哪些行对于df1 中的每一行具有members 的所有元素。也许会产生这样的结果:


id | members      | which_cols            |                
1  |['a',b']      | ['one','two']         |                       
2  |['b']         | ['one','two','three'] |                         
3  |['a','b','c'] | ['one']               |                      

我认为将其转换为 {k: list(v) for k,v in df1.groupby("id")["members"]}{i: list(j) for i,j in df2.groupby("num")["available"]} 之类的字典可能会使它更灵活地实现所需的输出,但仍然没有找到一种方法来获得我正在寻找的东西。

df2 将有大约300 行,长度为available25,000 一样大。而df1 可以和1M 一样大,列表长度在members 最多15 行。所以我认为效率也很重要。

【问题讨论】:

  • c 没有出现在two 中?
  • 刚刚添加了一些关于数据的更多信息。
  • 有趣的是,您的membersavailable 丰富得多。您可以过滤掉所有长度超过 15members 列表,因为它们不适合任何 available
  • 那是我的另一个错误。情况恰恰相反。 available 就像一个主列表,members 是子集,但它们并非全部在 df2 的所有行中

标签: python pandas list dataframe dictionary


【解决方案1】:

问题的核心在于您的数据设置。如果你做一些预处理,你可以避免多次重复遍历每个列表。

设置

df1 = pd.Series([['a', 'b'], ['b'], ['a', 'b', 'c']], name = 'members').to_frame()
df2 = pd.Series([['a', 'b', 'c', 'd', 'e'], 
                  ['a', 'b'],
                  ['b', 'd', 'e']], name = 'available').to_frame()
df2.index = ['one', 'two', 'three']

>>> df1

    members
0   ['a', 'b']
1   ['b']
2   ['a', 'b', 'c']

>>> df2

        available
one.    ['a', 'b', 'c', 'd', 'e']
two     ['a', 'b']
three   ['b', 'd', 'e']

重塑数据

如果您在处理数据之前对数据进行一次性编码,那么您在进行子集检查时会处于极大的优势:

# You can do this many ways, but sklearn makes this very easy with:
from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()
df1 = df1.join(pd.DataFrame(mlb.fit_transform(df1.pop('members')),
                          columns=mlb.classes_, index=df1.index))

mlb = MultiLabelBinarizer()
df2 = df2.join(pd.DataFrame(mlb.fit_transform(df2.pop('available')),
                          columns=mlb.classes_, index=df2.index))

>>> df1
    a   b   c
0   1   1   0
1   0   1   0
2   1   1   1


>>> df2
        a   b   c   d   e
one     1   1   1   1   1
two     1   1   0   0   0
three   0   1   0   1   1

计算

这种数据格式的巧妙之处在于,现在您可以从 df2 中减去 df1,如果结果值都不是 -1(表示 df2 中缺少元素,则添加到列表中。可以将其视为覆盖两个数据帧(对齐每个资源)然后相减。当然,这可以向量化:

>>> df1.apply(lambda row: df2.index[((df2[df1.columns] - row) >= 0).all(axis = 1)], axis = 1)

0   Index(['one', 'two'], dtype='object')
1   Index(['one', 'two', 'three'], dtype='object')
2   Index(['one'], dtype='object')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2021-03-26
    • 2020-05-01
    • 2020-05-08
    • 2022-01-06
    相关资源
    最近更新 更多