在熊猫中带有“通配符”的查找表

时间:2019-03-08 22:45:55

标签: python pandas

几天来我一直在寻找答案,但是在其他线程中找不到类似的东西。

我有一个查找表来定义一些输入数据的分类。分类取决于大陆,国家和城市。但是,某些类别可能取决于这些变量的子集,例如仅大陆和国家(无城市)。此类查找表的示例如下。在我的示例中,我将一星和两星用作通配符:  -一星:我希望将法国的所有城市都归类为法国,并且  -两颗星:美国的所有城市,但纽约和旧金山除外,为美国-其他。

lookup_df = pd.DataFrame({'Continent': ['Europe', 'Europe', 'Asia', 'America', 'America', 'America', 'America', 'Africa'], 
                     'Country': ['France', 'Italy', 'Japan', 'USA', 'USA', 'USA', 'Argentina', '*'],
                     'City': ['*', '*', '*', 'New York', 'San Francisco', '**', '*', '*'],
                     'Classification': ['France', 'Italy', 'Japan', 'USA - NY', 'USA - SF', 'USA - Other', 'Argentina', 'Africa']})

如果我的数据框是

df = pd.DataFrame({'Continent': ['Europe', 'Europe', 'Asia', 'America ', 'America', 'America', 'Africa'], 
               'Country': ['France', 'Italy', 'Japan', 'USA', 'USA', 'USA', 'Egypt'], 
               'City': ['Paris', 'Rome', 'Tokyo', 'San Francisco', 'Houston', 'DC', 'Cairo']})

我正在尝试获得以下结果:

    Continent   Country     City            Classification
0   Europe      France      Paris           France
1   Europe      Italy       Rome            Italy
2   Asia        Japan       Tokyo           Japan
3   America     USA         San Francisco   USA - SF
4   America     USA         Houston         USA - Other
5   America     USA         DC              USA - Other
6   Africa      Egypt       Cairo           Africa

我需要从查找表或类似表开始,因为它更易于维护,易于解释并且也被其他进程使用。我无法创建完整表格,因为我必须考虑世界上所有可能的城市。

有什么pythonic的方法可以做到这一点吗?我以为可以使用pd.merge,但是我没有在网上找到任何示例。

1 个答案:

答案 0 :(得分:0)

一种易于维护的方法是使用地图:

Toplevel

注意:您第4行上的原始df2 = df.copy() # below will yield a field df2.Classification and save the value when all "Continent", "Country" and "City" match, otherwise np.nan df2 = df2.merge(lookup_df, how='left', on = ["Continent", "Country", "City"]) # create map1 from lookup_df when City is '*' but Country is not '*' map1 = lookup_df.loc[lookup_df.City.str.match('^\*+$') & ~lookup_df.Country.str.match('^\*+$')].set_index(['Continent','Country']).Classification.to_dict() map1 #{('Europe', 'France'): 'France', # ('Europe', 'Italy'): 'Italy', # ('Asia', 'Japan'): 'Japan', # ('America', 'USA'): 'USA - Other', # ('America', 'Argentina'): 'Argentina'} # create map2 from lookup_df when both City and Country are '*' map2 = lookup_df.loc[lookup_df.City.str.match('^\*+$') & lookup_df.Country.str.match('^\*+$')].set_index('Continent').Classification.to_dict() map2 #{'Africa': 'Africa'} # create a function to define your logic: def set_classification(x): return x.Classification if x.Classification is not np.nan else \ map1[(x.Continent, x.Country)] if (x.Continent, x.Country) in map1 else \ map2[x.Continent] if x.Continent in map2 else \ np.nan # apply the above function to each row of the df2 df2["Classification"] = df2.apply(set_classification, axis = 1) 包含一个额外的尾随空格df.Continent,它将使以上'America '行失败。您仍然需要解决此数据问题。