Pandas 使用多索引为部分列设置值
Pandas set values for part of column with multiindex
我确定有一个简单的方法可以做到这一点,但我似乎找不到它。
本质上,我有一个 DataFrame
和 MultiIndex
,我想用 Series
设置列的一部分(对应于第一个索引级别中的值)。但是,无论我尝试什么,值都被设置为 NaN
,即使索引名称对齐。
我尝试过的例子:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(12).reshape(4, 3),
columns=['col1', 'col2', 'col3'],
index=pd.MultiIndex.from_product((('a1', 'a2'), ('b1', 'b2')),
names=['idx1', 'idx2']))
s = pd.Series([100, 101], index=['b1', 'b2'], name='col3')
df.loc['a1', 'col3'] = s
在此之后,我希望 df
成为
col1 col2 col3
idx1 idx2
a1 b1 0 1 100
b2 3 4 101
a2 b1 6 7 8
b2 9 10 11
但它是
col1 col2 col3
idx1 idx2
a1 b1 0 1 NaN
b2 3 4 NaN
a2 b1 6 7 8.0
b2 9 10 11.0
关于如何在没有 .to_numpy()
或 .to_list()
的情况下实现此目标的任何想法(从那时起我需要手动检查项目的顺序)一个班轮没有做像
这样荒谬的事情
df.loc['a1', 'col3'] = s.to_frame().eval('idx1 = "a1"').reset_index().set_index(['idx1', 'idx2'])
您可以使用s.to_numpy()
或s.tolist()
:
>>> df.loc['a1', 'col3'] = s.to_numpy()
col1 col2 col3
idx1 idx1
a1 b1 0 1 100.0
b2 3 4 101.0
a2 b1 6 7 8.0
b2 9 10 11.0
使用:
df.loc['a1', 'col3'] = [100, 101]
输出:
根据您的评论:
s = pd.Series([100, 101], index=['b1', 'b2'], name='col3')
s = s.to_list()
df.loc['a1', 'col3'] = s
具有相同的输出。
基于其他评论!:
s = pd.Series([100, 101], index=(('a1', 'b1'), ('a1', 'b2')), name='col3')
df.loc['a1', 'col3'] = s
输出:
假设您没有在 df 索引中不存在的 in s 值,您可以这样做:
df.loc[('a1', s.index), 'col3'] = s.values
这将独立于 s 的顺序工作
输出:
col1 col2 col3
idx1 idx2
a1 b1 0 1 100
b2 3 4 101
a2 b1 6 7 8
b2 9 10 11
我确定有一个简单的方法可以做到这一点,但我似乎找不到它。
本质上,我有一个 DataFrame
和 MultiIndex
,我想用 Series
设置列的一部分(对应于第一个索引级别中的值)。但是,无论我尝试什么,值都被设置为 NaN
,即使索引名称对齐。
我尝试过的例子:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(12).reshape(4, 3),
columns=['col1', 'col2', 'col3'],
index=pd.MultiIndex.from_product((('a1', 'a2'), ('b1', 'b2')),
names=['idx1', 'idx2']))
s = pd.Series([100, 101], index=['b1', 'b2'], name='col3')
df.loc['a1', 'col3'] = s
在此之后,我希望 df
成为
col1 col2 col3
idx1 idx2
a1 b1 0 1 100
b2 3 4 101
a2 b1 6 7 8
b2 9 10 11
但它是
col1 col2 col3
idx1 idx2
a1 b1 0 1 NaN
b2 3 4 NaN
a2 b1 6 7 8.0
b2 9 10 11.0
关于如何在没有 .to_numpy()
或 .to_list()
的情况下实现此目标的任何想法(从那时起我需要手动检查项目的顺序)一个班轮没有做像
df.loc['a1', 'col3'] = s.to_frame().eval('idx1 = "a1"').reset_index().set_index(['idx1', 'idx2'])
您可以使用s.to_numpy()
或s.tolist()
:
>>> df.loc['a1', 'col3'] = s.to_numpy()
col1 col2 col3
idx1 idx1
a1 b1 0 1 100.0
b2 3 4 101.0
a2 b1 6 7 8.0
b2 9 10 11.0
使用:
df.loc['a1', 'col3'] = [100, 101]
输出:
根据您的评论:
s = pd.Series([100, 101], index=['b1', 'b2'], name='col3')
s = s.to_list()
df.loc['a1', 'col3'] = s
具有相同的输出。
基于其他评论!:
s = pd.Series([100, 101], index=(('a1', 'b1'), ('a1', 'b2')), name='col3')
df.loc['a1', 'col3'] = s
输出:
假设您没有在 df 索引中不存在的 in s 值,您可以这样做:
df.loc[('a1', s.index), 'col3'] = s.values
这将独立于 s 的顺序工作
输出:
col1 col2 col3
idx1 idx2
a1 b1 0 1 100
b2 3 4 101
a2 b1 6 7 8
b2 9 10 11