如何计算每列中唯一的重复值
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-loop
和dict-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)
.apply
与 sum()
%%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.Counter
和itertools.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)时立即停止。
最后,我们得到这个输出的长度,它对应于重复组的数量。
【讨论】:
以上是关于如何计算每列中唯一的重复值的主要内容,如果未能解决你的问题,请参考以下文章