在Pandas MultiIndex DataFrame中更改特定列值

2 投票
2 回答
3489 浏览
提问于 2025-04-18 05:04

假设我们有一个这样的数据表:

myDF = DataFrame(np.random.randn(4,2), index= [[1,1,2,2],['Mon','Tue','Mon','Tue']])
myDF

             0           1
1   Mon -0.910930    1.592856
    Tue -0.167228   -0.763317
2   Mon -0.926121   -0.718729
    Tue  0.372288   -0.417337

如果我想把第一列的所有行中索引为1的值改掉,我尝试这样做:

myDF.ix[1,:][0] = 99

但是这样做没有效果,数据表没有改变。请问我漏掉了什么呢?谢谢!

2 个回答

1

我认为我们可以通过以下方法实现真正的灵活性:

index = [idx for idx, vals in enumerate(myDF.index.values) if vals[1] in ['Mon','Wed'] and vals[0] in [2,3,4]]
colums = [0,1]
myDF.iloc[index, columns] = 99

在for循环中创建索引并不是最有效的方法,所以可以创建一个字典,字典的键是多重索引的元组,值是索引。

这样我们就可以指定想要更改的两个索引层级中的哪些值。
.xs()函数做的事情有点类似,但你不能通过这个函数来更改值。

如果有更简单的方法,我会很感兴趣去了解一下……

3

最近版本的pandas在你尝试做某些操作时会给出警告。例如,在0.13.1版本中,你会看到这样的提示:

In [4]: myDF.ix[1,:][0] = 99
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead

你所做的事情叫做链式赋值,这个操作因为numpy内部的一些细节问题而失败,而pandas正是依赖于numpy的。

你的情况比一般的警告所提到的要复杂,因为你使用了多重索引(MultiIndex)。如果你想选择外层标签为1的所有行,以及列标签为0的列,可以使用.loc[1, 0]。 (你也可以查看这个回答。)

In [5]: myDF.loc[1, 0] = 99

In [6]: myDF
Out[6]: 
           0         1
1 Mon  99.000000  1.609539
  Tue  99.000000  1.464771
2 Mon  -0.819186 -1.122967
  Tue  -0.545171  0.475277

撰写回答