【问题标题】:Assign to *new* subset of a pandas DataFrame分配给 pandas DataFrame 的 *new* 子集
【发布时间】:2016-08-26 14:04:32
【问题描述】:

假设我在 DataFrame df 中有一些数据。特别是,df.columns 是一个 MultiIndex,其中第一级表示我们正在处理的“什么样的数据”,第二级表示某种 ID。首先,最外层的列级别只有一个唯一值:

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.randn(400, 5), columns=list('abcde'))
df.columns = pd.MultiIndex.from_tuples([('raw', c) for c in df.columns], 
                                       names=['datum', 'id'])

假设我想计算这组数据的 10 个周期移动平均值。我可以很容易地做到这一点

df['raw'].rolling(window=10, min_periods=10).mean()

我想将此分配给现有数据框的 部分。我希望语法简单:

df['avg_10'] = df['raw'].rolling(window=10, min_periods=10).mean()

但这不起作用。相反,为了得到等价物,我需要做一些笨拙的事情,比如:

a = df['raw'].rolling(window=10, min_periods=10).mean()
a.columns = pd.MultiIndex.from_tuples([('avg_10', c) for c in a.columns],
                                      names=['datum', 'id'])
df = pd.concat([df, a], axis=1)

有没有简洁的方法来做到这一点?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以像这样一次性添加新列:

    df[df.columns.get_level_values(1)] = df['raw'].rolling(window=10, min_periods=10).mean()
    

    现在让我们对列级别进行排序:

    df.columns = pd.MultiIndex.from_tuples(
      [t if t[0]=='raw' else ('avg_10', t[0]) for t in df.columns.tolist()]
    )
    

    输出:

    In [121]: df.tail()
    Out[121]:
             raw                                            avg_10            \
               a         b         c         d         e         a         b
    35 -0.036381 -0.202369  0.728408 -1.149906 -0.888169  0.174578  0.244956
    36  1.700182 -0.957104 -0.005931 -1.035258  0.916398  0.304429  0.025519
    37  1.142203  0.198508 -0.568147  0.006620  1.912575  0.408570  0.029939
    38 -1.360093  0.638533 -0.899154  1.120311  1.702436  0.109886  0.155383
    39 -1.860319  0.863798  0.876608  1.292301  0.547762 -0.069686  0.141820
    
    
               c         d         e
    35 -0.046456 -0.291078  0.176360
    36  0.128143 -0.670730  0.213351
    37  0.041724 -0.542027  0.301774
    38 -0.147804 -0.363713  0.400007
    39  0.005854 -0.164190  0.483140
    

    【讨论】:

    • @8one6,有帮助吗?
    【解决方案2】:

    由于df.rolling 如您的示例所示,此解决方案仅适用于 Pandas 0.18.0+。

    # Create sample data with three columns.
    np.random.seed(0)
    df = pd.DataFrame(np.random.randn(400, 3), columns=list('abc'))
    df.columns = pd.MultiIndex.from_tuples([('raw', c) for c in df.columns], 
                                           names=['datum', 'id'])
    
    # Have two window periods (e.g. 10, 30).
    windows = [10, 30]
    cols = df.columns.get_level_values(1)
    for window in windows:
        for col in cols:
            df.loc[:, ('avg_{0}'.format(window), col)] = \
                df.xs(col, axis=1, level=1).rolling(window=window, min_periods=window).mean()
    
    >>> df.tail()
    
    datum       raw                        avg_10                        avg_30                    
    id            a         b         c         a         b         c         a         b         c
    395   -0.177813  0.250998  1.054758  0.528226  0.266558  0.123020  0.046781  0.365069  0.233943
    396    0.960048 -0.416499 -0.276823  0.459380  0.379910  0.140920  0.067177  0.329077  0.261536
    397    1.123905 -0.173464 -0.510030  0.429155  0.268950  0.022079  0.105671  0.270666  0.271052
    398    1.392518  1.037586  0.018792  0.485142  0.340002 -0.139202  0.170970  0.315509  0.262711
    399   -0.593777 -2.011880  0.589704  0.387988  0.114828 -0.096127  0.133680  0.206199  0.265718
    

    【讨论】:

      猜你喜欢
      • 2020-01-15
      • 1970-01-01
      • 2021-04-12
      • 2019-02-06
      • 2020-02-13
      • 1970-01-01
      • 2022-08-23
      • 1970-01-01
      • 2019-04-12
      相关资源
      最近更新 更多