我有两个包含时间序列的数据框(时间编码为数字,而不是时间对象;时间未排序)。我想将一个数据帧中的响应变量规范化为另一个数据帧中的响应变量。问题是两个数据帧中的时间点并不完全相同。所以,我需要通过两个时间列的近似匹配来合并两个数据帧。
数据如下所示:
df1 <- structure(list(t1 = c(3, 1, 2, 4), y1 = c(9, 1, 4, 16)), .Names = c("t1", "y1"), row.names = c(NA, -4L), class = "data.frame")
df2 <- structure(list(t2 = c(0.9, 4.1), y2 = structure(1:2, .Label = c("a", "b"), class = "factor")), .Names = c("t2", "y2"), row.names = c(NA, -2L), class = "data.frame")
结果应如下所示:
t1 y1 y2
1 1 a
4 16 b
似乎approx
或approxfun
会很有用,但我不太明白该怎么做。
答案 0 :(得分:7)
您可以使用动物园中的na.approx
轻松完成此操作:
library(zoo)
Data <- merge(df1, df2, by.x="t1", by.y="t2", all=TRUE)
Data$y1 <- na.approx(Data$y1, na.rm=FALSE, rule=2)
na.omit(Data)
# t1 y1 y2
# 1 0.9 1 a
# 6 4.1 16 b
您也可以使用approx
执行此操作:
Data <- merge(df1, df2, by.x="t1", by.y="t2", all=TRUE)
y1.na <- is.na(Data$y1)
Data$y1[y1.na] <- (approx(Data$y1, rule=2, n=NROW(Data))$y)[y1.na]
答案 1 :(得分:1)
@JoshuaUlrich提供了一种很好的方法,如果您希望最终结果包含df2
中的所有内容,并且您不关心t1
列是否包含来自t2
的值。
但是,如果您想避免这些事情并继续按照@BrandonBertelsen建议的方式继续,您可以定义自定义round
函数,然后在第二个data.frame
的合并列上使用它。例如:
# define a more precise rounding function that meets your needs.
# e.g., this one rounds values in x to their nearest multiple of h
gen.round <- function(x, h) {
ifelse(x %% h > (h/2), h + h * (x %/% h), -(h + h * (-x %/% h)))
}
# make a new merge function that uses gen.round to round the merge column
# in the second data.frame
merge.approx <- function(x, y, by.x, by.y, h, ...) {
y <- within(y, assign(by.y, gen.round(get(by.y), h)))
merge(x, y, by.x=by.x, by.y=by.y, ...)
}
merge.approx(df1, df2, by.x='t1', by.y='t2', h =.5)
t1 y1 y2
1 1 1 a
2 4 16 b