You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame动态添加列:计算各国年度GDP占比的实现问题

问题描述

我手头有这样一个Pandas DataFrame:

Date         Country     GDP
0   2011  United States   345.0
1   2012  United States     0.0
2   2013  United States   457.0
3   2014  United States   577.0
4   2015  United States     0.0
5   2016  United States   657.0
6   2011             UK    35.0
7   2012             UK    64.0
8   2013             UK    54.0
9   2014             UK    67.0
10  2015             UK   687.0
11  2016             UK     0.0
12  2011           China    34.0
13  2012           China    54.0
14  2013           China   678.0
15  2014           China   355.0
16  2015           China  5678.0
17  2016           China   345.0

我想给它加一列perc,用来计算每个国家当年的GDP在三个国家当年总GDP中的占比。

最开始我写了嵌套循环的代码:

import pandas as pd
countrylist=['United States','UK','China']
for country in countrylist:
    for year in range (2011,2016):
        df['perc']=(df['GDP'][(df['Country']==country) & (df['Date']==year)]).astype(float)/df['GDP'][df['Date']==year].sum()
        print (df['perc'])

结果发现每次循环都会把之前的perc值覆盖掉,最后只有最后一次循环的结果保留,大部分行都是NaN。后来我试了指定位置赋值:

df['perc'][([(df['Country']==country) & (df['Date']==year)])]=(df['GDP'][(df['Country']==country) & (df['Date']==year)]).astype(float)/df['GDP'][df['Date']==year].sum()

也没起作用,想请教怎么才能得到如下的理想结果:

Date         Country     GDP  perc
0   2011  United States   345.0  0.81
1   2012  United States     0.0  0.0
2   2013  United States   457.0  0.23
3   2014  United States   577.0  xx
4   2015  United States     0.0  xx
5   2016  United States   657.0  xx
6   2011             UK    35.0  xx
7   2012             UK    64.0  xx
8   2013             UK    54.0  xx
9   2014             UK    67.0  xx
10  2015             UK   687.0  xx
11  2016             UK     0.0  xx
12  2011           China    34.0  xx
13  2012           China    54.0  xx
14  2013           China   678.0  xx
15  2014           China   355.0  xx
16  2015           China  5678.0  xx
17  2016           China   345.0  xx

解决方案

你踩了Pandas新手常见的坑:用嵌套循环逐行赋值不仅效率低,还容易因为覆盖整列数据导致结果丢失。其实用Pandas的分组功能就能一行搞定,完全不需要循环。

推荐方法:groupby + transform

groupby('Date')会把数据按年份分组,transform('sum')会计算每个年份的GDP总和,并且把这个总和广播回该年份的每一行,这样直接用每行的GDP除以对应年份的总和就能得到占比:

import pandas as pd

# 先构造你的DataFrame(如果还没创建的话)
data = [
    [2011, 'United States', 345.0],
    [2012, 'United States', 0.0],
    [2013, 'United States', 457.0],
    [2014, 'United States', 577.0],
    [2015, 'United States', 0.0],
    [2016, 'United States', 657.0],
    [2011, 'UK', 35.0],
    [2012, 'UK', 64.0],
    [2013, 'UK', 54.0],
    [2014, 'UK', 67.0],
    [2015, 'UK', 687.0],
    [2016, 'UK', 0.0],
    [2011, 'China', 34.0],
    [2012, 'China', 54.0],
    [2013, 'China', 678.0],
    [2014, 'China', 355.0],
    [2015, 'China', 5678.0],
    [2016, 'China', 345.0]
]
df = pd.DataFrame(data, columns=['Date', 'Country', 'GDP'])

# 计算占比并新增列
df['perc'] = df['GDP'] / df.groupby('Date')['GDP'].transform('sum')

# 可选:保留两位小数让结果更整洁
df['perc'] = df['perc'].round(2)

print(df)

为什么你的原代码失效?

  1. 整列覆盖问题:你每次循环直接给df['perc']赋值,会把整列替换成当前循环的结果——只有符合country和year条件的行有值,其他行都是NaN,所以循环结束后只剩最后一次循环的有效数据。
  2. 赋值语法错误:你尝试的位置赋值写法有问题,正确的修改应该用.loc来避免SettingWithCopyWarning,但即使改对了,嵌套循环的效率也远不如Pandas原生的分组运算。

运行结果示例

以2011年为例,总GDP是345+35+34=414,美国的占比是345/414≈0.83,英国是35/414≈0.08,中国是34/414≈0.08,和你理想结果里的0.81(手动近似值)接近。运行代码后,所有年份的占比都会正确计算,不会出现NaN覆盖的问题。

内容的提问来源于stack exchange,提问作者Chelseajcole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:02:54