【问题标题】:Stacking and shaping slices of DataFrame (pandas) without looping在不循环的情况下堆叠和塑造 DataFrame (pandas) 的切片
【发布时间】:2014-03-28 17:35:04
【问题描述】:

我有一个如下形式的 DataFrame:

     var1           var2        var3        day
0   -0.001284819    0.00138089  1.022781    1
1   -0.001310201    0.001377473 1.022626    1
2   -0.001330947    0.001374873 1.022477    2
3   -0.0013596      0.001430423 1.022385    2
4   -0.001361913    0.00144389  1.02228     3
5   -0.001371761    0.001440607 1.022161    3
6   -0.001393955    0.00143729  1.022017    4
7   -0.001431099    0.00143434  1.021908    4
8   -0.001466792    0.00143334  1.021749    5
9   -0.001491       0.00143159  1.021602    5

每个变量 var1 到 var3 都是一个时间序列,每天记录两个样本。我正在尝试将这个 DataFrame 转换成这样的东西:

     day   1             2             3             4             5
0   var1  -0.001284819  -0.001330947  -0.001361913  -0.001393955  -0.001466792
1         -0.001310201  -0.0013596    -0.001371761  -0.001431099  -0.001491
2   var2   0.00138089    0.001374873   0.00144389    0.00143729    0.00143334
3          0.001377473   0.001430423   0.001440607   0.00143434    0.00143159
4   var3   1.022781      1.022477      1.02228       1.022017      1.021749
5          1.022626      1.022385      1.022161      1.021908      1.021602

现在每一列都是一天,在每一天中,每个变量的顺序仍然与原始时间序列中的顺序相同。

我一直在尝试找出一种方法来使用旋转、堆叠和此类操作来避免循环,但到目前为止我还无法管理。

任何有关如何解决此问题的建议/提示/想法将不胜感激:)

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    一种方法是使用 groupby 的 cumcount 创建一个列来跟踪它是第一还是第二:

    In [11]: df['occurrence'] = df.groupby('day').cumcount()
    
    In [12]: df = df.set_index(['day', 'occurrence'])
    

    现在你可以做一些堆叠和拆解:

    In [13]: df.stack(0).unstack(0)
    Out[13]: 
    day                     1         2         3         4         5
    occurrence                                                       
    0          var1 -0.001285 -0.001331 -0.001362 -0.001394 -0.001467
               var2  0.001381  0.001375  0.001444  0.001437  0.001433
               var3  1.022781  1.022477  1.022280  1.022017  1.021749
    1          var1 -0.001310 -0.001360 -0.001372 -0.001431 -0.001491
               var2  0.001377  0.001430  0.001441  0.001434  0.001432
               var3  1.022626  1.022385  1.022161  1.021908  1.021602
    

    【讨论】:

    • 我更喜欢@DSM 的方式(更强大)!要堆叠/取消堆叠的级别不是很可读...
    【解决方案2】:

    不一定是最漂亮的,但过去我做过类似的事情

    df = pd.read_csv("vd.csv", sep="\s+")
    d2 = pd.melt(df, id_vars="day")
    d2["sample"] = d2.groupby(["variable", "day"])["day"].rank("first")
    d3 = d2.pivot_table(index=["variable", "sample"], columns="day")
    

    给了

    >>> d3
                        value                                        
    day                     1         2         3         4         5
    variable sample                                                  
    var1     1      -0.001285 -0.001331 -0.001362 -0.001394 -0.001467
             2      -0.001310 -0.001360 -0.001372 -0.001431 -0.001491
    var2     1       0.001381  0.001375  0.001444  0.001437  0.001433
             2       0.001377  0.001430  0.001441  0.001434  0.001432
    var3     1       1.022781  1.022477  1.022280  1.022017  1.021749
             2       1.022626  1.022385  1.022161  1.021908  1.021602
    
    [6 rows x 5 columns]
    

    (虽然老实说,我认为 Andy 的方式更巧妙。我将把它留在这里,因为在过去,在更困难的情况下,melt-modify-pivot 模式对我非常有用。)

    【讨论】:

    • 感谢您保留此信息。 TBH 我认为这更好,我知道我更喜欢阅读哪一个(stack/unstack 无法辨认)
    • 我认为船长 wide_to_long 实际上可能会这样做:pandas-docs.github.io/pandas-docs-travis/…,例如这非常接近:pd.wide_to_long(df,['var1','var2','var3'],i='day',j='foo'),但一开始并没有真正理解它.....
    • 这确实起到了作用。 Andy 的版本非常简洁,在我看来这很好,但我发现它有点难以阅读,而且它没有让样本保持井井有条。非常感谢!
    猜你喜欢
    • 2018-04-12
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2018-10-13
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多