基于另一列的每个值的列值总和,然后除以总数
Posted
技术标签:
【中文标题】基于另一列的每个值的列值总和,然后除以总数【英文标题】:Sum values of a column for each value based on another column and divide it by total 【发布时间】:2019-11-23 09:24:27 【问题描述】:今天我又一次在 python 和数据分析方面苦苦挣扎。
我得到了一个如下所示的数据框:
name totdmgdealt
0 Warwick 96980.0
1 Nami 25995.0
2 Draven 171568.0
3 Fiora 113721.0
4 Viktor 185302.0
5 Skarner 148791.0
6 Galio 130692.0
7 Ahri 145731.0
8 Jinx 182680.0
9 VelKoz 85785.0
10 Ziggs 46790.0
11 Cassiopeia 62444.0
12 Yasuo 117896.0
13 Warwick 129156.0
14 Evelynn 179252.0
15 Caitlyn 163342.0
16 Wukong 122919.0
17 Syndra 146754.0
18 Karma 35766.0
19 Warwick 117790.0
20 Draven 74879.0
21 Janna 11242.0
22 Lux 66424.0
23 Amumu 87826.0
24 Vayne 76085.0
25 Ahri 93334.0
..
..
..
这是一个数据框,其中包括一个英雄在一场比赛中的总伤害。 现在我想对这些信息进行分组,这样我就可以看到总体上哪个英雄造成的伤害最大。 我尝试了 groupby('name') 但它根本不起作用。 我已经完成了一些关于 groupby 和 summing values 的线程,但我没有解决我的具体问题。
每个英雄造成的伤害也应该显示为总伤害的百分比。
我正在寻找这样的输出:
name totdmgdealt percentage
0 Warwick 2378798098 2.1 %
1 Nami 2837491074 2.3 %
2 Draven 1231451224 ..
3 Fiora 1287301724 ..
4 Viktor 1239808504 ..
5 Skarner 1487911234 ..
6 Galio 1306921234 ..
【问题讨论】:
添加你尝试过的代码 【参考方案1】:我们可以按名称分组并得到sum
,然后我们将每个值除以.div
的总数,然后将其乘以100 并使用.mul
,最后将其四舍五入到小数点后.round
:
total = df['totdmgdealt'].sum()
summed = df.groupby('name', sort=False)['totdmgdealt'].sum().reset_index()
summed['percentage'] = summed.groupby('name', sort=False)['totdmgdealt']\
.sum()\
.div(total)\
.mul(100)\
.round(1).values
name totdmgdealt percentage
0 Warwick 343926.0 12.2
1 Nami 25995.0 0.9
2 Draven 246447.0 8.7
3 Fiora 113721.0 4.0
4 Viktor 185302.0 6.6
5 Skarner 148791.0 5.3
6 Galio 130692.0 4.6
7 Ahri 239065.0 8.5
8 Jinx 182680.0 6.5
9 VelKoz 85785.0 3.0
10 Ziggs 46790.0 1.7
11 Cassiopeia 62444.0 2.2
12 Yasuo 117896.0 4.2
13 Evelynn 179252.0 6.4
14 Caitlyn 163342.0 5.8
15 Wukong 122919.0 4.4
16 Syndra 146754.0 5.2
17 Karma 35766.0 1.3
18 Janna 11242.0 0.4
19 Lux 66424.0 2.4
20 Amumu 87826.0 3.1
21 Vayne 76085.0 2.7
【讨论】:
感谢您的回答。我需要提一下,列名对于每个名称都有多次出现。我想将每个名称的这些值相加,然后将一个名称的总伤害除以总伤害。 您能否编辑您的答案并将其包含在您的示例数据框中? @FloatingGoat 我刚刚更新了我的帖子。带有名称和 totdmgdealt 的数据框是 1.784.592 行大。 更新了答案,只有矢量化方法,没有使用.apply
。这应该对 180 万行与您在速度方面接受@FloatingGoat 的答案产生很大影响
@FloatingGoat 是的,肯定应该有,因为.apply
逐行进行,而“本机”(即矢量化)方法可以并行化这项工作。我去申请格式。【参考方案2】:
您可以使用sum()
获取总伤害,并使用apply
计算每行的相关百分比,如下所示:
import pandas as pd
from io import StringIO
df = pd.read_csv(StringIO("""
name totdmgdealt
0 Warwick 96980.0
1 Nami 25995.0
2 Draven 171568.0
3 Fiora 113721.0
4 Viktor 185302.0
5 Skarner 148791.0
6 Galio 130692.0
7 Ahri 145731.0
8 Jinx 182680.0
9 VelKoz 85785.0
10 Ziggs 46790.0
11 Cassiopeia 62444.0
12 Yasuo 117896.0
13 Warwick 129156.0
14 Evelynn 179252.0
15 Caitlyn 163342.0
16 Wukong 122919.0
17 Syndra 146754.0
18 Karma 35766.0
19 Warwick 117790.0
20 Draven 74879.0
21 Janna 11242.0
22 Lux 66424.0
23 Amumu 87826.0
24 Vayne 76085.0
25 Ahri 93334.0"""), sep=r"\s+")
summed_df = df.groupby('name')['totdmgdealt'].agg(['sum']).rename(columns="sum": "totdmgdealt").reset_index()
summed_df['percentage'] = summed_df.apply(
lambda x: ":.2f%".format(x['totdmgdealt'] / summed_df['totdmgdealt'].sum() * 100), axis=1)
print(summed_df)
输出:
name totdmgdealt percentage
0 Ahri 239065.0 8.48%
1 Amumu 87826.0 3.12%
2 Caitlyn 163342.0 5.79%
3 Cassiopeia 62444.0 2.21%
4 Draven 246447.0 8.74%
5 Evelynn 179252.0 6.36%
6 Fiora 113721.0 4.03%
7 Galio 130692.0 4.64%
8 Janna 11242.0 0.40%
9 Jinx 182680.0 6.48%
10 Karma 35766.0 1.27%
11 Lux 66424.0 2.36%
12 Nami 25995.0 0.92%
13 Skarner 148791.0 5.28%
14 Syndra 146754.0 5.21%
15 Vayne 76085.0 2.70%
16 VelKoz 85785.0 3.04%
17 Viktor 185302.0 6.57%
18 Warwick 343926.0 12.20%
19 Wukong 122919.0 4.36%
20 Yasuo 117896.0 4.18%
21 Ziggs 46790.0 1.66%
【讨论】:
注意:如果您打算稍后将此值用于计算(而不仅仅是显示),最好将其保持为浮点数,不带%
符号。
感谢您的回答。我需要提一下,列名对于每个名称都有多次出现。我想将每个名称的这些值相加,然后将一个名称的总伤害除以总伤害。
@FloatingGoat,好的,我编辑了我的答案,首先创建了一个求和的 df,然后将我的解决方案应用于它。
@FloatingGoat 编辑了我的输出和示例以使用您的新扩展示例
有没有办法不将名称作为索引值?【参考方案3】:
也许你可以试试这个: 我尝试使用我的示例数据来实现相同的目标,并尝试在您的 Jupyter Notebook 中运行以下代码:
import pandas as pd
name=['abhit','mawa','vaibhav','dharam','sid','abhit','vaibhav','sid','mawa','lakshya']
totdmgdealt=[24,45,80,22,89,55,89,51,93,85]
name=pd.Series(name,name='name') #converting into series
totdmgdealt=pd.Series(totdmgdealt,name='totdmgdealt') #converting into series
data=pd.concat([name,totdmgdealt],axis=1)
data=pd.DataFrame(data) #converting into Dataframe
final=data.pivot_table(values="totdmgdealt",columns="name",aggfunc="sum").transpose() #actual aggregating method
total=data['totdmgdealt'].sum() #calculating total for calculating percentage
def calPer(row,total): #actual Function for Percentage
return ((row/total)*100).round(2)
total=final['totdmgdealt'].sum()
final['Percentage']=calPer(final['totdmgdealt'],total) #assigning the function to the column
final
样本数据:
name totdmgdealt
0 abhit 24
1 mawa 45
2 vaibhav 80
3 dharam 22
4 sid 89
5 abhit 55
6 vaibhav 89
7 sid 51
8 mawa 93
9 lakshya 85
输出:
totdmgdealt Percentage
name
abhit 79 12.48
dharam 22 3.48
lakshya 85 13.43
mawa 138 21.80
sid 140 22.12
vaibhav 169 26.70
理解并运行代码,只需将数据集替换为 Yours。也许这会有所帮助。
【讨论】:
以上是关于基于另一列的每个值的列值总和,然后除以总数的主要内容,如果未能解决你的问题,请参考以下文章