【问题标题】:multipart index in zoo timeseries动物园时间序列中的多部分索引
【发布时间】:2015-06-15 12:25:21
【问题描述】:

我正在处理包含数千行的贸易数据集。每条记录都有一个基于符号和日期的唯一键。给定符号的交易记录是不规则的,因此使用 zoo 将是自然的选择。我需要使用滞后和合并来创建一个新的数据集。但是,我不知道如何在动物园中设置多列索引以使用滞后功能。以下是示例数据集和预期输出。

df = data.frame(
    dt = as.Date(c("2015-01-01", "2015-01-05", "2015-01-06",
                   "2015-01-01", "2015-01-02")),
    id = c("i1", "i1", "i1", "i2", "i2"),
    v1 = c(110, 115, 119, 212, 213),
    v2 = c(100, 170, 180, 202, 210),
    v3 = c(11, 13, 16, 22, 24)
)
df$id = as.character(df$id)

输出应该是

2015-01-01, i1, 110, 100, 11, 2015-01-05, i1, 115, 170, 13 
2015-01-05, i1, 115, 170, 13, 2015-01-06, i1, 119, 180, 16 
2015-01-06, i1, 119, 180, 16, NA, NA, NA, NA, NA
2015-01-01, i2, 212, 202, 22, 2015-01-02, i2, 213, 210, 24 
2015-01-02, i2, 213, 210, 24, NA, NA, NA, NA, NA

在 SO 中,有许多帖子完成“分组”滞后操作,但仅针对单个列。我正在寻找合并完整行,无论列数如何。

更新这个问题...

以下是解决基于zoo的“分组”滞后操作的一种可能方法。

doProcessing = function(df){
  icolnames = colnames(df)
  tt = zoo(df, df$dt)
  tt1 = merge(tt, lag(tt, 1))
  colnames(tt1) = c(icolnames, paste0("lag_", icolnames))
  data.frame(tt1, stringsAsFactors=F)
}
fin_df = do.call(rbind, with(df, by(df, list(id), doProcessing, simplify=F)))

这个最终输出帧将每个字段都作为因子。如何根据输入数据框获得正确的输出结构?


基于@Grothendieck 的 lapply 思想,下面给出了上述问题的可能解决方案。

doProcessing = function(df){
  icolnames = colnames(df)
  tt = zoo(df, df$dt)
  tt1 = merge(tt, lag(tt, 1))
  colnames(tt1) = c(icolnames, paste0("lag_", icolnames))
  data.frame(tt1, stringsAsFactors=F)
}

fin_df = do.call(rbind, with(df, by(df, list(id), doProcessing, simplify=F)))

仍然需要一些帮助,一些结果数据框如何将每一列作为因素。如何恢复原始结构?

原始数据帧结构

> str(df)
'data.frame':   5 obs. of  5 variables:
 $ dt: Date, format: "2015-01-05" "2015-01-01" ...
 $ id: chr  "i1" "i1" "i1" "i2" ...
 $ v1: num  115 110 119 212 213
 $ v2: num  170 100 180 202 210
 $ v3: num  13 11 16 22 24

结果数据框看起来像

> str(fin_df)
'data.frame':   5 obs. of  10 variables:
 $ dt    : Factor w/ 4 levels "2015-01-01","2015-01-05",..: 1 2 3 1 4
 $ id    : Factor w/ 2 levels "i1","i2": 1 1 1 2 2
 $ v1    : Factor w/ 5 levels "110","115","119",..: 1 2 3 4 5
 $ v2    : Factor w/ 5 levels "100","170","180",..: 1 2 3 4 5
 $ v3    : Factor w/ 5 levels "11","13","16",..: 1 2 3 4 5
 $ lag_dt: Factor w/ 3 levels "2015-01-05","2015-01-06",..: 1 2 NA 3 NA
 $ lag_id: Factor w/ 2 levels "i1","i2": 1 1 NA 2 NA
 $ lag_v1: Factor w/ 3 levels "115","119","213": 1 2 NA 3 NA
 $ lag_v2: Factor w/ 3 levels "170","180","210": 1 2 NA 3 NA
 $ lag_v3: Factor w/ 3 levels "13","16","24": 1 2 NA 3 NA

