2016-07-04 4 views
0

У меня есть кадр данных, который выглядит как этотЗаменить на в колонке на значение, соответствующее имени столбца в отдельной таблице

data <- data.frame(ID = c(1,2,3,4,5),A = c(1,4,NA,NA,4),B = c(1,2,NA,NA,NA),C= c(1,2,3,4,NA)) 

> data 
    ID A B C 
1 1 1 1 1 
2 2 4 2 2 
3 3 NA NA 3 
4 4 NA NA 4 
5 5 4 NA NA 

У меня есть файл отображения, а который выглядит как этот

reference <- data.frame(Names = c("A","B","C"),Vals = c(2,5,6)) 

> reference 
    Names Vals 
1  A 2 
2  B 5 
3  C 6 

Я хочу, чтобы мой файл данных был изменен с использованием файла ссылки таким образом, чтобы это дало мне этот окончательный кадр данных.

> final_data 
    ID A B C 
1 1 1 1 1 
2 2 4 2 2 
3 3 2 5 3 
4 4 2 5 4 
5 5 4 5 6 

Каков самый быстрый способ, которым я могу справиться с этим в R?

ответ

4

Мы можем сделать это с Map

data[as.character(reference$Names)] <- Map(function(x,y) replace(x, 
     is.na(x), y), data[as.character(reference$Names)], reference$Vals) 
data 
# ID A B C 
#1 1 1 1 1 
#2 2 4 2 2 
#3 3 2 5 3 
#4 4 2 5 4 
#5 5 4 5 6 

EDIT: На основе @ thelatemail Замечаний.

ПРИМЕЧАНИЕ: Никакие внешние пакеты, используемые


Как мы ищем эффективные решения, другой подход было бы set от data.table

library(data.table) 
setDT(data) 
v1 <- as.character(reference$Names) 

for(j in seq_along(v1)){ 
    set(data, i = which(is.na(data[[v1[j]]])), j= v1[j], value = reference$Vals[j] ) 
} 

Примечания: Только один эффективного внешнего пакета используется.

+1

не должен там быть каким-то способом убедиться, что упорядочение матчей между двумя наборами значений, как 'Map (функция (d, r) заменить (d, is.na (d), r), data [as.character (reference $ Names)], reference $ Vals) '? В противном случае вы полагаетесь на все, что находится в том же порядке строк и столбцов. – thelatemail

+0

@thelatemail Спасибо, что ты прав. – akrun

3

Один из подходов - вычислить логическую матрицу целевых столбцов, в которых фиксируются ячейки NA. Затем мы можем присвоить индексные ячейки NA значениям замены. Хитрость заключается в обеспечении вектора замены совпадет с индексированных клетками:

im <- is.na(data[as.character(reference$Names)]); 
data[as.character(reference$Names)][im] <- rep(reference$Vals,colSums(im)); 
data; 
## ID A B C 
## 1 1 1 1 1 
## 2 2 4 2 2 
## 3 3 2 5 3 
## 4 4 2 5 4 
## 5 5 4 5 6 
0

Если reference была такой же широкий формат, как data, dplyr Новый (v 0.5.0). coalesce функция создана для замены NA с; вместе с purrr, который предлагает альтернативные обозначения для *apply функций, это делает процесс очень простой:

library(dplyr) 

# spread reference to wide, add ID column for mapping 
reference_wide <- data.frame(ID = NA_real_, tidyr::spread(reference, Names, Vals)) 

reference_wide 

# ID A B C 
# 1 NA 2 5 6 

# now coalesce the two column-wise and return a df 
purrr::map2_df(data, reference_wide, coalesce) 

# Source: local data frame [5 x 4] 
# 
#  ID  A  B  C 
# <dbl> <dbl> <dbl> <dbl> 
# 1  1  1  1  1 
# 2  2  4  2  2 
# 3  3  2  5  3 
# 4  4  2  5  4 
# 5  5  4  5  6 
Смежные вопросы