【问题标题】:Mapping country name to multiple-region designation将国家名称映射到多区域名称
【发布时间】:2022-01-20 13:47:13
【问题描述】:

我有一个包含 'COUNTRY' 列的数据框。我想在数据框中插入一个新列 'REGION',该列在每一行中都包含该国家所属地区的列表。例如,如果 'COUNTRY' 列是:

In [5]: df['COUNTRY']
Out[5]: 
0            ITALY
1    UNITED STATES
2            CHINA
3           FRANCE
4           BRAZIL
Name: COUNTRY, dtype: object

我希望 'REGION' 列是:

df['REGION']
Out[8]: 
0          [ROW, EU]
1    [UNITED STATES]
2        [ROW, ASIA]
3          [ROW, EU]
4          [ROW]
Name: REGION, dtype: object

'ROW' 代表世界其他地区,'EU' 代表欧洲等。

我使用np.select() 尝试了以下操作,但出现错误。

    # insert region column
    condlist = [
        (df.COUNTRY == 'ITALY'),
        (df.COUNTRY == 'UNITED STATES'),
        (df.COUNTRY != 'UNITED STATES'),
        (df.COUNTRY == 'CHINA'),
    ]
    region = [
        ['ROW', 'EU'],
        ['UNITED STATES'],
        ['ROW'],
        ['ROW', 'ASIA']
    ]
    print(np.select(condlist, region, ['ROW']))

请注意,对于未包含在condlist[] 测试中的国家/地区,我想为其分配区域['ROW']

我得到的错误是:

ValueError: shape mismatch: objects cannot be broadcast to a single shape

【问题讨论】:

    标签: python pandas dataframe numpy


    【解决方案1】:

    这是我相信的一种方式。不幸的是,我无法将不同大小的列表放入 Dataframe,因此您只需查询 Region 的内容以确定“ROW”和“EU”是否存在。

    countries = ['ITALY', 'UNITED STATES', 'CHINA', 'FRANCE', 'BRAZIL']
    
    regions = [['ROW, EU'], ['UNITED STATES'], ['ROW, ASIA'], ['ROW, EU'], ['ROW']]
    
    region_map = dict(zip(countries, regions))
    
    df = pd.DataFrame(data={'COUNTRY': countries})
    
    df['REGION'] = ""
    
    for country in region_map:
        df.loc[df['COUNTRY'] == country, 'REGION'] = region_map[country]
    
    print(df)
    
             COUNTRY         REGION
    0          ITALY        ROW, EU
    1  UNITED STATES  UNITED STATES
    2          CHINA      ROW, ASIA
    3         FRANCE        ROW, EU
    4         BRAZIL            ROW
    

    【讨论】:

      【解决方案2】:

      我喜欢@nanobennett 的解决方案的地方是使用字符串来表示区域而不是列表。对区域使用字符串可以更轻松地将区域插入数据框列并使用 .str 访问器进行操作。这是我最终做的:

         regions = countries.copy()
         for country in countries.unique():
      
                 region = ''
      
                 # ROW
                 if country != 'UNITED STATES':
                     region += 'ROW, '
      
                 # all other countries
                 if country in alant.local.EU:
                     region += 'EU, '
                     if country in alant.local.DACH:
                         region += 'DACH, '
                     elif country in alant.local.NORDIC:
                         region += 'NORDIC, '
                     elif country in alant.local.BENELUX:
                         region += 'BENELUX, '
                 elif country in alant.local.SA:
                     region += 'SA, '
                 elif country in ['CANADA', 'UNITED STATES']:
                     region += 'NA, '
                     if country == 'UNITED STATES':
                         region += 'US, '
      
                 # special country blocs
                 if country in alant.local.BRICS:
                     region += 'BRICS, '
      
                 regions[countries == country] = region.rstrip(' ,')
      
         return regions
      

      if elif 测试中使用的列表的位置: alant.local.EU 是欧洲国家列表,alant.local.DACH 是 DACH 国家列表,即 ['AUSTRIA', 'GERMANY', 'SWITZERLAND'] 等。

      我相信这个解决方案可以改进,也许使用 3.10 的 switch 语句,以及 pycountry 或其他我不知道的包。但现在它为我完成了这项工作。

      【讨论】: