【问题标题】:how to use pandas isin for multiple columns如何将熊猫 isin 用于多列
【发布时间】:2021-04-14 04:12:14
【问题描述】:

我想找到col1col2 的值,其中第一个数据帧的col1col2 都在第二个数据帧中。

这些行应该在结果数据框中:

  1. 披萨,男孩

  2. 披萨,女孩

  3. 冰淇淋,男孩

因为所有三行都在第一个和第二个数据帧中。

我怎么可能做到这一点?我正在考虑使用isin,但是当我必须考虑多个列时,我不确定如何使用它。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    col1col2 上执行inner merge

    import pandas as pd
    df1 = pd.DataFrame({'col1': ['pizza', 'hamburger', 'hamburger', 'pizza', 'ice cream'], 'col2': ['boy', 'boy', 'girl', 'girl', 'boy']}, index=range(1,6))
    df2 = pd.DataFrame({'col1': ['pizza', 'pizza', 'chicken', 'cake', 'cake', 'chicken', 'ice cream'], 'col2': ['boy', 'girl', 'girl', 'boy', 'girl', 'boy', 'boy']}, index=range(10,17))
    
    print(pd.merge(df2.reset_index(), df1, how='inner').set_index('index'))
    

    产量

                col1  col2
    index                 
    10         pizza   boy
    11         pizza  girl
    16     ice cream   boy
    

    reset_indexset_index 调用的目的是保留df2 的索引,就像您发布的所需结果一样。如果索引不重要,那么

    pd.merge(df2, df1, how='inner')
    #         col1  col2
    # 0      pizza   boy
    # 1      pizza  girl
    # 2  ice cream   boy
    

    足够了。


    或者,您可以从col1col2 列中构造MultiIndexs,然后调用MultiIndex.isin method

    index1 = pd.MultiIndex.from_arrays([df1[col] for col in ['col1', 'col2']])
    index2 = pd.MultiIndex.from_arrays([df2[col] for col in ['col1', 'col2']])
    print(df2.loc[index2.isin(index1)])
    

    产量

             col1  col2
    10      pizza   boy
    11      pizza  girl
    16  ice cream   boy
    

    【讨论】:

    • 您可以选择使用 df.loc[df.isin(filter_to_apply).sum(axis=1) == len(filter_to_apply.keys()), :] 而不是 MultiIndex to apply 是一个以列名作为键的字典,而 dict values 是一个值列表 这采用 df.isin(filter_to_apply) 的二进制结果的逐行总和,并确保我们过滤行中所有元素的行是真的。可以轻松将此过滤器更改为其他类型的过滤器
    【解决方案2】:

    谢谢你! 这是一个小更新。

    import pandas as pd
    df1 = pd.DataFrame({'col1': ['pizza', 'hamburger', 'hamburger', 'pizza', 'ice cream'], 'col2': ['boy', 'boy', 'girl', 'girl', 'boy']}, index=range(1,6))
    df2 = pd.DataFrame({'col1': ['pizza', 'pizza', 'chicken', 'cake', 'cake', 'chicken', 'ice cream'], 'col2': ['boy', 'girl', 'girl', 'boy', 'girl', 'boy', 'boy']}, index=range(10,17))
    df1[df1.set_index(['col1','col2']).index.isin(df2.set_index(['col1','col2']).index)]
    

    返回:

        col1    col2
    1   pizza   boy
    4   pizza   girl
    5   ice cream   boy
    

    【讨论】:

      【解决方案3】:

      如果您必须坚持使用isin 或否定版本~isin。 您可以先创建一个新列,将col1col2 串联。然后使用isin 过滤您的数据。代码如下:

      import pandas as pd
      df1 = pd.DataFrame({'col1': ['pizza', 'hamburger', 'hamburger', 'pizza', 'ice cream'], 'col2': ['boy', 'boy', 'girl', 'girl', 'boy']}, index=range(1,6))
      df2 = pd.DataFrame({'col1': ['pizza', 'pizza', 'chicken', 'cake', 'cake', 'chicken', 'ice cream'], 'col2': ['boy', 'girl', 'girl', 'boy', 'girl', 'boy', 'boy']}, index=range(10,17))
      
      df1['indicator'] = df1['col1'].str.cat(df1['col2'])
      df2['indicator'] = df2['col1'].str.cat(df2['col2'])
      
      df2.loc[df2['indicator'].isin(df1['indicator'])].drop(columns=['indicator'])
      

      给了

      
          col1    col2
      10  pizza   boy
      11  pizza   girl
      16  ice cream   boy
      

      如果您这样做,请记住确保连接两列不会产生误报,例如df1123456 的串联以及df2123456 的串联将匹配,即使它们各自的列不匹配。您可以通过附加sep 参数来解决此问题。

      df1['indicator'] = df1['col1'].str.cat(df1['col2'], sep='$$$')
      df2['indicator'] = df2['col1'].str.cat(df2['col2'], sep='$$$')
      

      【讨论】:

      • 请您详细说明为什么使用.drop(columns=['indicator']
      • @CN_Cabbage 因为我们不希望临时帮助列出现在已处理的数据框中。
      【解决方案4】:

      最好的方法是将字典传递给 isin()

      正如https://www.oreilly.com/library/view/mastering-exploratory-analysis/9781789619638/eb563c9a-83e1-4e0c-82d7-6f83addc3340.xhtml 建议的那样。

      此外,文档https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.isin.html 显示了另一个如何传递字典的示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-20
        • 2014-02-04
        • 1970-01-01
        相关资源
        最近更新 更多