如何使用映射变量重新索引数据帧?

时间:2016-06-19 11:45:37

标签: python pandas indexing dataframe mapping

我有以下数据框:

                  population   GDP
country
United Kingdom    4.5m         10m
Spain             3m           8m
France            2m           6m

我在2列数据框中也有以下信息(很高兴将其作为另一个数据结构,如果这将更有益,因为计划是它将在VARS文件中排序。

county           code
Spain            es
France           fr
United Kingdom   uk

“映射”数据结构将按随机顺序排序,因为将随机添加/删除国家/地区。

从国家/地区名称将数据框重新索引到其国家/地区代码的最佳方法是什么?

是否有一个智能解决方案也适用于其他列,例如,如果数据框是在日期编制索引但是一列是df['county']那么您可以将df['country']更改为其国家/地区代码?最后是否有第三个选项可以添加一个额外的列,该列是国家/代码,它根据另一列中的国家/地区名称选择了正确的代码?

2 个答案:

答案 0 :(得分:2)

我认为您可以使用Series.map,但它仅适用于Series,因此需要Index.to_series。上次rename_axispandas 0.18.0中的新内容):

df1.index = df1.index.to_series().map(df2.set_index('county').code)
df1 = df1.rename_axis('county')
#pandas bellow 0.18.0
#df1.index.name = 'county'
print (df1)
       population  GDP
county                
uk           4.5m  10m
es             3m   8m
fr             2m   6m

dict

的映射相同
d = df2.set_index('county').code.to_dict()
print (d)
{'France': 'fr', 'Spain': 'es', 'United Kingdom': 'uk'}

df1.index = df1.index.to_series().map(d)
df1 = df1.rename_axis('county')
#pandas bellow 0.18.0
#df1.index.name = 'county'
print (df1)
       population  GDP
county                
uk           4.5m  10m
es             3m   8m
fr             2m   6m

编辑:

使用Index.map的另一个解决方案,因此省略to_series

d = df2.set_index('county').code.to_dict()
print (d)
{'France': 'fr', 'Spain': 'es', 'United Kingdom': 'uk'}

df1.index = df1.index.map(d.get)
df1 = df1.rename_axis('county')
#pandas bellow 0.18.0
#df1.index.name = 'county'
print (df1)
       population  GDP
county                
uk           4.5m  10m
es             3m   8m
fr             2m   6m

答案 1 :(得分:0)

以下是一些简短的方法来解决您的3个问题。更多详情如下:

1)如何根据单独的df

中的映射来更改索引

使用df_with_mapping.todict("split")创建字典,然后使用列表推导将其更改为{"old1":"new1",...,"oldn":"newn"}表单,然后使用df.index = df.base_column.map(dictionary)获取更改的索引。

2)如果新列在同一个df中,如何更改索引:

df.index = df["column_you_want"]

3)通过映射旧列来创建新列:

df["new_column"] = df["old_column"].map({"old1":"new1",...,"oldn":"newn"})

1)当前索引的映射存在于单独的数据框中,但您还没有数据框中的映射列

这与问题2基本相同,还有为您想要的映射创建字典的附加步骤。

#creating the mapping dictionary in the form of current index : future index

df2 = pd.DataFrame([["es"],["fr"]],index = ["spain","france"])
interm_dict = df2.to_dict("split") #Creates a dictionary split into column labels, data labels and data
mapping_dict = {country:data[0] for country,data in zip(interm_dict["index"],interm_dict['data'])}
#We only want the first column of the data and the index so we need to make a new dict with a list comprehension and zip

df["country"] = df.index #Create a new column if u want to save the index
df.index = pd.Series(df.index).map(mapping_dict) #change the index
df.index.name = "" #Blanks out index name
df = df.drop("county code",1) #Drops the county code column to avoid duplicate columns

在:

       county code language
spain           es  spanish
france          fr   french

后:

   language country

es  spanish   spain
fr   french  france

2)将当前索引更改为数据框中已有的列之一

df = pd.DataFrame([["es","spanish"],["fr","french"]], columns = ["county code","language"], index = ["spain", "french"])
df["country"] = df.index #if you want to save the original index
df.index = df["county code"]  #The only step you actually need
df.index.name = "" #if you want a blank index name
df = df.drop("county code",1) #if you dont want the duplicate column

在:

   county code language
spain           es  spanish
french          fr   french

后:

   language country

es  spanish   spain
fr   french  french

3)根据其他列创建其他列 除了我们创建一个额外的列而不是为创建的系列分配.index之外,这与第2步基本相同。

df = pd.DataFrame([["es","spanish"],["fr","french"]], columns = ["county code","language"], index = ["spain", "france"])
df["city"] = df["county code"].map({"es":"barcelona","fr":"paris"})

在:

       county code language
spain           es  spanish
france          fr   french

后:

       county code language       city
spain           es  spanish  barcelona
france          fr   french      paris