创建布尔掩码并计算它 - Trues 是类似 1 的过程:
m1 = df == 1
m0 = df == 0
m_1 = df == -1
df['Sum1'] = m1.sum(1)
df['Sum0'] = m0.sum(1)
df['Sum_1'] = m_1.sum(1)
print (df)
a b c d e Sum1 Sum0 Sum_1
0 0 0 -1 1 -1 1 2 2
1 0 1 -1 1 -1 2 1 2
2 -1 0 -1 1 1 2 1 2
3 -1 1 1 -1 1 3 0 2
4 1 0 1 -1 1 3 1 1
5 1 0 0 0 1 2 3 0
6 1 1 0 0 -1 2 2 1
7 1 1 -1 0 0 2 2 1
get_dummies的通用解决方案:
df1 = (pd.get_dummies(df.astype(str), prefix='', prefix_sep='')
.sum(level=0, axis=1)
.add_prefix('Sum'))
print (df1)
Sum-1 Sum0 Sum1
0 2 2 1
1 2 1 2
2 2 1 2
3 2 0 3
4 1 1 3
5 0 3 2
6 1 2 2
7 1 2 2
df = df.join(df1)
print (df)
a b c d e Sum-1 Sum0 Sum1
0 0 0 -1 1 -1 2 2 1
1 0 1 -1 1 -1 2 1 2
2 -1 0 -1 1 1 2 1 2
3 -1 1 1 -1 1 2 0 3
4 1 0 1 -1 1 1 1 3
5 1 0 0 0 1 0 3 2
6 1 1 0 0 -1 1 2 2
7 1 1 -1 0 0 1 2 2
Zero 解决方案的更好性能的想法 - 比较 numpy array,而静态值可以使用 numpy.unique 的唯一值:
all_vals = np.unique(df.values)
arr = df.values
df1 = df.join(pd.DataFrame({'Sum{}'.format(v):(arr == v).sum(1) for v in all_vals}))
print (df1)
a b c d e Sum-1 Sum0 Sum1
0 0 0 -1 1 -1 2 2 1
1 0 1 -1 1 -1 2 1 2
2 -1 0 -1 1 1 2 1 2
3 -1 1 1 -1 1 2 0 3
4 1 0 1 -1 1 1 1 3
5 1 0 0 0 1 0 3 2
6 1 1 0 0 -1 1 2 2
7 1 1 -1 0 0 1 2 2
时间
np.random.seed(234)
N = 100000
df = pd.DataFrame(np.random.randint(3, size=(N,5)), columns=list('abcde')) - 1
print (df)
#wen's solution 1
In [49]: %timeit pd.concat([df,pd.get_dummies(df.astype(str).stack()).sum(level=0).add_prefix('Sum')],1)
1 loop, best of 3: 2.21 s per loop
#wen's solution 2
In [56]: %timeit df.apply(lambda x : x.value_counts(),1).fillna(0)
1 loop, best of 3: 1min 35s per loop
#jezrael's solution 2
In [50]: %timeit df.join((pd.get_dummies(df.astype(str), prefix='', prefix_sep='').sum(level=0, axis=1).add_prefix('Sum')))
1 loop, best of 3: 2.14 s per loop
#jezrael's solution 1
In [55]: %%timeit
...: m1 = df == 1
...: m0 = df == 0
...: m_1 = df == -1
...: df['Sum1'] = m1.sum(1)
...: df['Sum0'] = m0.sum(1)
...: df['Sum_1'] = m_1.sum(1)
...:
10 loops, best of 3: 50.6 ms per loop
#zero's solution1
In [51]: %timeit df.assign(**{'Sum{}'.format(v):df.eq(v).sum(1) for v in [1, 0, -1]})
10 loops, best of 3: 39.8 ms per loop
#zero's solution2
In [52]: %timeit df.join(pd.DataFrame({'Sum{}'.format(v):df.eq(v).sum(1) for v in [1, 0, -1]}))
10 loops, best of 3: 39.6 ms per loop
#zero&jezrael's solution1
In [53]: %timeit df.join(pd.DataFrame({'Sum{}'.format(v):(df.values == v).sum(1) for v in np.unique(df.values)}))
10 loops, best of 3: 23.8 ms per loop
#zero&jezrael's solution2
In [54]: %timeit df.join(pd.DataFrame({'Sum{}'.format(v):(df.values == v).sum(1) for v in [0, 1, -1]}))
100 loops, best of 3: 12.8 ms per loop
#if many columns and more unique values is possible convert to numpy array outside loop
def f1(df):
all_vals = np.unique(df.values)
arr = df.values
return df.join(pd.DataFrame({'Sum{}'.format(v):(arr == v).sum(1) for v in all_vals}))
def f2(df):
arr = df.values
return df.join(pd.DataFrame({'Sum{}'.format(v):(arr == v).sum(1) for v in [0, 1, -1]}))
print (f1(df))
print (f2(df))
#zero&jezrael's solution3
In [58]: %timeit (f1(df))
10 loops, best of 3: 25.8 ms per loop
#zero&jezrael's solution4
In [59]: %timeit (f2(df))
100 loops, best of 3: 13 ms per loop