【问题标题】:Assigning values to Pandas Multiindex DataFrame by index level按索引级别为 Pandas Multiindex DataFrame 赋值
【发布时间】:2015-07-19 00:23:02
【问题描述】:

我有一个 Pandas 多索引数据框,我需要将值分配给系列中的一列。该系列与数据帧的第一级索引共享其索引。

import pandas as pd
import numpy as np
idx0 = np.array(['bar', 'bar', 'bar', 'baz', 'foo', 'foo'])
idx1 = np.array(['one', 'two', 'three', 'one', 'one', 'two'])
df = pd.DataFrame(index = [idx0, idx1], columns = ['A', 'B'])
s = pd.Series([True, False, True],index = np.unique(idx0))
print df
print s

出来:

             A    B
bar one    NaN  NaN
    two    NaN  NaN
    three  NaN  NaN
baz one    NaN  NaN
foo one    NaN  NaN
    two    NaN  NaN

bar     True
baz    False
foo     True
dtype: bool

这些不起作用:

df.A = s # does not raise an error, but does nothing
df.loc[s.index,'A'] = s # raises an error

预期输出:

             A     B
bar one    True   NaN
    two    True   NaN
    three  True   NaN
baz one    False  NaN
foo one    True   NaN
    two    True   NaN

【问题讨论】:

    标签: python pandas multi-index


    【解决方案1】:

    系列(和字典)可以像使用 map 和 apply 的函数一样使用(感谢@normanius 改进了语法):

    df['A'] = pd.Series(df.index.get_level_values(0)).map(s).values
    

    或类似:

    df['A'] = df.reset_index(level=0)['level_0'].map(s).values
    

    结果:

    A    B
    bar one     True  NaN
        two     True  NaN
        three   True  NaN
    baz one    False  NaN
    foo one     True  NaN
        two     True  NaN
    

    【讨论】:

    • 我想知道这是否是一个错误,如果传递的值具有可以对齐的索引值,它不起作用,无论如何 +1
    • 我无法弄清楚应该使用什么语法来分配值 .loc,希望会有更好的熊猫人来回答这个问题。对我来说,这应该只是工作,所以必须有一种方法可以做到这一点而不诉诸map
    • 哦,我以为你指的是别的东西。我认为地图是一种很好的方式来做到这一点。也可以通过合并来完成,但我怀疑这会慢一些(但可能更容易阅读)。
    • @JohnE:我建议写df['A'] = pd.Series(df.index.get_level_values(0)).map(s).values,这比你的例子更健壮而且更清晰。
    • @normanius 谢谢!我什至不记得回答过这个问题,但完全同意您的评论并已编辑以包含您的建议。
    【解决方案2】:

    df.A = s 不会引发错误,但什么也不做

    确实应该有效。您的观点实际上与mine有关。

    ᐊᐊ 解决方法 ᐊᐊ

    >>> s.index = pd.Index((c,) for c in s.index)  # ᐊᐊᐊᐊᐊᐊᐊᐊ
    >>> df.A = s
    >>> df
                   A    B
    bar one     True  NaN
        two     True  NaN
        three   True  NaN
    baz one    False  NaN
    foo one     True  NaN
        two     True  NaN
    

    为什么上述方法有效?

    因为当您直接执行df.A = s 没有解决方法时,您实际上是在尝试在子类实例中分配包含pandas.Index 的坐标,不知何故,它看起来像是LS principle 的“反对派”,即pandas.MultiIndex 的一个实例。我的意思是,寻找自己:

    >>> type(s.index).__name__
    'Index'
    

    >>> type(df.index).__name__
    'MultiIndex'
    

    因此,此解决方法是将s 的索引转换为一维pandas.MultiIndex 实例。

    >>> s.index = pd.Index((c,) for c in s.index)
    >>> type(s.index).__name__
    'MultiIndex'
    

    并没有明显改变

    >>> s
    bar     True
    baz    False
    foo     True
    dtype: bool
    

    一个想法: 从许多观点(数学的、本体论的)来看,这一切都表明pandas.Index 应该被设计为pandas.MultiIndex 的子类,而不是与现在相反。

    【讨论】:

    • @EdChum 上述解决方法可能会让您了解当前正在工作的错误类型。
    猜你喜欢
    • 2017-10-16
    • 2019-01-26
    • 2020-06-05
    • 2018-06-24
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 2020-05-19
    相关资源
    最近更新 更多