【问题标题】:Merge data frames by approximate column values按近似列值合并数据框
【发布时间】:2012-10-07 00:00:41
【问题描述】:

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

数据如下:

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 会很有用,但我不太明白该怎么做。

【问题讨论】:

  • 这可能适用于您的示例,但不适用于您的问题 - 但您始终可以在合并之前 round() 两者。但是,如果您的测量值 (a,b) 不是相互排斥的,这可能会变得非常棘手。

标签: r


【解决方案1】:

您可以使用 zoo 的 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]

【讨论】:

    【解决方案2】:

    如果您希望最终结果包含来自df2 的所有内容并且您不关心t1 列是否具有来自t2 的值,@JoshuaUlrich 提供了一种很好的方法来执行此操作。

    但是,如果您想避免这些事情并按照@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
    

    【讨论】:

    • 麻烦是(根据@Brandon Bertilsen 的猜测)我的实时值不一定是整数。我喜欢这种方法,但我想弄清楚是否可以修改它以将 t2 列的值“四舍五入”为 t1 列的非整数值。这对我来说更直观。
    • 是的,可以。此处定义的gen.round 函数舍入到最接近的h 倍数,其中h 可以是任何值,例如gen.round(1.36, .5) 将为您提供1.5
    猜你喜欢
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 2018-10-08
    • 2017-09-15
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多