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

问题描述 投票:0回答:1

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

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

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,但我没有在网上找到任何这个例子。

python pandas
1个回答
0
投票

一种易于维护的方法来处理您的任务是使用地图:

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)

注意:你在第4行的原始df.Continent包含一个额外的尾随空间'America ',这将失败上面的df2 = df2.merge(...)线。您需要修复此数据问题。

© www.soinside.com 2019 - 2024. All rights reserved.