在 pandas 中使用多索引设置值
Setting values with multiindex in pandas
关于 SO 已经有几个与此相关的问题,最著名的是 ,但是 none 的答案似乎对我有用,并且有很多文档链接(尤其是在lexsorting) 坏了,所以我会问另一个。
我正在尝试做一些(看似)非常简单的事情。考虑以下多索引数据框:
import pandas as pd; import random
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.concat([pd.Series(np.random.randn(8), index=index), pd.Series(np.random.randn(8), index=index)], axis=1)
现在我想将列 0
中的所有值设置为某个值(比如 np.NaN
),用于类别 one
中的观察。我失败了:
df.loc(axis=0)[:, "one"][0] = 1 # setting with copy warning
和
df.loc(axis=0)[:, "one", 0] = 1
这要么会产生关于键长度超过索引长度的警告,要么会产生关于缺乏足够深度的词法排序的警告。
正确的做法是什么?
我认为您可以使用 loc
和元组来选择 MultiIndex
和 0
来选择列:
import pandas as pd;
import random
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
#add for testing
np.random.seed(0)
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.concat([pd.Series(np.random.randn(8), index=index), pd.Series(np.random.randn(8), index=index)], axis=1)
print df
0 1
first second
bar one 1.764052 -0.103219
two 0.400157 0.410599
baz one 0.978738 0.144044
two 2.240893 1.454274
foo one 1.867558 0.761038
two -0.977278 0.121675
qux one 0.950088 0.443863
two -0.151357 0.333674
df.loc[('bar', "one"), 0] = 1
print df
0 1
first second
bar one 1.000000 -0.103219
two 0.400157 0.410599
baz one 0.978738 0.144044
two 2.240893 1.454274
foo one 1.867558 0.761038
two -0.977278 0.121675
qux one 0.950088 0.443863
two -0.151357 0.333674
如果您需要将级别 second
中的所有行设置为值 one
,请使用 slice(None)
:
df.loc[(slice(None), "one"), 0] = 1
print df
0 1
first second
bar one 1.000000 -0.103219
two 0.400157 0.410599
baz one 1.000000 0.144044
two 2.240893 1.454274
foo one 1.000000 0.761038
two -0.977278 0.121675
qux one 1.000000 0.443863
two -0.151357 0.333674
Docs.
关于 SO 已经有几个与此相关的问题,最著名的是
我正在尝试做一些(看似)非常简单的事情。考虑以下多索引数据框:
import pandas as pd; import random
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.concat([pd.Series(np.random.randn(8), index=index), pd.Series(np.random.randn(8), index=index)], axis=1)
现在我想将列 0
中的所有值设置为某个值(比如 np.NaN
),用于类别 one
中的观察。我失败了:
df.loc(axis=0)[:, "one"][0] = 1 # setting with copy warning
和
df.loc(axis=0)[:, "one", 0] = 1
这要么会产生关于键长度超过索引长度的警告,要么会产生关于缺乏足够深度的词法排序的警告。
正确的做法是什么?
我认为您可以使用 loc
和元组来选择 MultiIndex
和 0
来选择列:
import pandas as pd;
import random
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
#add for testing
np.random.seed(0)
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.concat([pd.Series(np.random.randn(8), index=index), pd.Series(np.random.randn(8), index=index)], axis=1)
print df
0 1
first second
bar one 1.764052 -0.103219
two 0.400157 0.410599
baz one 0.978738 0.144044
two 2.240893 1.454274
foo one 1.867558 0.761038
two -0.977278 0.121675
qux one 0.950088 0.443863
two -0.151357 0.333674
df.loc[('bar', "one"), 0] = 1
print df
0 1
first second
bar one 1.000000 -0.103219
two 0.400157 0.410599
baz one 0.978738 0.144044
two 2.240893 1.454274
foo one 1.867558 0.761038
two -0.977278 0.121675
qux one 0.950088 0.443863
two -0.151357 0.333674
如果您需要将级别 second
中的所有行设置为值 one
,请使用 slice(None)
:
df.loc[(slice(None), "one"), 0] = 1
print df
0 1
first second
bar one 1.000000 -0.103219
two 0.400157 0.410599
baz one 1.000000 0.144044
two 2.240893 1.454274
foo one 1.000000 0.761038
two -0.977278 0.121675
qux one 1.000000 0.443863
two -0.151357 0.333674
Docs.