统计DataFrame每行中Series项的出现次数
我有一个 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
通常,使用 apply
和 series
函数对整个数据表进行操作会让整个过程变得很慢。想了解更多,可以看看这个链接:链接
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 版本中引入)。