如何对 Pandas 中的列进行 COUNTIFS

How to COUNTIFS across columns in Pandas

我想对跨列中每个值的数量求和。这相当于 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)] = 0

for 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()

也很高兴让这段代码更简洁、更高效,但最关心的是让它正常工作!提前感谢您的帮助!

您可以使用 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),以便进一步提高可用性代码。如果您需要对原始数据执行其他操作,则必须删除这些列,这不是常见的做法,使用您的代码的任何其他人可能都不会想到这种行为。

澄清一下问题。

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 行。

  1. 计算行中 0 的出现次数。有 1. 将其放在 'Ranking_0'
  2. 列中
  3. 计算行中 1 的出现次数。有 0 个。将其放在 'Ranking_1'
  4. 列中

以此类推

所需输出:

   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)