如何对 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 行。
- 计算行中 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)
- 注意只对前 5 列求和,否则您将开始添加 Ranking_ 列!这就是为什么我做了
df.iloc[:,0:5)
- 我用
.isin({})
只是因为它很干净。还有其他方法。
.sum(1)
沿水平行求和(轴=1)
我想对跨列中每个值的数量求和。这相当于 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 行。
- 计算行中 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)
- 注意只对前 5 列求和,否则您将开始添加 Ranking_ 列!这就是为什么我做了
df.iloc[:,0:5)
- 我用
.isin({})
只是因为它很干净。还有其他方法。 .sum(1)
沿水平行求和(轴=1)