2015-01-01 3 views
1

Что-то вроде функции «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 работает, я не могу не думать, что это, должно быть, было рассмотрено раньше, и поэтому, возможно, уже есть колодец известную функцию, которая работает быстрее и имеет проверку ошибок. Если есть, пожалуйста, дайте мне знать, что это. Спасибо.

ответ

4

Мы можем сделать это, используя data.table следующим образом:

setkeyv(setDT(D1), "k") 
cols = c("D", "E", "A") 
D1[D2, (cols) := D2[, cols]] 
  • setDT() преобразует data.frame в data.table по ссылке (без фактического копирования данных). Мы хотим, чтобы D1 являлся таблицей данных.

  • setkey() сортирует data.table в колонке, указанной (здесь k) и отмечает, что столбец в отсортированный (установив атрибут отсортированный) по ссылке. Это позволяет нам выполнять объединения с использованием двоичного поиска.

  • x[i] в data.table выполняет соединение. Вы можете узнать больше об этом here. Вкратце, для каждой строки столбца k в D2 он находит соответствующие индексы строк в D1, сопоставляя ключевые столбцы D1 (здесь k).

  • x[i, LHS := RHS] выполняет объединение, чтобы найти соответствующие строки, и часть LHS := RHSдобавляет/обновленияx с колоннами, указанными в LHS со значениями, указанными в RHSпосредством ссылки. LHS должен быть вектором имен столбцов или номеров, а RHS должен быть списком значений.

    Таким образом, D1[D2, (cols) := D2[, cols]] находит соответствующие строки в D1 для k=c(1,3,4) из D2 и обновляют столбцы D,E,A, указанных в cols списке (а data.frame также список) соответствующие столбцы из D2 на RHS.

D1 теперь будет изменен в месте.

HTH

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 
Смежные вопросы