我有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作为值的系列 - 一种最重要的方法是循环遍历DataFrame的行和列,然后通过此系列,并在计数器匹配时递增计数器。但是有一种apply
方法能够以紧凑的方式实现这一目标吗?
答案 0 :(得分:10)
您可以申请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和applend:
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引入)。
答案 1 :(得分:3)
安迪的回答很明显。
我添加了这个答案,如果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
答案 2 :(得分:0)
通常,对整个数据框使用apply
+ serise
函数会减慢整个过程,其他阅读:Link
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