【问题标题】:a complex merge in R to flag unmatched observations?R 中的复杂合并以标记不匹配的观察结果?
【发布时间】:2012-12-18 01:12:32
【问题描述】:

我正在尝试将两个数据集连接在一起。称它们为 x 和 y。我相信 y 中的 ID 变量是 x 中的 ID 变量的子集。但不是纯粹意义上的,因为我知道 x 包含的 ID 比 y 多,但我不知道映射。也就是说,x 和 y 中的一些(但不是全部)ID 可以 1:1 匹配。

我的最终目标是找出这种 1:1 映射失败的地方并标记这些观察结果。我认为合并将是要走的路,但也许不是。下面是一个例子:

id <- c(1:10, 1:100)

X1 <- rnorm(110, mean = 0, sd = 1)
year <- c("2004","2005","2006","2001","2002") 
year <- rep(year, 22)

month = c("Jul","Aug","Sep","Oct","Nov","Dec","Jan","Feb","Mar","Apr")
month <- rep(month, 11)

#dataset X
x <- cbind(id, X1, month, year)

#dataset Y
id2 <- c(1:10, 200)
Y1 <- rnorm(11, mean = 0 , sd = 1)
y <- cbind(id2,Y1)

#merge on the IDs; but we get an error because when id2 == 200 in y we don't 
#have a match in x 
result <- merge(x, y, by.x="id", by.y = "id2", all =TRUE)

合并引发错误,因为 id2 == 200 在 x 数据集中没有匹配项。不幸的是,我丢失了身份证和所有信息! (它应该等于第 111 行中的 200):

tail(result) 
      id                   X1 month year         Y1
106   95  -0.0748386054887876   Nov 2002         NA
107   96    0.196765325477989   Dec 2004         NA
108   97    0.527922135906927   Jan 2005         NA
109   98    0.197927230533413   Feb 2006         NA
110   99 -0.00720474886698309   Mar 2001         NA
111 <NA>                 <NA>  <NA> <NA> -0.9664941

此外,我在合并文件中的 ID 变量上得到了重复的观察结果。 id2 == 1 观察只存在一次,但它只是复制了两次(例如 Y1 两次取值 1.55)。

head(result)
   id                 X1 month year       Y1
1   1  -0.67371266313441   Jul 2004 1.553220
2   1 -0.318666983469993   Jul 2004 1.553220
3  10 -0.608192898092431   Apr 2002 1.234325
4  10  -0.72299929212347   Apr 2002 1.234325
5 100 -0.842111221826554   Apr 2002       NA
6  11  -0.16316681842082   Jul 2004       NA

这次合并让事情变得比我预期的要复杂。我希望我可以检查 x 中的每个观察结果,并找出 id 与 y 中的 id2 匹配的位置,并标记那些不匹配的位置。所以我会得到一个新的向量,称为标志,如果 x$id 在 y$id2 中有匹配项,则取值为 1,否则取值为 0。这样,我就可以知道 1:1 映射失败的地方。通过重新编码 NA,我可能会对此有所了解,但是当 id2 == 200 时抛出的错误呢?它只是丢弃信息。

我试过按行追加,但没有运气,看起来我也应该放弃合并,也许最好用一个循环或函数来做一些事情:

对于 x 中的每个观察

id2 = which(id2) 对应id-month-year

如果上面的长度== 1,则flag = 1,否则为0

等等。

希望这一切都有意义。我将非常感谢任何帮助或指导。

【问题讨论】:

  • cbind 创建矩阵,而不是数据帧。您创建xy 的调用应该是x &lt;- data.frame(id,X1,month,year)y &lt;- data.frame(id2,Y1)
  • 您将获得两个关于 y$id2 == 1 的观察结果,因为 x 中有两行 x$id == 1。如果合并看到多个符合连接条件的观察,它将为每个可能的组合创建一行。这是设计使然,非常有用。

标签: r function merge append apply


【解决方案1】:

如果你正在寻找x$id中的哪些东西在y$id2中,那么你可以使用

x$id %in% y$id2

获取返回匹配项的逻辑向量。但是,它不保证一对一的通信;只是一对多。然后,您可以将此向量添加到您的数据框中

