Python 如何在没有lambda的情况下使用pandas对列中的外观进行求和

Python 如何在没有lambda的情况下使用pandas对列中的外观进行求和,python,pandas,numpy,dataframe,lambda,Python,Pandas,Numpy,Dataframe,Lambda,我有以下数据帧 a b c d e 0 0 0 -1 1 -1 1 0 1 -1 1 -1 2 -1 0 -1 1 1 3 -1 1 1 -1 1 4 1 0 1 -1 1 5 1 0 0 0 1 6 1 1 0 0 -1 7 1 1 -1 0 0 对于

我有以下数据帧

    a    b    c    d    e 
0   0    0   -1    1   -1
1   0    1   -1    1   -1
2  -1    0   -1    1    1
3  -1    1    1   -1    1
4   1    0    1   -1    1  
5   1    0    0    0    1 
6   1    1    0    0   -1 
7   1    1   -1    0    0
对于a、b、c、d、e中出现的每个数字,我想求和并将其在一行中出现的次数存储在一列中,因此结果应该是这样的:

    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    1    2     2
7   1    1   -1   -1    0    2    1     2
所以在第一行中,数字“1”在a,b,c,d,e中出现一次,所以我们将其存储在Sum1列中。然后,数字“0”出现两次,我们将其存储在Sum0中,数字“-1”出现两次,我们将其存储在Sum_1中


如果不使用lambda函数(为了获得更好的性能),如何计算这些列?我猜这里涉及到numpy,但我不知道如何做

创建布尔掩码并计算它-
True
s是类似于
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

一般解决方案包括:

提高
Zero
解决方案性能的想法-比较
numpy数组
,而不是使用静态值,可以通过以下方式使用唯一值:

计时

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




创建布尔掩码并将其计数-
True
s是类似于
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

一般解决方案包括:

提高
Zero
解决方案性能的想法-比较
numpy数组
,而不是使用静态值,可以通过以下方式使用唯一值:

计时

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




使用
get_假人

df=df.astype(str)
pd.get_dummies(df.stack()).sum(level=0)
Out[667]: 
   -1  0  1
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
更多信息

pd.concat([df,pd.get_dummies(df.stack()).sum(level=0).add_prefix('Sum')],1)
Out[669]: 
    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
另一种方法可能会解决,但不需要转换为str。

df.apply(lambda x : x.value_counts(),1).fillna(0)

Out[674]: 
    -1    0    1
0  2.0  2.0  1.0
1  2.0  1.0  2.0
2  2.0  1.0  2.0
3  2.0  0.0  3.0
4  1.0  1.0  3.0
5  0.0  3.0  2.0
6  1.0  2.0  2.0
7  1.0  2.0  2.0

使用
get_假人

df=df.astype(str)
pd.get_dummies(df.stack()).sum(level=0)
Out[667]: 
   -1  0  1
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
更多信息

pd.concat([df,pd.get_dummies(df.stack()).sum(level=0).add_prefix('Sum')],1)
Out[669]: 
    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
另一种方法可能会解决,但不需要转换为str。

df.apply(lambda x : x.value_counts(),1).fillna(0)

Out[674]: 
    -1    0    1
0  2.0  2.0  1.0
1  2.0  1.0  2.0
2  2.0  1.0  2.0
3  2.0  0.0  3.0
4  1.0  1.0  3.0
5  0.0  3.0  2.0
6  1.0  2.0  2.0
7  1.0  2.0  2.0
使用

In [72]: df.join(pd.DataFrame({'Sum{}'.format(v):df.eq(v).sum(1) for v in [1, 0, -1]}))
Out[72]:
   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
使用

In [72]: df.join(pd.DataFrame({'Sum{}'.format(v):df.eq(v).sum(1) for v in [1, 0, -1]}))
Out[72]:
   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


现在只有-1,0,1吗?是的。虽然将来我可能会使用其他值,但是只有-1、0和1的解决方案是完全可以接受的。现在只有-1、0和1吗?是的。虽然我可能希望将来使用其他值,但只使用-1、0和1的解决方案是完全可以接受的。如果运行
Sum0
,然后运行
Sum1
,这可能不起作用。由于
df
会被覆盖,并且会对所有
df
进行值检查,请记住,如果您需要对3个以上的值求和,则这会很不方便。Zero的答案是对这一点的一种概括。新的?看起来很像温的答案,唯一的区别是加入…;-)@Cᴏʟᴅsᴘᴇᴇᴅ - 和移除堆栈;)我怀疑,这将是低效的,字符串转换,然后mxn值爆炸,…?如果运行
Sum0
,然后运行
Sum1
,这可能不起作用。由于
df
会被覆盖,并且会对所有
df
进行值检查,请记住,如果您需要对3个以上的值求和,则这会很不方便。Zero的答案是对这一点的一种概括。新的?看起来很像温的答案,唯一的区别是加入…;-)@Cᴏʟᴅsᴘᴇᴇᴅ - 和移除堆栈;)我怀疑,这将是低效的,字符串转换,然后mxn值爆炸,…?这个答案最好的部分是,它适用于一百万个值,就像它适用于[-1,0,1].Nice和
pd.get_dummies(df.stack()).sum(level=0).reindex(columns=[-1,0,1],fill_value=0)
如果只对值的子集感兴趣,则会出现问题;如果a、b、c、d、e列具有相同的名称,这是否有效?(因为dataframe是其他df的pd.concat,所有df都具有相同的列名)@PandemicCode同名列总是创建这种类型的问题,最好重命名it@Wen你的代码运行得很好。尽管其他答案也很好,但这是一个非常优雅的答案。这个答案最好的部分是它适用于一百万个值,就像它适用于[-1,0,1].Nice和
pd.get\u dummies(df.stack()).sum(level=0)。如果只对值的子集感兴趣,则重新索引(columns=[-1,0,1],fill\u value=0)
。此外,出现了一个问题;如果a、b、c、d、e列具有相同的名称,这是否有效?(因为dataframe是其他df的pd.concat,所有df都具有相同的列名)@PandemicCode同名列总是创建这种类型的问题,最好重命名it@Wen你的代码运行得很好。虽然其他答案也不错,但这是一个非常优雅的答案。