【问题标题】:Divide Pandas dataframe with multiindex by another dataframe with smaller multiindex将具有多索引的 Pandas 数据帧除以具有较小多索引的另一个数据帧
【发布时间】:2020-08-03 21:22:18
【问题描述】:

我想将具有多索引的数据帧中的所有列除以具有多索引的另一个数据帧,小一级。飞蛾指数的前两个级别是相同的。第三级应该是广播的。

df_0 = pd.DataFrame( {
    "col0": [ 1, 2, 3, 4, 5 ],
    "col1": [ 3, 6, 9, 12, 15 ],
} )
df_0.index = pd.MultiIndex.from_tuples(
    [ ( "A", "a", 0 ), ( "A", "a", 1 ), ( "A", "b", 0 ), ( "A", "b", 1 ), ( "B", "b", 0 ) ]
)
df_0.index.names = [ "foo", "bar", "baz" ]

df_1 = pd.DataFrame( {
    "stuff": [ 100, 110, 120, 130, ],
} )
df_1.index = pd.MultiIndex.from_tuples(
    [ ( "A", "a" ), ( "A", "b" ), ( "B", "a" ), ( "B", "b" ) ]
)
df_1.index.names = [ "foo", "bar" ]
print( df_0 )
print( df_1 )

这给了我以下两个数据框df_0

             col0  col1
foo bar baz            
A   a   0       1     3
        1       2     6
    b   0       3     9
        1       4    12
B   b   0       5    15

df_1

         stuff
foo bar       
A   a      100
    b      110
B   a      120
    b      130

如果我尝试将每个列值除以相应的 stuff 列,我会收到一条错误消息

print( df_0.div( df_1 ) )
Join on level between two MultiIndex objects is ambiguous

我想要达到的是以下结果:

              col0    col1
foo bar baz            
A   a   0    1/100   3/100
        1    2/100   6/100
    b   0    3/110   9/110
        1    4/110  12/110
B   b   0    5/130  15/130

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    首先使用DataFrame.reindex DataFrame,所以两个级别都相同,所以可能除以Seriesstuff 选择:

    df = df_0.div(df_1.reindex(df_0.index)['stuff'], axis=0)
    print (df)
                     col0      col1
    foo bar baz                    
    A   a   0    0.010000  0.030000
            1    0.020000  0.060000
        b   0    0.027273  0.081818
            1    0.036364  0.109091
    B   b   0    0.038462  0.115385
    

    详情

    print( df_1.reindex(df_0.index)['stuff'] )
    foo  bar  baz
    A    a    0      100
              1      100
         b    0      110
              1      110
    B    b    0      130
    Name: stuff, dtype: int64
    

    【讨论】:

    • 使用 Pandas 0.22.0 df_1.reindex(df_0.index)['stuff'] 导致数据框仅填充 NaNs。更新到 Pandas 1.0.3 后,它的行为符合预期并显示在答案中。
    • @leviathan - 谢谢你的信息。我猜它在0.22.0 中不起作用,因为错误。
    【解决方案2】:

    您首先需要join 数据帧,以便索引对齐,然后然后执行操作:

    df = df_0.join(df_1)
    df['col0'] = df.col0/df.stuff
    df['col1'] = df.col1/df.pop('stuff')
    
                   col0      col1
    foo bar baz                    
    A   a   0    0.010000  0.030000
            1    0.020000  0.060000
        b   0    0.027273  0.081818
            1    0.036364  0.109091
    B   b   0    0.038462  0.115385
    

    如果您的 pandas 版本过时,您可能会收到 NotImplementedError。在这种情况下,reset_indexmerge 的替代方法是:

    df = df_0.reset_index().merge(df_1, on=['foo', 'bar']).set_index(['foo', 'bar','baz'])
    

    【讨论】:

    • 如果我尝试df_0.join(df_1),我会收到错误消息:“NotImplementedError: 未实现多索引上的多级重叠合并”我使用的是 Pandas 0.22.0 版。
    • 你有什么版本的熊猫@leviathan?它适用于我的 pandas 1。
    • 我将 Pandas 更新到 1.0.3 版,现在可以使用了。
    猜你喜欢
    • 2021-12-13
    • 1970-01-01
    • 2020-09-13
    • 2017-06-20
    • 2022-12-17
    • 2021-05-16
    • 2017-02-06
    • 2015-06-21
    相关资源
    最近更新 更多