Python 数据帧二级索引和重新分配值的子集

Python 数据帧二级索引和重新分配值的子集,python,pandas,Python,Pandas,这可能是一个由两部分组成的问题,但我正在寻找对由二级索引标识的记录子集进行重新缩放(或执行任何操作)的最佳方法 例如,假设我有以下数据帧: >>> df=pd.DataFrame(data=[[1,2,3],[.4,.5,.6],[7,8,9],[.10,.11,.12]], index=pd.MultiIndex.from_tuples([(1,'a'), (1,'b'), (2,'a'), (2,'b')]), columns=['Var1','Var2','Var3'])

这可能是一个由两部分组成的问题,但我正在寻找对由二级索引标识的记录子集进行重新缩放(或执行任何操作)的最佳方法

例如,假设我有以下数据帧:

>>> df=pd.DataFrame(data=[[1,2,3],[.4,.5,.6],[7,8,9],[.10,.11,.12]], index=pd.MultiIndex.from_tuples([(1,'a'), (1,'b'), (2,'a'), (2,'b')]), columns=['Var1','Var2','Var3'])
>>> df.index.names=['Number','Letter']
>>> print df
               Var1  Var2  Var3
Number Letter                  
1      a        1.0  2.00  3.00
       b        0.4  0.50  0.60
2      a        7.0  8.00  9.00
       b        0.1  0.11  0.12
我希望字母“b”标识的两个记录将所有3个变量乘以10

我正在努力解决的第一个问题是如何在多索引的第二个索引上进行选择。我可以通过以下草率的方法来实现这一点,但我可以想象有一种更干净的方法:

>>> df=df.reset_index().set_index(['Letter','Number'])
>>> Records=df.loc['b']
>>> print Records
        Var1  Var2  Var3
Number                  
1        0.4  0.50  0.60
2        0.1  0.11  0.12
关于第二个索引子集的更好方法,有什么建议吗

然后我可以重新缩放它们:

>>> print Records*10
        Var1  Var2  Var3
Number                  
1          4     5     6
2         10    11    12

但是,如何用这些新重新缩放的值替换原始值?

如果第二个索引级别为
'b'
,则将值缩放10倍:

In [82]:

print pd.DataFrame(data=df.values*np.where(df.index.get_level_values(1) == 'a', 1, 10).reshape((-1,1)), 
                   index=df.index)
               0    1    2
Number Letter             
1      a       1  2.0  3.0
       b       4  5.0  6.0
2      a       7  8.0  9.0
       b       1  1.1  1.2
或者:

In [94]:

print (df.T * np.where(df.index.get_level_values(1) == 'a', 1, 10)).T
               Var1  Var2  Var3
Number Letter                  
1      a          1   2.0   3.0
       b          4   5.0   6.0
2      a          7   8.0   9.0
       b          1   1.1   1.2

我将通过unstack使多索引级别成为第一级,然后对其进行切片:

    In [72]: df=pd.DataFrame(data=[[1,2,3],[.4,.5,.6],[7,8,9],[.10,.11,.12]], index=pd.MultiIndex.from_tuples([(1,'a'), (1,'b'), (2,'a'), (2,'b')]),         columns=['Var1','Var2','Var3'])        

    In [73]: df
    Out[73]: 
         Var1  Var2  Var3
    1 a   1.0  2.00  3.00
      b   0.4  0.50  0.60
    2 a   7.0  8.00  9.00
      b   0.1  0.11  0.12

    In [89]: df1 = df.unstack(-2) # the same as level=0
    In [90]: df1
    Out[90]: 
       Var1       Var2        Var3      
          1    2     1     2     1     2
    a   1.0  7.0   2.0  8.00   3.0  9.00
    b   0.4  0.1   0.5  0.11   0.6  0.12

    In [91]: df1.loc['a']*=10
    In [92]: df1
    Out[92]: 
       Var1        Var2         Var3       
          1     2     1      2     1      2
    a  10.0  70.0  20.0  80.00  30.0  90.00
    b   0.4   0.1   0.5   0.11   0.6   0.12

    df = df1.stack().swaplevel(0,1) # return back to the multi-index

使用Pandas,您可以通过以下任一方式访问多索引中的第二级:

df.loc[df.index.isin("b", level="Letter")]
               Var1  Var2  Var3
Number Letter                  
1      b        0.4  0.50  0.60
2      b        0.1  0.11  0.12

它不是完全相同的输出,只有第一个版本允许您更改值(感谢
loc
以及您保留所有索引值的事实):

这样,您还可以轻松访问给定的列,也可以对其进行修改:

df.loc[df.index.isin("b", level="Letter"), "Var3"] = "Foo"
df

               Var1  Var2 Var3
Number Letter                 
1      a          1   2.0    3
       b          4   5.0  Foo
2      a          7   8.0    9
       b          1   1.1  Foo

如果您喜欢优雅的方式,希望这对您有所帮助:

df.loc[(slice(None), 'b'), :]
请参阅更多:
df1.stack().swaplevel(0,1)
?是的,这是选项。补充我的答案。谢谢
df.loc[df.index.isin("b", level="Letter"), "Var3"] = "Foo"
df

               Var1  Var2 Var3
Number Letter                 
1      a          1   2.0    3
       b          4   5.0  Foo
2      a          7   8.0    9
       b          1   1.1  Foo
df.loc[(slice(None), 'b'), :]