【问题标题】:R - merge and update primary dataset [duplicate]R - 合并和更新主数据集[重复]
【发布时间】:2016-08-22 01:06:52
【问题描述】:

所以,我有两个数据集代表旧地址和当前地址。

> main
idspace   id  x  y move
    198 1238 33  4 stay
    641 1236 36 12 move
    1515 1237 30 28 move

> move
idspace   id x y move
      4 1236 4 1 move

我需要将新数据 (move) 与旧数据 (main) 合并,并在合并后更新 main

我想知道是否有可能在一次手术中完成?

更新基于id,这是个人标识符。

idspacexy 是位置 ID。

所以,我需要的输出是

> main
  idspace   id   x  y move
       198 1238 33  4 stay
       4   1236 4   1 move # this one is updated 
       1515 1237 30 28 move

我不知道该怎么做。

有点像

merge(main, move, by = c('id'), all = T, suffixes = c('old', 'new'))

但是,这是错误的,因为我需要手动进行很多操作。

有什么解决办法吗?

数据

> dput(main)
structure(list(idspace = structure(c(2L, 3L, 1L), .Label = c("1515", 
"198", "641"), class = "factor"), id = structure(c(3L, 1L, 2L
), .Label = c("1236", "1237", "1238"), class = "factor"), x = structure(c(2L, 
3L, 1L), .Label = c("30", "33", "36"), class = "factor"), y = structure(c(3L, 
1L, 2L), .Label = c("12", "28", "4"), class = "factor"), move =     structure(c(2L, 
1L, 1L), .Label = c("move", "stay"), class = "factor")), .Names = c("idspace", 
"id", "x", "y", "move"), row.names = c(NA, -3L), class = "data.frame")

> dput(move)
structure(list(idspace = structure(1L, .Label = "4", class = "factor"), 
id = structure(1L, .Label = "1236", class = "factor"), x = structure(1L,  .Label = "4", class = "factor"), 
    y = structure(1L, .Label = "1", class = "factor"), move = structure(1L, .Label = "move", class = "factor")), .Names = c("idspace", 
"id", "x", "y", "move"), row.names = c(NA, -1L), class = "data.frame")`

【问题讨论】:

  • 我认为这是一个重复,因为tmp <- rbind(move,main); tmp[!duplicated(tmp$id),] 逻辑工作得很好,假设这里没有其他要求。
  • @thelatemail 我正在考虑使用sqldf,但我不知道该 API 足以回答。
  • @TimBiegeleisen - 也许sqldf(" select coalesce(b.idspace,a.idspace) as idspace, coalesce(b.id,a.id) as id, coalesce(b.x,a.x) as x, coalesce(b.y,a.y) as y, coalesce(b.move,a.move) as move from main a left join move b on a.id = b.id ") - 丑陋但确实有效。
  • 它应该存在一个优雅的sql,当然,我需要深入研究它,但感谢@TimBiegeleisen

标签: r merge sql-update


【解决方案1】:

使用data.tablejoin+update功能:

require(data.table) # v1.9.6+
setDT(main) # convert data.frames to data.tables by reference
setDT(move)

main[move, on=c("id", "move"),  # extract the row number in 'main' where 'move' matches
       c("idspace", "x", "y") := .(i.idspace, i.x, i.y)] # update cols of 'main' with 
                                                         # values from 'i' = 'move' for 
                                                         # those matching rows


main
#    idspace   id  x  y move
# 1:     198 1238 33  4 stay
# 2:       4 1236  4  1 move
# 3:    1515 1237 30 28 move

这会更新main就地

【讨论】:

  • 这太棒了!是否有任何dplyr 例程?
  • 向主要的 data.table 开发人员寻求 dplyr 解决方案...嗯...
  • 好吧好吧对不起;) - 仍然很棒的解决方案!
【解决方案2】:

这是dplyr 解决方案:

# If you want both old and new
dplyr::full_join(main, move)

# If you want both old and new with a suffix column
main$suffix <- "old"
move$suffix <- "new"
dplyr::full_join(main, move)

# If you want new only
new       <- dplyr::left_join(main,move,by="id") # could also use  %>%
main[!is.na(new$move.y),1]   <- new[!is.na(new$move.y),6]  
main[!is.na(new$move.y),3:4] <- new[!is.na(new$move.y),7:8]

【讨论】:

    【解决方案3】:

    我想我找到了一个非常简单的方法来解决这个问题

    main = as.matrix(main)
    move = as.matrix(move)
    
    main[main[,'id'] %in% move[,'id'], ] <- move
    

    匹配id,保持id有序,只更改匹配的rows。它似乎适用于整个数据集。

    【讨论】:

    • 请注意,在这种情况下,无法知道哪个main$id 与哪个move$id 匹配。您假设匹配的顺序与move 中的行顺序相同。
    • @Arun 你是绝对正确的。但是,它似乎确实有效。我也试过main[main[,'id'] %in% move[,'id'], c('idspace', 'x', 'y','move')] &lt;- move[which(move[,'id'] %in% main[,'id']), c('idspace', 'x', 'y','move')],它也更新得很好。在后一种情况下,这个id 是匹配的。再次感谢您的耐心和关注!
    • %in% 返回一个逻辑向量。它始终保留输入数据在子集上的顺序。尝试一个更复杂的例子。例如,如果main$id 的第 1 和第 3 个条目与 move$id 的第 3 和第 1 个条目匹配,则您会将 move 的第 1 和第 3 行分配给 main 的第 1 和第 3 行。那是错误的。
    • 是的,你是对的。只要确保按照你说的顺序保持不变。
    猜你喜欢
    • 2018-05-11
    • 2020-10-19
    • 2020-10-11
    • 2021-08-10
    • 2011-05-30
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2018-02-24
    相关资源
    最近更新 更多