【问题标题】:Checking if elements in an array exist in a pandas DataFrame检查数组中的元素是否存在于 Pandas DataFrame 中
【发布时间】:2021-11-12 20:20:09
【问题描述】:

我有一个熊猫数据框和一个熊猫系列,如下所示。

df0 = pd.DataFrame({'col1':['a','b','c','d'],'col2':['b','c','e','f'],'col3':['d','f','g','a']})

  col1 col2 col3
0    a    b    d
1    b    c    f
2    c    e    g
3    d    f    a

df1 = pd.Series(['b','g','g'], index=['col1','col2','col3'])

col1    b
col2    g
col3    g
dtype: object

如您所见,df0 的列和df1 的索引是相同的。对于df1 的每个索引,我想知道该索引处的值是否存在于df0 的对应列中。所以,df1.col1b,我们只需要在df0.col1 中寻找b 并检查它是否存在。

期望的输出:

array([True, False, True])

有没有办法在不使用循环的情况下做到这一点?也许是 numpy 或 pandas 原生的方法?

【问题讨论】:

  • 可以使用melt 之类的东西将两个数据帧从宽转换为长,然后join 它们在列和值上?

标签: python pandas dataframe numpy


【解决方案1】:

您可以使用broadcasting:

(df0 == df1).any().values

它也适用于 NumPy ndarray:

assert (df0.columns == df1.columns).all()

(df0.values == df1.values).any(axis=0)

输出:

array([ True, False,  True])

【讨论】:

  • 这实际上与@StevenS' answer 相同。还是我应该提议df0.__eq__(df1).any()? :p
  • 我个人认为这在这里没有附加价值,如果为每个答案提出了所有语法变体,这将是无法忍受的(我只是说你的回答比其他答案晚得多)。最终您可以在其他答案中添加评论(或编辑)
  • eq== 是不同的函数,通过eq 中的参数可以得到不同的结果。另外我解释说你在这里使用广播。
  • 你能解释一下‘eq’和‘==’有什么不同吗?另外,对于 numpy 的情况,为什么没有'[None,:]' 它可以工作?抱歉,这些都是非常基本的问题。
  • 可以更改eq中的axis参数,得到不同的结果df0.eq(df1, axis='rows')。由于广播,它可以在没有[None,:] 的情况下工作(它会自动执行)。
【解决方案2】:

Pandas 的pandas.DataFrame.eq 方法可能是最简单的。

df0.eq(df1).any()

col1     True
col2    False
col3     True
dtype: bool

【讨论】:

  • 好! +1 可以添加 to_numpy() 以将系列转换为所需输出中的 numpy 数组。
【解决方案3】:

使用 numpy

你可以broadcastdf1检查df0

np.any(df1[None, :] == df0, axis=0)
# col1     True
# col2    False
# col3     True
# dtype: bool

请注意,这假定 df1.indexdf0.columns 具有相同的顺序。如果没有,请先reindex

np.any(df1.reindex(df0.columns)[None, :] == df0, axis=0)

使用熊猫

使用apply检查给定的df1isin是否对应df0col

df0.apply(lambda col: col.isin([df1[col.name]])).any()
# col1     True
# col2    False
# col3     True
# dtype: bool

【讨论】:

    【解决方案4】:
    import pandas as pd
    array=[]
    df0 = pd.DataFrame({'col1':['a','b','c','d'],'col2':['b','c','e','f'],'col3':['d','f','g','a']})
    df1 = pd.Series(['b','g','g'], index=['col1','col2','col3'])
    for i in range(1,4):
        col = 'col'+str(i)
        array.append(df0[col].str.contains(df1[col]).any())
    print(array)
    

    【讨论】:

      【解决方案5】:

      您可以使用apply 代替loop

      试试这个:

      df0 = pd.DataFrame({'col1':['a','b','c','d'],'col2':['b','c','e','f'],'col3':['d','f','g','a']})
      df1 = pd.Series(['b','g','g'], index=['col1','col2','col3'])
      
      df0.apply(lambda x : df1[x.name] in x.values) # for example x <-> 'col1' check this -> 'b' in ['a','b','c','d']
      # col1     True    <-> 'b' in ['a','b','c','d']
      # col2    False    <-> 'g' in ['b','c','e','f']
      # col3     True    <-> 'g' in ['d','f','g','a']
      # dtype: bool
      
      
      df0.apply(lambda x : df1[x.name] in x.values).tolist()
      # [True, False, True]
      

      【讨论】:

        【解决方案6】:

        如果您想要使用列表理解的快速单行:

        [df1[i] in df0[i].unique() for i in df1.index]

        如果它需要是一个数组:

        np.array([df1[i] in df0[i].unique() for i in df1.index])

        输出是:

        array([ True, False, True])

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-02-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-23
          • 2015-02-04
          • 2017-09-17
          相关资源
          最近更新 更多