按索引级别为Pandas多索引数据框赋值

bybem2ql  于 2023-01-07  发布在  其他
关注(0)|答案(3)|浏览(119)

我有一个Pandas多索引 Dataframe ,我需要为一个系列中的一列赋值。该系列与 Dataframe 的第一级索引共享其索引。

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
rqdpfwrv

rqdpfwrv1#

Series(和dictionary)可以像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
kr98yfug

kr98yfug2#

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的索引转换为1维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

***一个想法:***从许多Angular (数学的、本体论的)看,所有这些都表明pandas.Index应该被设计为pandas.MultiIndex的子类,而不是像现在这样相反。

qfe3c7zg

qfe3c7zg3#

可以对df DataFrame使用join方法,但需要相应地命名索引和序列:

>>> df.index.names = ('lvl0', 'lvl1')
>>> s.index.name = 'lvl0'
>>> s.name = 'new_col'

然后join方法在DataFrame中创建一个新列:

>>> df.join(s)
              A    B  new_col
lvl0 lvl1
bar  one    NaN  NaN     True
     two    NaN  NaN     True
     three  NaN  NaN     True
baz  one    NaN  NaN    False
foo  one    NaN  NaN     True
     two    NaN  NaN     True

要将其分配给现有列:

>>> df['A'] = df.join(s)['new_col']
>>> df
                A    B
lvl0 lvl1
bar  one     True  NaN
     two     True  NaN
     three   True  NaN
baz  one    False  NaN
foo  one     True  NaN
     two     True  NaN

相关问题