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你的代码运行得很好。虽然其他答案也不错,但这是一个非常优雅的答案。