用于在现有数据框内粘贴更正值的函数

时间:2015-01-01 15:38:58

标签: r dataframe subset

下面的'paste_over'函数是否已经存在于基础R或其中一个标准R包中?

paste_over <- function(original, corrected, key){
  corrected <- corrected[order(corrected[[key]]),]

  output <- original
  output[
    original[[key]] %in% corrected[[key]],
    names(corrected)
    ] <- corrected

  return(output)
}

一个例子:

D1 <- data.frame(
  k = 1:5,
  A = runif(5),
  B = runif(5),
  C = runif(5),
  D = runif(5),
  E = runif(5)
  )

D2 <- data.frame(
  k=c(4,1,3),
  D=runif(3),
  E=runif(3),
  A=runif(3)
  )

D2 <- D2[order(D2$k),]

D3 <- D1
D3[
  D1$k %in% D2$k,
  names(D2)
  ] <- D2


D4 <- paste_over(D1, D2, "k")

all(D4==D3)

在示例中,D2包含一些我要粘贴在D1中相应单元格上的值。但是,D2的顺序不同,并且与D1的维度不同。

这样做的动机是我获得了一个非常大的数据集,报告了其中的一些错误,并收到了原始数据集的一个子集,其中包含一些更正的值。我希望能够将新的校正值“粘贴”到旧数据集中,而无需在结构方面更改旧数据集。 (正如我编写的其余代码假设是旧数据集的结构。)

虽然paste_over函数似乎工作,但我不禁认为这之前必须解决,所以也许已经有一个众所周知的函数,它既快又错误检查。如果有的话请告诉我它是什么。 感谢。

2 个答案:

答案 0 :(得分:4)

我们可以使用data.table完成此操作,如下所示:

setkeyv(setDT(D1), "k")
cols = c("D", "E", "A")
D1[D2, (cols) := D2[, cols]]
  • setDT()通过引用将data.frame转换为data.table (不实际复制数据)。我们希望D1成为data.table。

  • setkey()按指定的列(此处为k)对data.table进行排序,并将该列标记为排序(通过设置属性已排序引用。这允许我们使用二进制搜索来执行连接。

  • data.table中的
  • x[i]执行连接。您可以阅读更多相关信息here。简而言之,对于k中的D2列中的每一行,它通过匹配D1的关键列(此处为{{}来查找D1中的匹配行索引1}})。

  • k执行联接以查找匹配的行,x[i, LHS := RHS]部分使用{{1}中指定的列添加/更新 LHS := RHS使用引用x 中指定的值。 LHS应该是列名或数字的向量,RHS应该是值列表。

    因此,LHSRHS中找到D1[D2, (cols) := D2[, cols]]中与D1匹配的行,并在列表中更新k=c(1,3,4)中指定的列D2 (一个数据框也是一个列表)来自D,E,Acols的相应列。

D2现在将就地修改

HTH

答案 1 :(得分:1)

您可以在函数中使用替换方法来处理数据框,也许这样。它会为你做足够的检查。我选择将逻辑行子集作为参数传递,但您可以更改

pasteOver <- function(original, corrected, key) {
    "[<-.data.frame"(original, key, names(corrected), corrected)
}

(p1 <- pasteOver(D1, D2, D1$k %in% D2$k))
  k          A           B         C         D          E
1 1 0.18827167 0.006275082 0.3754535 0.8690591 0.73774065
2 2 0.54335829 0.122160101 0.6213813 0.9931259 0.38941407
3 3 0.62946977 0.323090601 0.4464805 0.5069766 0.41443988
4 4 0.66155954 0.201218532 0.1345516 0.2990733 0.05296677
5 5 0.09400961 0.087096652 0.2327039 0.7268058 0.63687025

p2 <- paste_over(D1, D2, "k")
identical(p1, p2)
# [1] TRUE