【问题标题】:How to count the unique duplicate values in each column如何计算每列中唯一的重复值
【发布时间】:2021-11-12 22:38:16
【问题描述】:

我们有以下数据框,

df = pd.DataFrame(data = {'A': [1,2,3,3,2,4,5,3],
                     'B': [9,6,7,9,2,5,3,3],
                     'C': [4,4,4,5,9,3,2,1]})
df

我想创建一个新的数据框,其中每个列名都会显示重复的数量。

例如。 'B',有两个重复的值(9 和 3),我想打印 2 等

【问题讨论】:

  • 仅供参考:彻底回答问题非常耗时。如果您的问题已解决,请通过接受最适合您的需求的解决方案表示感谢。✔ 位于答案左上角的 ▲/▼ 箭头下方。如果出现更好的解决方案,则可以接受新的解决方案。如果您的声望超过 15,您也可以使用 ▲/▼ 箭头对答案的有用性进行投票。 如果解决方案无法回答问题,请发表评论。 What should I do when someone answers my question?。谢谢。

标签: python pandas duplicates


【解决方案1】:

选项 1

如果我们需要计算重复值的个数

import pandas as pd

df = pd.DataFrame(data = {'A': [1,2,3,3,2,4,5,3],
                     'B': [9,6,7,9,2,5,3,3],
                     'C': [4,4,4,5,9,3,2,1]})

df1 = df.apply(lambda x:sum(x.duplicated()))
print(df1)

打印:

A    3
B    2
C    2
dtype: int64

选项 2

如果我们需要计算重复值的数量

df1 = df.agg(lambda x: sum(x.value_counts() > 1)) # or df1 = df.apply(lambda x: sum(x.value_counts() > 1))
print(df1)

打印:

A    2
B    2
C    1
dtype: int64

选项 2.1

详细

df1 = df.apply(lambda x: ' '.join([f'[val = {i}, cnt = {v}]' for i, v in x.value_counts().iteritems() if v > 1]))
print(df1)

打印:

A    [val = 3, cnt = 3] [val = 2, cnt = 2]
B    [val = 9, cnt = 2] [val = 3, cnt = 2]
C                       [val = 4, cnt = 3]
dtype: object

【讨论】:

  • 感谢两位的贡献!第二个选项是我正在寻找的。​​span>
【解决方案2】:

如果您希望每个元素重复计数,您可以使用:

import pandas as pd
from collections import Counter

df = pd.DataFrame(data = {'A': [1,2,3,3,2,4,5,3],
                     'B': [9,6,7,9,2,5,3,3],
                     'C': [4,4,4,5,9,3,2,1]})
def cnt(x):
    return {k:v for k,v in x.items() if v>1}
        

df.apply(lambda x : cnt(Counter(x)))

输出:

A    {2: 2, 3: 3}
B    {9: 2, 3: 2}
C          {4: 3}
dtype: object

【讨论】:

    【解决方案3】:
    • 这可以通过获取每列的pandas.Series.value_counts,然后获取值计数大于1的pandas.Series.sum来完成
      • vc[vc.gt(1)] 创建一个 pandas.Series ,其计数对于列中的每个值都大于 1。
    • 我们可以从%%timeit比较5列1M行,.apply矢量化方法,以及for-loopdict-comprehension,比使用内置python的.apply更快sum(...)

    .apply.value_counts.sum

    • col.value_counts().gt(1) 创建一个 Boolean 系列
      • True 的计算结果为 1,False 的计算结果为 0,因此 .sum() 产生正确的结果。
    dupe_count = df.agg(lambda col: col.value_counts().gt(1).sum())
    
    A    2
    B    2
    C    1
    dtype: int64
    

    for-loop

    • 通常不建议迭代数据帧,尤其是逐行。但是,我们正在遍历列,然后应用向量化函数,这与 .apply 发生的情况相同。
    def col_vc(df):
        dupe_count = dict()
        for col in df.columns:
            dupe_count[col] = df[col].value_counts().gt(1).sum()
        return dupe_count
    
    
    col_vc(df)
    
    [result]:
    {'A': 2, 'B': 2, 'C': 1}
    
    • 等效单行dict-comprehension
    dupe_count = {col: df[col].value_counts().gt(1).sum() for col in df.columns}
    
    [result]:
    {'A': 2, 'B': 2, 'C': 1}
    
    # to a dataframe if desired
    dupe_count = pd.DataFrame.from_dict(dupe_count, orient='index')
    
       0
    A  2
    B  2
    C  1
    

    %%timeit比较

    import pandas as pd
    import numpy as np
    
    # sample data 5 columns by 1M rows
    np.random.seed(365)
    rows = 1000000
    data = {'a': np.random.randint(0, 10000, size=(rows)),
            'b': np.random.randint(15, 25000, size=(rows)),
            'c': np.random.randint(30, 40000, size=(rows)),
            'd': np.random.randint(450, 550000, size=(rows)),
            'e': np.random.randint(6000, 70000, size=(rows))}
    df = pd.DataFrame(data)
    
    • .apply.value_counts.sum
    %%timeit
    df.agg(lambda x: x.value_counts().gt(1).sum())
    [out]:
    112 ms ± 1.67 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    • dict-comprehension
    %%timeit
    {col: df[col].value_counts().gt(1).sum() for col in df.columns}
    [out]:
    111 ms ± 983 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    • for-loop
    %%timeit
    col_vc(df)
    [out]:
    115 ms ± 4.11 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    %%timeit
    df.agg(lambda x: sum(x.value_counts() > 1))
    [out]:
    194 ms ± 17.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    【讨论】:

      【解决方案4】:

      您可以使用collections.Counteritertools.takewhile

      from collections import Counter
      from itertools import takewhile
      df.apply(lambda c: len(list(takewhile(lambda x: x[1]>1, Counter(c).most_common()))))
      

      输出:

      A    2
      B    2
      C    1
      

      如果要将输出作为数据框,请添加.to_frame(name='n_duplicates'): 输出:

         n_duplicates
      A             2
      B             2
      C             1
      

      工作原理

      对于每一列,Counter 获取每个元素的计数,most_common 首先返回最常见的元素。

      takewhile 迭代此输入并在有一个元素低于阈值(此处为 1)时立即停止。

      最后,我们得到这个输出的长度,它对应于重复组的数量。

      【讨论】:

        猜你喜欢
        • 2014-04-07
        • 2021-08-03
        • 1970-01-01
        • 1970-01-01
        • 2017-11-19
        • 1970-01-01
        • 1970-01-01
        • 2012-10-25
        相关资源
        最近更新 更多