2013-05-30 30 views
16

我想修改DataFrame中某列的某些值。目前我有一个视图从选择通过我的原始df的多索引(和修改确实改变df)。从MultiIndex DataFrame分配新值以切片

下面是一个例子:

In [1]: arrays = [np.array(['bar', 'bar', 'baz', 'qux', 'qux', 'bar']), 
        np.array(['one', 'two', 'one', 'one', 'two', 'one']), 
        np.arange(0, 6, 1)] 
In [2]: df = pd.DataFrame(randn(6, 3), index=arrays, columns=['A', 'B', 'C']) 

In [3]: df 
        A   B   C 
bar one 0 -0.088671 1.902021 -0.540959 
    two 1 0.782919 -0.733581 -0.824522 
baz one 2 -0.827128 -0.849712 0.072431 
qux one 3 -0.328493 1.456945 0.587793 
    two 4 -1.466625 0.720638 0.976438 
bar one 5 -0.456558 1.163404 0.464295 

我尝试修改的df片为标量值:

In [4]: df.ix['bar', 'two', :]['A'] 
Out[4]: 
1 0.782919 
Name: A, dtype: float64 

In [5]: df.ix['bar', 'two', :]['A'] = 9999 
# df is unchanged 

我真的想在列修改几个值(和自索引返回一个向量,而不是标量值,我认为这会更有意义):

In [6]: df.ix['bar', 'one', :]['A'] = [999, 888] 
# again df remains unchanged 

我使用的是熊猫0.11。有没有简单的方法来做到这一点?

目前的解决方案是重新创建一个新的df并修改我想要的值。但它不够高雅,可能会对复杂的数据帧造成很大影响。在我看来,问题应该来自.ix和.loc而不是返回一个视图,而是一个副本。

+0

why -1 vote?你能解释一下吗? – HadiM

+0

+1一个很好的问题,一个令人困惑的问题。唯一我能想到的是,由于标题不是描述性的,因此它被低估了。 (但是谁知道!) –

+1

对不起,但我不是英语母语的人,话题有点复杂,所以很难找到一个好的:-)如果你想给我一个标题,我可以改变当前一。 – HadiM

回答

10

排序的图像,然后使用一个元组的多指标

In [12]: df = pd.DataFrame(randn(6, 3), index=arrays, columns=['A', 'B', 'C']) 

In [13]: df 
Out[13]: 
        A   B   C 
bar one 0 -0.694240 0.725163 0.131891 
    two 1 -0.729186 0.244860 0.530870 
baz one 2 0.757816 1.129989 0.893080 
qux one 3 -2.275694 0.680023 -1.054816 
    two 4 0.291889 -0.409024 -0.307302 
bar one 5 1.697974 -1.828872 -1.004187 

In [14]: df = df.sortlevel(0) 

In [15]: df 
Out[15]: 
        A   B   C 
bar one 0 -0.694240 0.725163 0.131891 
     5 1.697974 -1.828872 -1.004187 
    two 1 -0.729186 0.244860 0.530870 
baz one 2 0.757816 1.129989 0.893080 
qux one 3 -2.275694 0.680023 -1.054816 
    two 4 0.291889 -0.409024 -0.307302 

In [16]: df.loc[('bar','two'),'A'] = 9999 

In [17]: df 
Out[17]: 
        A   B   C 
bar one 0 -0.694240 0.725163 0.131891 
     5  1.697974 -1.828872 -1.004187 
    two 1 9999.000000 0.244860 0.530870 
baz one 2  0.757816 1.129989 0.893080 
qux one 3 -2.275694 0.680023 -1.054816 
    two 4  0.291889 -0.409024 -0.307302 

您还可以整理出来做选择/设置,如果你指定完整的指标,例如

In [23]: df.loc[('bar','two',1),'A'] = 999 

In [24]: df 
Out[24]: 
        A   B   C 
bar one 0 -0.113216 0.878715 -0.183941 
    two 1 999.000000 -1.405693 0.253388 
baz one 2 0.441543 0.470768 1.155103 
qux one 3 -0.008763 0.917800 -0.699279 
    two 4 0.061586 0.537913 0.380175 
bar one 5 0.857231 1.144246 -2.369694 

要检查的那种深度

In [27]: df.index.lexsort_depth 
Out[27]: 0 

In [28]: df.sortlevel(0).index.lexsort_depth 
Out[28]: 3 

你的问题的最后一部分,与列表(请注意,您必须有 相同数量的元素,你试图取代)分配,并且必须对此进行排序以便工作

In [12]: df.loc[('bar','one'),'A'] = [999,888] 

In [13]: df 
Out[13]:  
                    A         B         C 
bar one 0  999.000000 -0.645641  0.369443 
        5  888.000000 -0.990632 -0.577401 
    two 1   -1.071410  2.308711  2.018476 
baz one 2    1.211887  1.516925  0.064023 
qux one 3   -0.862670 -0.770585 -0.843773 
    two 4   -0.644855 -1.431962  0.232528 
+0

所以,这一切都是关于排序......好的,我将在未来使用它。谢谢你的诀窍! – HadiM

+1

是的,让这成为你的朋友:http://pandas.pydata.org/pandas-docs/dev/indexing.html#the-need-for-sortedness – Jeff