【问题标题】:Add a calculated result with multiple columns to Pandas DataFrame with MultiIndex columns将具有多列的计算结果添加到具有 MultiIndex 列的 Pandas DataFrame
【发布时间】:2016-01-06 16:17:03
【问题描述】:

我有一个像这样的 DataFrame:

In [10]: df.head()
Out[10]: 
      sand              silt              clay             rho_b  ...      n  \
        5     25    60    5     25    60    5     25    60    5   ...     60   
STID                                                              ...          
ACME  73.0  60.3  52.5  19.7  23.9  25.9   7.2  15.7  21.5  1.27  ...   1.32   
ADAX  61.1  51.1  47.6  22.0  25.4  24.6  16.9  23.5  27.8  1.01  ...   1.25   
ALTU  23.8  17.8  14.3  40.0  45.2  40.9  36.2  37.0  44.8  1.57  ...   1.18   
ALV2  33.3  21.2  19.8  31.4  29.7  29.8  35.3  49.1  50.5  1.66  ...   1.20   
ANT2  55.6  57.5  47.7  34.9  31.1  26.8   9.4  11.3  25.5  1.49  ...   1.29  

因此,对于每个 STID(例如 ACME、ADAX、ALTU),都有一些属性(例如沙子、淤泥、粘土)定义在三个深度(5、25、60)。

这种结构使得在每个 STID 上进行按深度计算变得非常容易,例如:

In [12]: (df['sand'] + df['silt']).head()
Out[12]: 
        5     25    60
STID                  
ACME  92.7  84.2  78.4
ADAX  83.1  76.5  72.2
ALTU  63.8  63.0  55.2
ALV2  64.7  50.9  49.6
ANT2  90.5  88.6  74.5

如何将计算结果巧妙地合并回 DataFrame?比如我想调用上面计算的结果'notclay'

In [13]: df['notclay'] = df['sand'] + df['silt']
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-a30bd9ba99c3> in <module>()
----> 1 df['notclay'] = df['sand'] + df['silt']

<snip>

ValueError: Wrong number of items passed 3, placement implies 1

应为结果中的每一列定义三列,而不仅仅是 'notclay' 列。

我确实有一个使用严格分配的解决方案,但我对此不太满意:

In [21]: df[[('notclay', 5), ('notclay', 25), ('notclay', 60)]] = df['sand'] + df['silt']

In [22]: df['notclay'].head()
Out[22]: 
        5     25    60
STID                  
ACME  92.7  84.2  78.4
ADAX  83.1  76.5  72.2
ALTU  63.8  63.0  55.2
ALV2  64.7  50.9  49.6
ANT2  90.5  88.6  74.5

我还有很多其他的计算要做类似于这个,每次都使用严格的赋值似乎很乏味。我猜有更好/“正确”的方法来做到这一点。我认为add a field in pandas dataframe with MultiIndex columns 可能包含答案,但我不太了解解决方案(甚至不了解小组是什么以及它是否可以帮助我)。

编辑:我尝试过的东西不起作用,使用 concat 前置一个类别:

In [36]: concat([df['sand'] + df['silt']], axis=1, keys=['notclay']).head()
Out[36]: 
     notclay            
          5     25    60
STID                    
ACME    92.7  84.2  78.4
ADAX    83.1  76.5  72.2
ALTU    63.8  63.0  55.2
ALV2    64.7  50.9  49.6
ANT2    90.5  88.6  74.5

In [37]: df['notclay'] = concat([df['sand'] + df['silt']], axis=1, keys=['notclay'])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

<snip>

ValueError: Wrong number of items passed 3, placement implies 1

与上述相同的ValueError 提出。

【问题讨论】:

    标签: python pandas multi-index


    【解决方案1】:

    根据您的口味,这可能是仍然使用 concat 的更好方法:

    In [53]: df
    Out[53]: 
           blah                           foo                    
              1         2         3         1         2         3
    a  0.351045  0.044654  0.855627  0.839725  0.675183  0.325324
    b  0.610374  0.394499  0.924708  0.924303  0.404475  0.885368
    c  0.116418  0.487866  0.190669  0.283535  0.862869  0.346477
    d  0.771014  0.204143  0.143449  0.848520  0.887373  0.220083
    e  0.103268  0.306820  0.277125  0.627272  0.631019  0.386406
    
    In [54]: newdf
    Out[54]: 
              1         2         3
    a  0.433377  0.806679  0.976298
    b  0.593683  0.217415  0.086565
    c  0.716244  0.908777  0.180252
    d  0.031942  0.074283  0.745019
    e  0.651517  0.393569  0.861616
    
    In [56]: newdf.columns=pd.MultiIndex.from_product([['bar'], newdf.columns])
    
    In [57]: pd.concat([df, newdf], axis=1)
    Out[57]: 
           blah                           foo                           bar  \
              1         2         3         1         2         3         1   
    a  0.351045  0.044654  0.855627  0.839725  0.675183  0.325324  0.433377   
    b  0.610374  0.394499  0.924708  0.924303  0.404475  0.885368  0.593683   
    c  0.116418  0.487866  0.190669  0.283535  0.862869  0.346477  0.716244   
    d  0.771014  0.204143  0.143449  0.848520  0.887373  0.220083  0.031942   
    e  0.103268  0.306820  0.277125  0.627272  0.631019  0.386406  0.651517   
    
    
              2         3  
    a  0.806679  0.976298  
    b  0.217415  0.086565  
    c  0.908777  0.180252  
    d  0.074283  0.745019  
    e  0.393569  0.861616 
    

    为了将它存储到原始数据帧中,您可以简单地在最后一行分配给它:

    In [58]: df = pd.concat([df, newdf], axis=1)
    

    【讨论】:

    • 仍然看起来有点笨重,但绝对更容易自动化pd.MultiIndex.from_product([[var_name], newdf.columns])。我可能会接受这个,除非其他人想尽快加入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    • 2021-06-16
    • 2018-02-22
    • 1970-01-01
    • 2022-11-10
    • 2019-02-14
    相关资源
    最近更新 更多