为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Pandas 中跨列进行 COUNTIFS

如何在 Pandas 中跨列进行 COUNTIFS

富国沪深 2023-07-27 10:30:26
我想对跨列中每个值的数量进行求和。这相当于 Excel 中的 COUNTIF。但是,我希望将值填充到列中,而不是单独的 groupby 语句中。因此,如果第 1 行有 5 列,其值如下:1, 1, 3, 1, 5那么Rating_1 = 3、Rating_2=0、Rating_3=1、Rating_4= 0、Rating_5 = 1 或 (3, 0, 1, 0, 1)我正在使用以下代码,并且无法获取要在循环中添加的布尔值(我所有的研究表明它们应该加起来很好!)。现在,我得到以下(二进制)输出:1, 0, 1, 0, 1(实际上应该是 3, 0, 1, 0, 1)df = pd.DataFrame(np.random.randint(0,5,size=(5, 5)), columns=list('ABCDE'))for val in range(1,6):    df['Rating_' + str(val)] = 0for val in range(1,6):    for row in range(0, df.shape[0]):        df['Rating_' + str(val)][row] = ((df['A'][row] == val) +  (df['B'][row] == val) +  (df['C'][row] == val) +  (df['D'][row] == val) +  (df['E'][row] == val)).sum()我也很高兴让这段代码变得更干净、更高效,但最关心的是让它工作!提前感谢您的帮助!
查看完整描述

2 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

您可以使用它groupby来创建一个临时数据帧,您可以对其进行处理并最终与 合并df。


np.random.seed(1) # always add a sample with random state for reproducibility

df = pd.DataFrame(np.random.randint(0,5,size=(5, 5)), columns=list('ABCDE'))



df2 = df.stack().droplevel(-1).reset_index()

df2 = (

    df2.groupby(df2.columns.to_list())

    .size().unstack()

    .fillna(0).astype(int)

)

df = pd.concat([df, df2], axis=1)    

输出


   A  B  C  D  E  0  1  2  3  4

0  3  4  0  1  3  1  1  0  2  1

1  0  0  1  4  4  2  1  0  0  2

2  1  2  4  2  4  0  1  2  0  2

3  3  4  2  4  2  0  0  2  1  2

4  4  1  1  0  1  1  3  0  0  1

我知道这看起来与在 Excel 中添加公式的方式非常相似,但请考虑将数据和结果保留为单独的数据帧(即跳过 ),pd.concat以便在进一步的代码中获得更好的可用性。如果您需要对原始数据执行其他操作,则必须删除这些列,这不是常见的做法,并且使用您的代码的其他人可能不会期望这种行为。


查看完整回答
反对 回复 2023-07-27
?
当年话下

TA贡献1890条经验 获得超9个赞

稍微澄清一下问题。


df

    

   A  B  C  D  E  

0  4  3  4  2  0         

1  0  4  2  3  3          

2  3  4  1  2  1          

3  0  2  3  0  2          

4  2  4  1  3  2  


    

跨行的所需结果:取第 0 行。


计算行中 0 的出现次数。有 1. 将其放入“Ranking_0”列中

计算行中 1 的出现次数。有 0 个。将其放入“Ranking_1”列中

等等


所需输出:


   A  B  C  D  E  Ranking_0  Ranking_1  Ranking_2  Ranking_3  Ranking_4

0  4  3  4  2  0          1          0          1          1          2

1  0  4  2  3  3          1          0          1          2          1

2  3  4  1  2  1          0          2          1          1          1

3  0  2  3  0  2          2          0          2          1          0

4  2  4  1  3  2          0          1          2          1          1

有很多方法可以做到这一点 - 所以我将使用一种对我有用但稍微简化的方法。


import pandas as pd

import numpy as np


df = pd.DataFrame(np.random.randint(0,5,size=(5, 5)), columns=list('ABCDE'))


# The numbers you want to check for

nums = [0,1,2,3,4]

for num in nums: 

     df['Ranking_'+str(num)] = (df.iloc[:,0:5]).isin({num}).sum(1)

  1. 小心地对前 5 列进行求和,否则您将开始在 Ranking_ 列中添加内容!这就是我这样做的原因df.iloc[:,0:5)

  2. 我用它.isin({})只是因为它很干净。还有其他方法。

  3. .sum(1)沿水平行求和(轴=1)


查看完整回答
反对 回复 2023-07-27
  • 2 回答
  • 0 关注
  • 159 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信