【问题标题】:Unable to merge multiIndexed pandas dataframes无法合并多索引熊猫数据框
【发布时间】:2016-08-24 16:30:13
【问题描述】:

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

每个 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 中的相应标签匹配?

【问题讨论】:

  • 您可能需要在首次创建这些 DataFrame 时考虑解决此问题,而不是在合并之前。查看df1,您似乎有零填充整数字符串,例如'02'。如果将其转换为df2 中的常规整数,它将只是2,并且将其转换为字符串不会给出零填充,并且不会在'02''2' 之间发生合并。当您转换为字符串时,您可以添加一个零填充单个字符的额外步骤,但似乎最好在初始化时获得正确的 dtype。
  • 绝对是好的做法@root

标签: python pandas


【解决方案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

【讨论】:

    猜你喜欢
    • 2019-03-18
    • 2018-02-02
    • 2021-03-25
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多