无法合并multiIndexed pandas数据帧

时间:2016-08-24 16:30:14

标签: python pandas

我相信我最终正在寻找一种方法来改变数据帧索引的类型。请允许我解释一下:

每个df在(相同的)四个级别上进行多索引。一个级别由整数,整数和字母(如D8)和字母组成。

但是,对于df1,索引标签中的整数用引号括起来,而对于df2,相同的整数标签没有任何引号;即,

df1.index.levels[1]  
Index(['Z5', '02', '1C', '26', '2G', '2S', '30', '46', '48', '5M', 'CSA', etc...'],     dtype='object', name='BMDIV')

df2.index.levels[1]  
Index([   26,    30,    46,    48,    72,  '1C',  '5M',  '7D',  '7Y',  '8F',
        '8J',  'AN',  'AS',  'C3',  'CA', etc.
      dtype='object', name='BMDIV')

当我尝试合并这些表时

df_merge = pd.merge(df1, df2, how='left', left_index=True, right_index=True)

我明白了:

  

TypeError:*之后的类型对象参数必须是序列,而不是映射

有没有办法改变df2中的标签类型,以便数字在引号中,因此可能与df1中的相应标签相匹配?

1 个答案:

答案 0 :(得分:1)

更改级别值的一种方法是构建新的MultiIndex并将其重新分配给df.index

import pandas as pd

df = pd.DataFrame(
    {'index':[ 26, 30, 46, 48, 72, '1C', '5M', '7D', '7Y', 
               '8F', '8J', 'AN', 'AS', 'C3', 'CA'], 
     'foo':1, 'bar':2})
df = df.set_index(['index', 'foo'])
level_values = [df.index.get_level_values(i) for i in range(index.nlevels)]
level_values[0] = level_values[0].astype(str)
df.index = pd.MultiIndex.from_arrays(level_values)

使得级别值为字符串:

In [53]: df.index.levels[0]
Out[56]: 
Index(['1C', '26', '30', '46', '48', '5M', '72', '7D', '7Y', '8F', '8J', 'AN',
       'AS', 'C3', 'CA'],
      dtype='object', name='index')

或者,您可以使用reset_indexset_value来避免一些低级别的混乱:

import pandas as pd

df = pd.DataFrame(
    {'index':[ 26, 30, 46, 48, 72, '1C', '5M', '7D', '7Y', 
               '8F', '8J', 'AN', 'AS', 'C3', 'CA'], 
     'foo':1, 'bar':2})
df = df.set_index(['index', 'foo'])

df = df.reset_index('index')
df['index'] = df['index'].astype(str)
df = df.set_index('index', append=True)
df = df.swaplevel(0, 1, axis=0)

再次产生字符串值索引级别值:

In [67]: df.index.levels[0]
Out[67]: 
Index(['1C', '26', '30', '46', '48', '5M', '72', '7D', '7Y', '8F', '8J', 'AN',
       'AS', 'C3', 'CA'],
      dtype='object', name='index')

在这两个选项中,using_MultiIndex更快:

N = 1000
def make_df(N):
    df = pd.DataFrame(
        {'index': np.random.choice(np.array(
            [26, 30, 46, 48, 72, '1C', '5M', '7D', '7Y', 
             '8F', '8J', 'AN', 'AS', 'C3', 'CA'], dtype='O'), size=N), 
         'foo':1, 'bar':2})
    df = df.set_index(['index', 'foo'])
    return df

def using_MultiIndex(df):
    level_values = [df.index.get_level_values(i) for i in range(index.nlevels)]
    level_values[0] = level_values[0].astype(str)
    df.index = pd.MultiIndex.from_arrays(level_values)
    return df

def using_reset_index(df):
    df = df.reset_index('index')
    df['index'] = df['index'].astype(str)
    df = df.set_index('index', append=True)
    df = df.swaplevel(0, 1, axis=0)
    return df


In [81]: %%timeit df = make_df(1000)
   ....: using_MultiIndex(df)
   ....: 
1000 loops, best of 3: 693 µs per loop

In [82]: %%timeit df = make_df(1000)
   ....: using_reset_index(df)
   ....: 
100 loops, best of 3: 2.09 ms per loop