【问题标题】:Why order matters for multiindex selection using .ix为什么顺序对使用 .ix 进行多索引选择很重要
【发布时间】:2014-01-06 18:48:25
【问题描述】:

仍在尝试了解多索引选择。构建数据框:

import pandas as pd
from numpy import *

arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
          ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'],
          ['cat', 'cat', 'cat', 'cat', 'dog', 'dog', 'dog', 'dog']]

tuples = zip(*arrays)
index = pd.MultiIndex.from_tuples(tuples, names=['first','second','third'])
data = pd.DataFrame(random.randn(8,3), index=index, columns=['c1','c2','c3'])

>>> data
                          c1        c2        c3
first second third                              
bar   one    cat   -0.309651 -0.242866  0.824422
      two    cat   -0.349640  0.873796 -1.879832
baz   one    cat   -0.851390 -1.241419 -0.016495
      two    cat    0.737211 -0.617967 -2.215459
foo   one    dog   -0.231820  0.140641 -1.619270
      two    dog   -1.363132 -0.929765 -0.005083
qux   one    dog   -1.187903 -0.753883 -0.442464
      two    dog    0.652967  0.423994 -0.705735

问题 1: 如果我想将“c1”值更改为 c1*10,我可以按原样进行吗?我试过了

data.ix['cat'].c1 = data.ix['cat'].c1*10
# Also tried 
data.xs('cat',level='second').c1 = data.xs('cat',level='second').c1*10

两者都不起作用。我得到一个“KeyError”的第一个和

"TypeError: 'instancemethod' object has no attribute 'getitem'" for the second

令人困惑的解决方案

我找到了重新排序索引的解决方案,但这有奇怪的行为(至少对我来说很奇怪)。

d = data.copy() 
d.index = d.index.reorder_levels( [2,0,1] )
>>> d
                          c1        c2        c3
third first second                              
cat   bar   one    -0.309651 -0.242866  0.824422
            two    -0.349640  0.873796 -1.879832
      baz   one    -0.851390 -1.241419 -0.016495
            two     0.737211 -0.617967 -2.215459
dog   foo   one    -0.231820  0.140641 -1.619270
            two    -1.363132 -0.929765 -0.005083
      qux   one    -1.187903 -0.753883 -0.442464
            two     0.652967  0.423994 -0.705735


# Now perform the operation (use *NaN below to make changes easily distinguished)
d.ix['cat'].c1 = d.ix['cat'].c1*NaN

>>> d
                          c1        c2        c3
third first second                              
cat   bar   one          NaN -0.242866  0.824422
            two          NaN  0.873796 -1.879832
      baz   one          NaN -1.241419 -0.016495
            two          NaN -0.617967 -2.215459
dog   foo   one    -0.231820  0.140641 -1.619270
            two    -1.363132 -0.929765 -0.005083
      qux   one    -1.187903 -0.753883 -0.442464
            two     0.652967  0.423994 -0.705735

太棒了!那行得通。但是,如果我想让“第二”成为第一个索引呢?

d = data.copy()
d.index = d.index.reorder_levels( [1,0,2] )
>>> d
                          c1        c2        c3
second first third                              
one    bar   cat   -0.309651 -0.242866  0.824422
two    bar   cat   -0.349640  0.873796 -1.879832
one    baz   cat   -0.851390 -1.241419 -0.016495
two    baz   cat    0.737211 -0.617967 -2.215459
one    foo   dog   -0.231820  0.140641 -1.619270
two    foo   dog   -1.363132 -0.929765 -0.005083
one    qux   dog   -1.187903 -0.753883 -0.442464
two    qux   dog    0.652967  0.423994 -0.705735

# Using the same logic as above...
d.ix['two'].c1 = d.ix['two'].c1*NaN

>>>                          c1        c2        c3
second first third                              
one    bar   cat   -0.309651 -0.242866  0.824422
two    bar   cat   -0.349640  0.873796 -1.879832
one    baz   cat   -0.851390 -1.241419 -0.016495
two    baz   cat    0.737211 -0.617967 -2.215459
one    foo   dog   -0.231820  0.140641 -1.619270
two    foo   dog   -1.363132 -0.929765 -0.005083
one    qux   dog   -1.187903 -0.753883 -0.442464
two    qux   dog    0.652967  0.423994 -0.705735

没有变化!但这(下)确实有效

# Keeping same data frame from previous example
d.c1.ix['two'] = d.ix['two'].c1*NaN

>>> d
                          c1        c2        c3
second first third                              
one    bar   cat   -0.309651 -0.242866  0.824422
two    bar   cat         NaN  0.873796 -1.879832
one    baz   cat   -0.851390 -1.241419 -0.016495
two    baz   cat         NaN -0.617967 -2.215459
one    foo   dog   -0.231820  0.140641 -1.619270
two    foo   dog         NaN -0.929765 -0.005083
one    qux   dog   -1.187903 -0.753883 -0.442464
two    qux   dog         NaN  0.423994 -0.705735

问题 2: 我不明白为什么 d.ix['ID'].c1 vs d.c1.ix['ID'] 的顺序取决于数据框的索引级别的排序方式。这对其他人有意义吗?如果是这样,你能解释一下这里发生了什么吗?任何帮助深表感谢。

【问题讨论】:

  • 阅读:pandas.pydata.org/pandas-docs/dev/…。使用df.loc[row,column] = value 确保您设置的是实际对象
  • 所以你只想改变一个子框架,例如由某个级别索引的某个列?或所有列c1
  • 只是想换个子帧。

标签: python-2.7 indexing pandas dataframe


【解决方案1】:

您的数据

In [48]: data = pd.DataFrame(random.randn(8,3), index=index, columns=['c1','c2','c3'])

In [49]: data
Out[49]: 
                          c1        c2        c3
first second third                              
bar   one    cat    0.219103 -1.142457  0.045307
      two    cat    0.890187  1.097527  0.074196
baz   one    cat   -0.043345 -0.595815  0.775877
      two    cat   -0.694324 -0.757964 -1.253632
foo   one    dog   -2.182311  0.474872  1.444720
      two    dog    1.482957 -0.658113  0.743051
qux   one    dog    1.544032 -0.225756  0.821863
      two    dog    0.121410 -0.143425  1.157422

[8 rows x 3 columns]

编写您要更改的值的掩码(可能更复杂 甚至在这里手动);你需要每个索引的布尔值(例如,长度必须与帧的长度相同)

In [50]: mask = data.index.get_level_values('third') == 'cat'

In [51]: mask
Out[51]: array([ True,  True,  True,  True, False, False, False, False], dtype=bool)

直接索引

In [52]: data.loc[mask,'c1'] *= 10

In [53]: data
Out[53]: 
                          c1        c2        c3
first second third                              
bar   one    cat    2.191029 -1.142457  0.045307
      two    cat    8.901870  1.097527  0.074196
baz   one    cat   -0.433448 -0.595815  0.775877
      two    cat   -6.943241 -0.757964 -1.253632
foo   one    dog   -2.182311  0.474872  1.444720
      two    dog    1.482957 -0.658113  0.743051
qux   one    dog    1.544032 -0.225756  0.821863
      two    dog    0.121410 -0.143425  1.157422

[8 rows x 3 columns]

【讨论】:

    猜你喜欢
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    • 2013-03-19
    • 2015-12-01
    • 1970-01-01
    相关资源
    最近更新 更多