Pandas:如何计算来自其他地方的人口百分比

Pandas: how to calculate percentage of a population from elsewhere

我找到了这个关于 covid 疫苗接种的数据文件,我想查看(部分)人口的疫苗接种覆盖率。实际示例可能会变得更加清晰,所以请耐心等待。

如果我使用 df = pd.read_csv('https://epistat.sciensano.be/Data/COVID19BE_VACC.csv', parse_dates=['DATE']) 读取 csv,我会得到这个结果:

        DATE    REGION AGEGROUP SEX            BRAND DOSE  COUNT
0 2020-12-28  Brussels    18-34   F  Pfizer-BioNTech    A      1
1 2020-12-28  Brussels    45-54   F  Pfizer-BioNTech    A      2
2 2020-12-28  Brussels    55-64   F  Pfizer-BioNTech    A      3
3 2020-12-28  Brussels    55-64   M  Pfizer-BioNTech    A      1
4 2020-12-28  Brussels    65-74   F  Pfizer-BioNTech    A      2

我对按地区和日期分类的数字特别感兴趣。
所以我使用 df.groupby(['REGION','DATE']).sum()

重新分组
                     COUNT
REGION   DATE             
Brussels 2020-12-28     56
         2020-12-30      5
         2021-01-05    725
         2021-01-06    989
         2021-01-07    994
...                    ...
Wallonia 2021-06-18  49567
         2021-06-19  43577
         2021-06-20   2730
         2021-06-21  37193
         2021-06-22  16938

为了比较不同地区的疫苗接种 'speeds',我必须使用每个地区的人口将数据从绝对数转换为相对数。

我找到了一些解释如何在这样的多索引数据框中计算百分比的帖子,但问题是我想将每个 COUNT 除以原始数据框中不存在的人口数。

下面是人口数

REGION     POP
Flanders   6629143
Wallonia   3645243
Brussels   1218255

我认为解决方案必须循环遍历原始 df 并检查 REGION 或索引级别,但我完全不知道如何做。这是我想掌握的一项技术,因为当我想要其他一些具有不同人群(可能是 AGEGROUP 或 SEX)的子集时,它可能会派上用场。

非常感谢您阅读到这里!

免责声明:我才刚刚开始使用 Python,这是我在 Stack Overflow 上的第一个问题,所以请对我温柔点……我发布这个的原因是因为我在其他任何地方都找不到答案。这可能是因为我还没有记下术语,也不知道该找什么^_^

您可以在 groupby 上 运行 reset_index(),然后在执行计算的自定义函数上 运行 df.apply

import pandas as pd

df = pd.read_csv('https://epistat.sciensano.be/Data/COVID19BE_VACC.csv', parse_dates=['DATE'])
df = df.groupby(['REGION','DATE']).sum().reset_index()

def calculate(row):
    if row['REGION'] == 'Flanders':
        return row['COUNT'] / 6629143
    elif row['REGION'] == 'Wallonia':
        return row['COUNT'] / 3645243
    elif row['REGION'] == 'Brussels':
        return row['COUNT'] / 1218255
    
df['REL_COUNT'] = df.apply(calculate, axis=1) #axis=1 takes the rows as input, axis=0 would run on columns

输出df.head()

REGION DATE COUNT REL_COUNT
0 Brussels 2020-12-28 00:00:00 56 0.000046
1 Brussels 2020-12-30 00:00:00 5 0.000004
2 Brussels 2021-01-05 00:00:00 725 0.000595
3 Brussels 2021-01-06 00:00:00 989 0.000812
4 Brussels 2021-01-07 00:00:00 994 0.000816

一种选择是将 population_df 重新格式化为 set_index + rename:

population_df = pd.DataFrame({
    'REGION': {0: 'Flanders', 1: 'Wallonia', 2: 'Brussels'},
    'POP': {0: 6629143, 1: 3645243, 2: 1218255}
})

denom = population_df.set_index('REGION').rename(columns={'POP': 'COUNT'})

denom:

            COUNT
REGION           
Flanders  6629143
Wallonia  3645243
Brussels  1218255

然后divgroupby sum相对于level=0的结果:

new_df = df.groupby(['REGION', 'DATE']).agg({'COUNT': 'sum'}).div(denom, level=0)

new_df:

                        COUNT
REGION   DATE                
Brussels 2020-12-28  0.000046
         2020-12-30  0.000004
         2021-01-05  0.000595
         2021-01-06  0.000812
         2021-01-07  0.000816
...                       ...
Wallonia 2021-06-18  0.013598
         2021-06-19  0.011954
         2021-06-20  0.000749
         2021-06-21  0.010203
         2021-06-22  0.004647

或作为新专栏:

new_df = df.groupby(['REGION', 'DATE']).agg({'COUNT': 'sum'})
new_df['NEW'] = new_df.div(denom, level=0)

new_df:

                     COUNT       NEW
REGION   DATE                       
Brussels 2020-12-28     56  0.000046
         2020-12-30      5  0.000004
         2021-01-05    725  0.000595
         2021-01-06    989  0.000812
         2021-01-07    994  0.000816
...                    ...       ...
Wallonia 2021-06-18  49567  0.013598
         2021-06-19  43577  0.011954
         2021-06-20   2730  0.000749
         2021-06-21  37193  0.010203
         2021-06-22  16938  0.004647