合并两个不规则的动物园时间序列会破坏结构
Merging two irregular zoo time-series is messing up the structure
我正在处理包含数千行的贸易数据集。每条记录都有一个基于符号和日期的唯一键。给定符号的交易记录是不规则的,因此使用动物园将是自然的选择。我需要使用滞后和合并来创建一个新的数据集。但是,我不知道如何在动物园中设置多列索引以使用滞后功能。以下是示例数据集和预期输出。
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
请注意,无论列数如何,我都需要合并完整的行。以下是解决基于 zoo 的 "grouped" 滞后操作的一种可能方法,它将合并完整的行。
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
我做错了什么以及如何根据原始数据框获得正确的结构?
我是按照这个linkmultipart index in zoo timeseries问这个问题的
但是我把那个线程搞砸了,因此没有收到任何回复。需要以正确的方式解决这个问题,因为手动修复并不优雅,也不是 "R" 的处理方式。
您的群组索引有重叠。为了避免大量遗漏,一个解决方案是使用一个包含每个 id 的列表作为它自己的时间序列(zoo
个对象):
> myTsList <- tapply(1:nrow(df), df$id, function(x) { zoo::zoo(df[x, ], df$dt[x]) } )
> myTsList
$i1
dt id v1 v2 v3
2015-01-01 2015-01-01 i1 110 100 11
2015-01-05 2015-01-05 i1 115 170 13
2015-01-06 2015-01-06 i1 119 180 16
$i2
dt id v1 v2 v3
2015-01-01 2015-01-01 i2 212 202 22
2015-01-02 2015-01-02 i2 213 210 24
然后你就可以很容易地做到你所说的grouped lag
:
> res <- lapply(myTsList, function(x) merge(x, lag(x), suffixes=c("","lag")) )
> res
$i1
dt. id. v1. v2. v3. dt.lag id.lag v1.lag v2.lag v3.lag
2015-01-01 2015-01-01 i1 110 100 11 2015-01-05 i1 115 170 13
2015-01-05 2015-01-05 i1 115 170 13 2015-01-06 i1 119 180 16
2015-01-06 2015-01-06 i1 119 180 16 <NA> <NA> <NA> <NA> <NA>
$i2
dt. id. v1. v2. v3. dt.lag id.lag v1.lag v2.lag v3.lag
2015-01-01 2015-01-01 i2 212 202 22 2015-01-02 i2 213 210 24
2015-01-02 2015-01-02 i2 213 210 24 <NA> <NA> <NA> <NA> <NA>
当然你可以 bind
如果你想有一个 data.frame
结构的组,但我们需要先转换它们,因为索引重叠:
> Reduce(rbind, lapply(res, as.data.frame))
dt. id. v1. v2. v3. dt.lag id.lag v1.lag v2.lag v3.lag
2015-01-01 2015-01-01 i1 110 100 11 2015-01-05 i1 115 170 13
2015-01-05 2015-01-05 i1 115 170 13 2015-01-06 i1 119 180 16
2015-01-06 2015-01-06 i1 119 180 16 <NA> <NA> <NA> <NA> <NA>
2015-01-011 2015-01-01 i2 212 202 22 2015-01-02 i2 213 210 24
2015-01-02 2015-01-02 i2 213 210 24 <NA> <NA> <NA> <NA> <NA>
编辑: 如果您根本不需要时间序列,而只需要最终输出 data.frame
,那么您可以在我的建议的启发下一起做点什么:
df$ind <- 1:nrow(df)
myTsList <- tapply(1:nrow(df), df$id, function(x) zoo::zoo(df[x, "ind"], df$dt[x]) )
res <- lapply(myTsList, function(x) merge(x, lag(x)) )
newDf<- Reduce(rbind, lapply(res, as.data.frame))
df$ind <- NULL
as.data.frame(cbind(df[newDf[,1],],df[newDf[,2],]))
dt id v1 v2 v3 dt id v1 v2 v3
1 2015-01-01 i1 110 100 11 2015-01-05 i1 115 170 13
2 2015-01-05 i1 115 170 13 2015-01-06 i1 119 180 16
3 2015-01-06 i1 119 180 16 <NA> <NA> NA NA NA
4 2015-01-01 i2 212 202 22 2015-01-02 i2 213 210 24
5 2015-01-02 i2 213 210 24 <NA> <NA> NA NA NA
这也将保留原始 data.frame
中正确的 类 等。
编辑* 更简单的dplyr
解决方案:
library(dplyr)
merge(
df,
df %>% group_by(id) %>% mutate(lag=lag(dt)),
by.x=c("id","dt"), by.y=c("id","lag"), all.x=TRUE
)
id dt v1.x v2.x v3.x dt v1.y v2.y v3.y
1 i1 2015-01-01 110 100 11 2015-01-05 115 170 13
2 i1 2015-01-05 115 170 13 2015-01-06 119 180 16
3 i1 2015-01-06 119 180 16 <NA> NA NA NA
4 i2 2015-01-01 212 202 22 2015-01-02 213 210 24
5 i2 2015-01-02 213 210 24 <NA> NA NA NA
我正在处理包含数千行的贸易数据集。每条记录都有一个基于符号和日期的唯一键。给定符号的交易记录是不规则的,因此使用动物园将是自然的选择。我需要使用滞后和合并来创建一个新的数据集。但是,我不知道如何在动物园中设置多列索引以使用滞后功能。以下是示例数据集和预期输出。
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
请注意,无论列数如何,我都需要合并完整的行。以下是解决基于 zoo 的 "grouped" 滞后操作的一种可能方法,它将合并完整的行。
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
我做错了什么以及如何根据原始数据框获得正确的结构?
我是按照这个linkmultipart index in zoo timeseries问这个问题的 但是我把那个线程搞砸了,因此没有收到任何回复。需要以正确的方式解决这个问题,因为手动修复并不优雅,也不是 "R" 的处理方式。
您的群组索引有重叠。为了避免大量遗漏,一个解决方案是使用一个包含每个 id 的列表作为它自己的时间序列(zoo
个对象):
> myTsList <- tapply(1:nrow(df), df$id, function(x) { zoo::zoo(df[x, ], df$dt[x]) } )
> myTsList
$i1
dt id v1 v2 v3
2015-01-01 2015-01-01 i1 110 100 11
2015-01-05 2015-01-05 i1 115 170 13
2015-01-06 2015-01-06 i1 119 180 16
$i2
dt id v1 v2 v3
2015-01-01 2015-01-01 i2 212 202 22
2015-01-02 2015-01-02 i2 213 210 24
然后你就可以很容易地做到你所说的grouped lag
:
> res <- lapply(myTsList, function(x) merge(x, lag(x), suffixes=c("","lag")) )
> res
$i1
dt. id. v1. v2. v3. dt.lag id.lag v1.lag v2.lag v3.lag
2015-01-01 2015-01-01 i1 110 100 11 2015-01-05 i1 115 170 13
2015-01-05 2015-01-05 i1 115 170 13 2015-01-06 i1 119 180 16
2015-01-06 2015-01-06 i1 119 180 16 <NA> <NA> <NA> <NA> <NA>
$i2
dt. id. v1. v2. v3. dt.lag id.lag v1.lag v2.lag v3.lag
2015-01-01 2015-01-01 i2 212 202 22 2015-01-02 i2 213 210 24
2015-01-02 2015-01-02 i2 213 210 24 <NA> <NA> <NA> <NA> <NA>
当然你可以 bind
如果你想有一个 data.frame
结构的组,但我们需要先转换它们,因为索引重叠:
> Reduce(rbind, lapply(res, as.data.frame))
dt. id. v1. v2. v3. dt.lag id.lag v1.lag v2.lag v3.lag
2015-01-01 2015-01-01 i1 110 100 11 2015-01-05 i1 115 170 13
2015-01-05 2015-01-05 i1 115 170 13 2015-01-06 i1 119 180 16
2015-01-06 2015-01-06 i1 119 180 16 <NA> <NA> <NA> <NA> <NA>
2015-01-011 2015-01-01 i2 212 202 22 2015-01-02 i2 213 210 24
2015-01-02 2015-01-02 i2 213 210 24 <NA> <NA> <NA> <NA> <NA>
编辑: 如果您根本不需要时间序列,而只需要最终输出 data.frame
,那么您可以在我的建议的启发下一起做点什么:
df$ind <- 1:nrow(df)
myTsList <- tapply(1:nrow(df), df$id, function(x) zoo::zoo(df[x, "ind"], df$dt[x]) )
res <- lapply(myTsList, function(x) merge(x, lag(x)) )
newDf<- Reduce(rbind, lapply(res, as.data.frame))
df$ind <- NULL
as.data.frame(cbind(df[newDf[,1],],df[newDf[,2],]))
dt id v1 v2 v3 dt id v1 v2 v3
1 2015-01-01 i1 110 100 11 2015-01-05 i1 115 170 13
2 2015-01-05 i1 115 170 13 2015-01-06 i1 119 180 16
3 2015-01-06 i1 119 180 16 <NA> <NA> NA NA NA
4 2015-01-01 i2 212 202 22 2015-01-02 i2 213 210 24
5 2015-01-02 i2 213 210 24 <NA> <NA> NA NA NA
这也将保留原始 data.frame
中正确的 类 等。
编辑* 更简单的dplyr
解决方案:
library(dplyr)
merge(
df,
df %>% group_by(id) %>% mutate(lag=lag(dt)),
by.x=c("id","dt"), by.y=c("id","lag"), all.x=TRUE
)
id dt v1.x v2.x v3.x dt v1.y v2.y v3.y
1 i1 2015-01-01 110 100 11 2015-01-05 115 170 13
2 i1 2015-01-05 115 170 13 2015-01-06 119 180 16
3 i1 2015-01-06 119 180 16 <NA> NA NA NA
4 i2 2015-01-01 212 202 22 2015-01-02 213 210 24
5 i2 2015-01-02 213 210 24 <NA> NA NA NA