如何计算每列中唯一的重复值

Posted

技术标签:

【中文标题】如何计算每列中唯一的重复值【英文标题】: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?。谢谢。 【参考方案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)
.applysum()
%%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)时立即停止。

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

【讨论】:

以上是关于如何计算每列中唯一的重复值的主要内容,如果未能解决你的问题,请参考以下文章

如何将熊猫数据框中每列中唯一值的数量绘制为条形图?

计算唯一字段的列中的重复值

从文本文件中删除每个单独列中的重复项

计算熊猫列中每个唯一值的数量[重复]

如何在 Python 中对每列的唯一值求和? [复制]

如何计算每列中有多少个空值?