索引/ MultiIndex中的字符串替换

时间:2015-07-24 14:13:00

标签: python pandas

我有一个MultiIndex版本的DataFrame,其中包含以下国家/地区的代码:

In [3]: idx = pd.MultiIndex.from_tuples([('AUS', 'a'), ('AUS', 'b'), ('BRA', 'a')])

In [4]: idx.names = ['country', 'foo']
In [5]: df = pd.DataFrame([4,5,6], index=idx)
In [6]: df
Out[6]: 
             0
country foo   
AUS     a    4
        b    5
BRA     a    6

我还有一个带有值的字典,用以下代码替换我的代码:

In [7]: codes = dict(AUS='Australia', BRA='Brazil')

我想做相当于df.replace(codes)但是在索引级别上(无论是所有级别,还是特定级别,我都不介意)

输出如下:

               0
country   foo
Australia a    4
          b    5
Brazil    a    6

我目前正以非常愚蠢的方式做这件事:

In [21]: replaced = [pd.Series(df.index.get_level_values(i)).replace(codes) for i in range(len(df.index.levels))]
In [22]: replaced_tuples = zip(*replaced)
In [23]: new_idx = pd.MultiIndex.from_tuples(replaced_tuples)
In [27]: df_replaced = pd.DataFrame(df.values, index=new_idx)
In [28]: df_replaced
Out[28]: 
             0
Australia a  4
          b  5
Brazil    a  6

面对我的那种更好的方式是什么? (请注意,此方法甚至不保留级别名称,因此它是全面坏的。)

2 个答案:

答案 0 :(得分:2)

您可以在多索引上调用set_levels并传递新名称,您必须创建一个与您的级别名称相同的列表,因为这不保证顺序:

In [380]:
country_code_list = [codes[x] for x in df.index.get_level_values(0).unique()]
df.index.set_levels(country_code_list, level='country', inplace=True)
df

Out[380]:
               0
country   foo   
Australia a    4
          b    5
Brazil    a    6

答案 1 :(得分:0)

这是一种看似合理的方式。不确定如何将效率/可读性与@ EdChum的回答进行比较:

In [46]: df.reset_index().replace(codes).set_index(df.index.names)
Out[46]: 
               0
country   foo   
Australia a    4
          b    5
Brazil    a    6

显然,这里的缺点是replace将在DataFrame中替换,而不仅仅在索引列中。

从好的方面来说,这样做可以像正则表达式一样访问replace的所有功能。

如果您真的关心仅在中替换索引,您可以执行以下任一操作:

codes_dict = dict(country=codes)

codes_dict = {k: codes for k in df.index.names}

然后在codes的调用中最后更改codes_dict的{​​{1}}。完美!