【问题标题】:How to COUNTIFS across columns in Pandas如何在 Pandas 中跨列进行 COUNTIFS
【发布时间】:2020-09-09 16:30:02
【问题描述】:

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

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

【问题讨论】:

  • 您不需要任何循环,但您现有的数据结构和所需的输出尚不清楚
  • 您能否添加一个实际可读的示例数据集以及您的预期输出。

标签: python pandas boolean


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    稍微澄清一下问题。

    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. 计算行中出现的 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) 沿水平行求和(axis=1)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多