x$match.y <- x$id %in% y$id2

查看x的哪些行在y中有对应的ID。

要查看哪些观察是一对一的,您可以执行类似的操作

y$id2[duplicated(y$id2)] #vector of duplicate elements in y$id2
(x$id %in% y$id2) & !(x$id %in% y$id2[duplicated(y$id2)])

过滤掉在y$id2 中出现多次的元素。您也可以将此添加到x

x$match.y.unique <- (x$id %in% y$id2) & !(x$id %in% y$id2[duplicated(y$id2)])

可以对y 执行相同的过程来确定y 的哪些行与x 匹配,哪些行是唯一匹配的。

【讨论】:

  • duplicated 返回一个布尔向量。你想要y$id2[duplicated(y$id2)]
  • 正确!我意识到我的错误并在编辑屏幕上花了几分钟试图记住正确的语法。谢谢你的收获。
  • 谢谢!当 y$id2 == 200 并且在 x$id 中没有匹配项时,此选项看起来效果不佳。它应该是假的,但出现的是真的:test &lt;- (x$id %in% y$id2) &amp; !(x$id %in% y$id2[duplicated(y$id2)])test &lt;- data.frame(x,y,test)test[1:20,]# first 20 rows 在第 11 行,我们有对应于 id 的 id2,它不是 1:1,应该是“FALSE”,但出现“TRUE”。然后所有后续行都搞砸了。所以我们在第 12 行有 2 == 1 = TRUE,等等。
  • 我在解决方案中提出的向量是一个逻辑向量,它告诉x$id 的哪些元素可以与y$id2 的元素以一对一的方式唯一匹配。考虑x$one.to.one &lt;- (x$id %in% y$id2) &amp; !(x$id %in% y$id2[duplicated(y$id2)]),然后查看x
  • 另外,我认为data.frame(x,y,test) 不会像你想的那样做。 data.frame 命令只会将其参数混合在一起,而不是通过 id 合并。此外,由于在此实例中y 的行数少于x,因此它得到recycled to fill up the space,因此将重复10 次。
【解决方案2】:

您的合并失败的原因是您为 x 和 y 提供了两个不同的结构(一个是数字矩阵,另一个是字符矩阵)。在应该选择data.frame 时使用cbind 是常见的失败策略。

> str(x)
 chr [1:110, 1:4] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "1" "2" ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:4] "id" "X1" "month" "year"
> str(y)
 num [1:11, 1:2] 1 2 3 4 5 6 7 8 9 10 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:2] "id2" "Y1"

如果您使用 data.frame 函数(因为数据帧是 merge 应该使用的)它会成功:

> x <- data.frame(id, X1, month, year); y <- data.frame(id2,Y1)
> str( result <- merge(x, y, by.x="id", by.y = "id2", all =TRUE) )
'data.frame':   111 obs. of  5 variables:
 $ id   : num  1 1 2 2 3 3 4 4 5 5 ...
 $ X1   : num  1.5063 2.5035 0.7889 -0.4907 -0.0446 ...
 $ month: Factor w/ 10 levels "Apr","Aug","Dec",..: 6 6 2 2 10 10 9 9 8 8 ...
 $ year : Factor w/ 5 levels "2001","2002",..: 3 3 4 4 5 5 1 1 2 2 ...
 $ Y1   : num  1.449 1.449 -0.134 -0.134 -0.828 ...

> tail( result <- merge(x, y, by.x="id", by.y = "id2", all =TRUE) )
     id         X1 month year        Y1
106  96 -0.3869157   Dec 2004        NA
107  97  0.6373009   Jan 2005        NA
108  98 -0.7735626   Feb 2006        NA
109  99 -1.3537915   Mar 2001        NA
110 100  0.2626190   Apr 2002        NA
111 200         NA  <NA> <NA> -1.509818

如果您的“x”参数中有重复项,那么您应该在结果中得到重复项。那么您有责任以您认为合适的任何方式使用!duplicated(在合并之前或之后),但您不能指望merge 会为您做出这样的决定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    相关资源
    最近更新 更多