按索引级别为Pandas Multiindex DataFrame分配值

时间:2015-05-08 07:08:18

标签: python pandas multi-index

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

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

2 个答案:

答案 0 :(得分:6)

系列(和字典)可以像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 :(得分:1)

<块引用>

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 应该被设计为 {{3} 的子类},而不是相反,就像目前一样。