统计DataFrame每行中Series项的出现次数

17 投票
3 回答
22277 浏览
提问于 2025-04-18 11:46

我有一个 pandas.DataFrame,它的样子是这样的。

COL1    COL2    COL3
C1      None    None
C1      C2      None
C1      C1      None
C1      C2      C3

我想对这个数据表中的每一行,统计一下 C1、C2 和 C3 各出现了多少次,并把这些信息作为新列添加到这个数据表里。比如,第一行有 1 个 C1,0 个 C2 和 0 个 C3。最终的数据表应该是这样的:

COL1    COL2    COL3    C1  C2  C3
C1      None    None    1   0   0
C1      C2      None    1   1   0
C1      C1      None    2   0   0
C1      C2      C3      1   1   1

所以,我创建了一个包含 C1、C2 和 C3 的 Series,想要统计这些值的出现次数。一个方法是遍历数据表的每一行和每一列,然后再遍历这个 Series,如果匹配就增加计数。但是,有没有一种 apply 的方法,可以更简洁地实现这个呢?

3 个回答

1

通常,使用 applyseries 函数对整个数据表进行操作会让整个过程变得很慢。想了解更多,可以看看这个链接:链接

df.mask(df.eq('None')).stack().str.get_dummies().sum(level=0)
Out[165]: 
   C1  C2  C3
0   1   0   0
1   1   1   0
2   2   0   0
3   1   1   1

或者你可以使用 Counter 来处理。

from  collections import Counter

pd.DataFrame([ Counter(x) for x in df.values]).drop('None',1)
Out[170]: 
   C1   C2   C3
0   1  NaN  NaN
1   1  1.0  NaN
2   2  NaN  NaN
3   1  1.0  1.0
4

安迪的回答非常准确。

我补充一下,如果C1、C2……Cn这个列表很大,而我们只想查看其中的一部分。

dff = df.copy()
dff['C1']=(df == 'C1').T.sum()
dff['C2']=(df == 'C2').T.sum()
dff['C3']=(df == 'C3').T.sum()
dff
  COL1  COL2  COL3  C1  C2  C3
0   C1  None  None   1   0   0
1   C1    C2  None   1   1   0
2   C1    C1  None   2   0   0
3   C1    C2    C3   1   1   1
22

你可以使用 value_counts 这个方法:

In [11]: df.apply(pd.Series.value_counts, axis=1)
Out[11]: 
   C1  C2  C3  None
0   1 NaN NaN     2
1   1   1 NaN     1
2   2 NaN NaN     1
3   1   1   1   NaN

这样你就可以填充缺失值(NaN),并且只添加你想要的基本值:

In [12]: df.apply(pd.Series.value_counts, axis=1)[['C1', 'C2', 'C3']].fillna(0)
Out[12]: 
   C1  C2  C3
0   1   0   0
1   1   1   0
2   2   0   0
3   1   1   1

注意:现在有一个未解决的问题,就是希望能直接在数据框(DataFrame)上使用 value_counts 方法(我觉得这个功能应该在 pandas 0.15 版本中引入)。

撰写回答