【问题标题】:How to compare columns in a pandas dataframe如何比较熊猫数据框中的列
【发布时间】:2017-08-14 21:02:31
【问题描述】:

我有一个看起来像这样的 pandas 数据框,其中“Word”作为所有列的列标题:

   Word    Word    Word    Word
0  Nap     Nap     Nap     Cat
1  Cat     Cat     Cat     Flower
2  Peace   Kick    Kick    Go
3  Phone   Fin     Fin     Nap

如何只返回出现在所有 4 列中的单词?

预期输出:

  Word
0 Nap
1 Cat

【问题讨论】:

    标签: python-3.x pandas if-statement dataframe compare


    【解决方案1】:
    • 使用apply(set) 将每一列变成一组单词
    • 使用set.intersection 查找每列集合中的所有单词
    • 先把它变成一个列表,然后是一个系列

    pd.Series(list(set.intersection(*df.apply(set))))
    
    0    Cat
    1    Nap
    dtype: object
    

    我们可以使用一些 python 函数魔法来完成相同的任务,以获得一些性能优势。

    pd.Series(list(
        set.intersection(*map(set, map(lambda c: df[c].values.tolist(), df)))
    ))
    
    0    Cat
    1    Nap
    dtype: object
    

    时间
    下面的代码

    pir1 = lambda d: pd.Series(list(set.intersection(*d.apply(set))))
    pir2 = lambda d: pd.Series(list(set.intersection(*map(set, map(lambda c: d[c].values.tolist(), d)))))
    # I took some liberties with @Anton vBR's solution.
    vbr = lambda d: pd.Series((lambda x: x.index[x.values == len(d.columns)])(pd.value_counts(d.values.ravel())))
    
    results = pd.DataFrame(
        index=pd.Index([10, 30, 100, 300, 1000, 3000, 10000, 30000]),
        columns='pir1 pir2 vbr'.split()
    )
    
    for i in results.index:
        d = pd.concat(dict(enumerate(
            [pd.Series(np.random.choice(words[:i*2], i, False)) for _ in range(4)]
        )), axis=1)
        for j in results.columns:
            stmt = '{}(d)'.format(j)
            setp = 'from __main__ import d, {}'.format(j)
            results.set_value(i, j, timeit(stmt, setp, number=100))
    
    results.plot(loglog=True)
    

    【讨论】:

      【解决方案2】:

      替代解决方案(但这需要唯一值)。

      tf = df.stack().value_counts()
      df2 = pd.DataFrame(pd.Series(tf)).reset_index()
      df2.columns = ["word", "count"]
      
          word    count
      0   Nap     4
      1   Cat     4
      2   Fin     2
      3   Kick    2
      4   Go      1
      5   Phone   1
      6   Peace   1
      7   Flower  1
      

      这可以用 df2[df2["count"] == len(df.columns)]["word"]

      过滤
      0    Nap
      1    Cat
      Name: word, dtype: object
      

      【讨论】:

      • 这仅在每列都是唯一的情况下才有效。如果您更正此问题,请告诉我,我会删除评论。
      • @piRSquared 是的,我知道这一点,这就是我把它放在括号中的原因。我提出它作为答案是因为它简单(易于理解)。但是是的,它以这种方式受到限制。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-27
      • 2017-03-28
      • 2017-02-28
      • 1970-01-01
      • 2016-05-04
      • 2020-06-08
      相关资源
      最近更新 更多