如何在R中将两个不同长度的向量组合

6

我有一组定期进行的测量数据,但其中有些数据缺失:

      measurement_date value
1  2011-01-17 13:00:00     5
2  2011-01-17 13:04:00     5
3  2011-01-17 13:08:00     7
4  2011-01-17 13:12:00     8
5  2011-01-17 13:16:00     4
6  2011-01-17 13:24:00     6
7  2011-01-17 13:28:00     5
8  2011-01-17 13:32:00     6
9  2011-01-17 13:36:00     9
10 2011-01-17 13:40:00     8
11 2011-01-17 13:44:00     6
12 2011-01-17 13:48:00     6
13 2011-01-17 13:52:00     4
14 2011-01-17 13:56:00     6

我有一个函数,将处理值并可以处理缺失的值,但是行必须存在,因此我正在生成一个数组,每分钟都有一行,像这样:

times <- timeSequence(from=.., length=60, by="min")

现在我每小时有一行数据,但我需要合并这些数据。我尝试了以下代码,但效果不太对:

lapply(times, function(time) {
    n <- as.numeric(time)
    v <- Position(function(candidate) {
        y <- as.numeric(candiated)
        n == y
    }

    .. insert the value into the row here ..
}

但是我只收到错误和警告信息。我这样做是对问题的正确解决方法吗?我真的想要一个“完整”的数组,每分钟都有值,因为将会运行许多不同的函数来读取该数据,并且如果它们可以假定一切都在那里,那么实现它们会更容易。


尝试提供一个可重现的示例,就像Gavin向您展示的那样。此外,我感觉您正在使事情过于复杂化。我想不出有哪种情况需要添加NA才能使函数正常工作。 - Joris Meys
请参阅动物园FAQ中的第13个问题:http://cran.r-project.org/web/packages/zoo/vignettes/zoo-faq.pdf - G. Grothendieck
2个回答

8
DF <- data.frame(measurement_date = seq(as.POSIXct("2011-01-17 13:00:00"),
                                        as.POSIXct("2011-01-17 13:56:00"),
                                        by = "mins")[seq(1, 57, by = 4)][-6],
                 value = c(5,5,7,8,4,6,5,6,9,8,6,6,4,6))
full <- data.frame(measurement_date = seq(as.POSIXct("2011-01-17 13:00:00"),
                                          by = "mins", length = 60),
                   value = rep(NA, 60))

有两种方法可以使用,第一种是通过merge

> v1 <- merge(full, DF, by.x = 1, by.y = 1, all = TRUE)[, c(1,3)]
> names(v1)[2] <- "value" ## I only reset this to pass all.equal later
> head(v1)
     measurement_date value
1 2011-01-17 13:00:00     5
2 2011-01-17 13:01:00    NA
3 2011-01-17 13:02:00    NA
4 2011-01-17 13:03:00    NA
5 2011-01-17 13:04:00     5
6 2011-01-17 13:05:00    NA

第二种方法是使用%in%操作符生成的指示变量:
> want <- full$measurement_date %in% DF$measurement_date
> full[want, "value"] <- DF[, "value"]
> head(full)
     measurement_date value
1 2011-01-17 13:00:00     5
2 2011-01-17 13:01:00    NA
3 2011-01-17 13:02:00    NA
4 2011-01-17 13:03:00    NA
5 2011-01-17 13:04:00     5
6 2011-01-17 13:05:00    NA
> all.equal(v1, full)
[1] TRUE

合并版本强烈推荐,但需要一些工作。 %in% 解决方案仅在DFfull中的数据按时间顺序排列时才有效,因此我之前称其为“首选”。然而,很容易确保这两个对象按时间顺序排列,因此两种方法都需要一些技巧才能正常工作。我们可以修改 %in% 方法以使两个变量有序(从 full 开始重新开始):
full2 <- data.frame(measurement_date = seq(as.POSIXct("2011-01-17 13:00:00"),
                                           by = "mins", length = 60),
                    value = rep(NA, 60))
full2 <- full2[order(full2[,1]), ] ## get full2 in order
DF2 <- DF[order(DF[,1]), ]         ## get DF in order
want <- full$measurement_date %in% DF$measurement_date
full2[want, "value"] <- DF2[, "value"]

>     all.equal(full, full2)
[1] TRUE
>     all.equal(full2, v1)
[1] TRUE
>

2
确实... (+1) "Joris-Gavin 相互欣赏协会" - Gavin Simpson
1
第二种解决方案依赖于行顺序的正确性。稍微更好的版本是 want <- match(DF$measurement_date, full$measurement_date)。但是有很多陷阱(重复的ID等),因此合并解决方案是强烈推荐的。 - Eduardo Leoni
@Eduardo 谢谢 - 鉴于时间顺序相同,在这里使用%in%没有任何问题,但你的观点很好,我已经强调了merge是首选。 - Gavin Simpson
我的回答似乎在emacs和粘贴代码到回答之间出现了不同步的情况。merge缺少一些修饰来处理两个对象中匹配的行,并纠正names(full)[2])。没有这个,我最初的代码返回了74行,明显不是all.equal(v1, full)。此外,我添加了一些内容来解决评论中提出的时间排序问题。 - Gavin Simpson
2
我刚刚发现以下代码可以更简单地编写: seq(as.POSIXct("2011-01-17 13:00:00"),length=60 / 4, by = "4 mins") 它等同于: seq(as.POSIXct("2011-01-17 13:00:00"), as.POSIXct("2011-01-17 13:56:00"), by = "mins")[seq(1, 57, by = 4)] - Trygve Laugstøl
@trygis 很好,我没想到你能做那种事情。今天我学了第二个新东西(第一个是古海洋学家对数据所做的奇怪处理方式,而且还能逃脱惩罚!) - Gavin Simpson

6
在你的函数中,as.numeric(candiated) 应该是 as.numeric(candidate)。还有一个括号缺失。我不知道你的函数实际想要实现什么,但对我来说看起来非常复杂。
尝试:
merge(Data,times,by.x=1,by.y=1,all.y=T)

这应该能给你提供一些工作材料。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接