子集Pandas DataFrame二级索引和重新分配值

时间:2015-10-20 16:25:52

标签: python pandas

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

例如 - 说我有以下数据框:

$connect->lastInsertId()

我希望通过Letter' b'将所有3个变量乘以10。

我挣扎的第一个方面是如何选择多索引的第二个索引。我可以通过以下草率的解决方法来做到这一点,但我想象有一种更清洁的方式:

>>> 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

有关更好地在第二个索引上进行子集化的建议吗?

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

>>> 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

但是,如何将原始值替换为新重新调整的值?

4 个答案:

答案 0 :(得分:2)

使用Pandas,您可以使用以下任一方式访问MultiIndex中的第二级:

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

df.xs("b", level="Letter")
        Var1  Var2  Var3
Number                  
1        0.4  0.50  0.60
2        0.1  0.11  0.12

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

df.loc[df.index.isin("b", level="Letter")] = df.loc[df.index.isin("b", level="Letter")]*10

df
               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

通过它,您还可以轻松访问您可以修改的给定列:

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

希望这有帮助

答案 1 :(得分:1)

如果第二个索引级别为'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

答案 2 :(得分:1)

我会通过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

答案 3 :(得分:0)

如果您希望以优雅的方式进行操作:

df.loc[(slice(None), 'b'), :]

查看更多: https://pandas.pydata.org/pandas-docs/stable/user_guide/advanced.html