2016-08-22 2 views
3

Итак, у меня есть два набора данных, представляющие старый и текущий адрес.R - объединить и обновить первичный набор данных

> 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, являющимся личным идентификатором.

idspace, x, y - идентификатор местоположения.

Таким образом, выход мне нужно

> 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")` 
+1

Я думаю, что это дуп, как 'tmp <- rbind (move, main); tmp [! duplicated (tmp $ id),] 'логика работает очень хорошо, предполагая, что здесь нет других требований. – thelatemail

+0

@thelatemail Я думал об использовании 'sqldf', но я не знаю, что API достаточно хорошо, чтобы ответить. –

+1

@TimBiegeleisen - может быть, 'sqldf (» выберите COALESCE (b.idspace, a.idspace), как idspace, сливаются (b.id, A.id) в качестве идентификатора, сливаются (BX, AX) при х, сливаются (by, ay) as y, coalesce (b.move, a.move) в качестве хода от основного a left join move b по a.id = b.id ")' - уродливый, но он действительно работает. – thelatemail

ответ

9

и Использование присоединиться + обновить особенность data.table:

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на месте.

+1

это здорово! любая процедура 'dplyr' за шанс? – giacomo

+2

Запрашивать главного разработчика data.table для решения dplyr ... Hmm ... – nrussell

+0

ok ok sorry;) - все еще устрашающее решение! – giacomo

1

Вот 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] 
1

Я думаю, что я нашел очень простой способ решить эту проблему с помощью

main = as.matrix(main) 
move = as.matrix(move) 

main[main[,'id'] %in% move[,'id'], ] <- move 

который соответствует id, держит id заказаны и изменить только совпадающую rows , Кажется, он работает на весь набор данных.

+0

Обратите внимание, что нет способа узнать, какие 'main $ id' совпадают, с которыми' move $ id' в этом случае. Вы предполагаете, что совпадения будут в том же порядке, в котором строки в 'move'. – Arun

+0

@Arun вы абсолютно правы. Однако, похоже, это работает. Я также попробовал 'main [, 'id']% in% move [, 'id'], c ('idspace', 'x', 'y', 'move')] <- move [which (move [, 'id']% in% main [, 'id']), c ('idspace', 'x', 'y', 'move')] ', которые также обновляются отлично. В последнем случае этот 'id' сопоставляется. Еще раз спасибо за ваше терпение и внимание! – giacomo

+1

'% in%' возвращает логический вектор. Он всегда сохраняет порядок входных данных при подмножестве. Попробуйте это на более сложном примере. Например, если первая и третья записи 'main $ id' соответствуют 3-й и 1-й записям' move $ id', вы должны назначить 1-й и 3-й строки 'move' в 1-й и 3-й строки' main' , Это было бы неправильно. – Arun

Смежные вопросы