2012-10-16 72 views
4

我有两个包含时间序列的数据帧(时间编码为数字,而不是时间对象;时间未排序)。我想将一个数据框中的响应变量标准化为另一个数据框中的响应变量。问题在于两个数据帧中的时间点并不完全相同。所以,我需要通过两个时间列的近似匹配来合并两个数据帧。按近似列值合并数据帧

的数据是这样的:

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 

好像approxapproxfun将是有益的,但我不能完全看怎么办它。

+2

这可能适用于您的示例,但不适用于您的问题 - 但在合并之前,您总是可以“round()”。尽管如果你的测量(a,b)不相互排斥,这可能会非常棘手。 –

回答

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] 
+0

Ooo,+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 
+0

麻烦是(根据@Brandon Bertilsen的猜测)我的实时值不一定是整数。我喜欢这种方法,但我试图弄清楚它是否可以修改为将t2列的值“舍入”到t1列的非整数值。这对我来说会更直观。 –

+1

是的,它可以。这里定义的'gen.round'函数取整为'h'的最接近倍数,其中'h'可以是任何东西,例如'gen.round(1.36,.5)'会给你'1.5'。 –