【问题讨论】:

    标签: r zoo


    【解决方案1】:

    动物园动物园对象是时间序列,所以通常这样做的方式是使用宽格式:

    read.zoo(df, split = 2) # zoo object created by splitting on column 2
    

    给予:

               v1.i1 v2.i1 v3.i1 v1.i2 v2.i2 v3.i2
    2015-01-01   110   100    11   212   202    22
    2015-01-02    NA    NA    NA   213   210    24
    2015-01-05   115   170    13    NA    NA    NA
    2015-01-06   119   180    16    NA    NA    NA
    

    列表或简单地将数据框拆分为动物园对象列表

    L <- lapply(split(df[-2], df$id), read.zoo)
    

    给予:

    > L
    $i1
                v1  v2 v3
    2015-01-01 110 100 11
    2015-01-05 115 170 13
    2015-01-06 119 180 16
    
    $i2
                v1  v2 v3
    2015-01-01 212 202 22
    2015-01-02 213 210 24
    

    melt 使用 reshape2 包我们可以创建长格式:

    m <- melt(df, id = 1:2)
    

    给予:

    > m
               dt id variable value
    1  2015-01-01 i1       v1   110
    2  2015-01-05 i1       v1   115
    3  2015-01-06 i1       v1   119
    4  2015-01-01 i2       v1   212
    5  2015-01-02 i2       v1   213
    6  2015-01-01 i1       v2   100
    7  2015-01-05 i1       v2   170
    8  2015-01-06 i1       v2   180
    9  2015-01-01 i2       v2   202
    10 2015-01-02 i2       v2   210
    11 2015-01-01 i1       v3    11
    12 2015-01-05 i1       v3    13
    13 2015-01-06 i1       v3    16
    14 2015-01-01 i2       v3    22
    15 2015-01-02 i2       v3    24
    

    在这种形式下,很容易得到各种切片。例如,

    > subset(m, dt == "2015-01-01")
               dt id variable value
    1  2015-01-01 i1       v1   110
    4  2015-01-01 i2       v1   212
    6  2015-01-01 i1       v2   100
    9  2015-01-01 i2       v2   202
    11 2015-01-01 i1       v3    11
    14 2015-01-01 i2       v3    22
    

    3d 数组 另一种可能性是将其表示为三维数组。 m 来自上述melt 解决方案。我们可以置换第二个参数的组成部分以获得变化:

    a <- acast(m, ... ~ id ~ dt)
    
    giving:
    
    , , 2015-01-01
    
        i1  i2
    v1 110 212
    v2 100 202
    v3  11  22
    
    , , 2015-01-02
    
       i1  i2
    v1 NA 213
    v2 NA 210
    v3 NA  24
    
    , , 2015-01-05
    
        i1 i2
    v1 115 NA
    v2 170 NA
    v3  13 NA
    
    , , 2015-01-06
    
        i1 i2
    v1 119 NA
    v2 180 NA
    v3  16 NA
    

    各种切片轻松搞定:a[1,,]a[,1,]a[,,1]

    更新已添加到解决方案并重新排列和改进了一些解决方案。

    【讨论】:

    • @Grothendieck,输出需要连接相同符号的连续行。 read.zoo 输出将同一日期的 i1 数据与 i2 连接起来。这不是预期的输出。
    • 你不能拥有你想要的东西,但仍然将它作为一个可用的动物园对象,但我添加了更多的方法以防万一。
    • @Grothendieck,作为起点,您最后建议的方法看起来更自然,我可以对单个 id 应用滞后,数据集有数百个符号,最终结果必须有符号返回。让我做一些关于如何完成这项工作的工作。我将发布我的发现。谢谢
    • 使用 reshape2 包中的 acast 改进了阵列解决方案并重新排列了演示文稿。
    • @Grothendieck,我只使用 zoo 解决了这个问题,但遇到了一些 str 问题。你能帮忙吗?
    猜你喜欢
    • 2012-03-30
    • 1970-01-01
    • 2017-10-14
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 2012-02-27
    • 1970-01-01
    相关资源
    最近更新 更多