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

问题描述

我发现了这个关于 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

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

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

人口数量如下

REGION     POP
Flanders   6629143
Wallonia   3645243
Brussels   1218255

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

非常感谢您阅读到这里!

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

解决方法

一种选择是用 set_index + rename 重新格式化 population_df

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

然后div groupby 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
,

您可以在 reset_index() 上运行 groupby,然后在进行计算的自定义函数上运行 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()

区域 日期 COUNT REL_COUNT
0 布鲁塞尔 2020-12-28 00:00:00 56 0.000046
1 布鲁塞尔 2020-12-30 00:00:00 5 0.000004
2 布鲁塞尔 2021-01-05 00:00:00 725 0.000595
3 布鲁塞尔 2021-01-06 00:00:00 989 0.000812
4 布鲁塞尔 2021-01-07 00:00:00 994 0.000816