Заменить значения из другого фрейма данных идентификаторами

#r #dataframe

#r #фрейм данных

Вопрос:

У меня есть два фрейма данных::

 as1 <- data.frame(ID = c(1,2,3,4,5,6),
                  pID = c(21,22,23,24,25,26),
                  Values = c(435,33,45,NA, NA,12))
as2 <- data.frame(ID = c(4,5),
                  pid = c(24,25),
                  Values = c(544, 676))
  

Мне нужно заменить значения NA в as1 на значения в as2, сопоставив ID и pID

Мне нужно получить результирующий фрейм данных в виде:

   resultdf
    ID pID Values
    1  1  21    435
    2  2  22     33
    3  3  23     45
    4  4  24    544
    5  5  25    676
    6  6  26     12
  

Я попытался выполнить подмножество, а затем na.omit() а затем rbind редактирование… но я теряю индекс.

Ответ №1:

Вот два базовых R-решения.

Сначала, используя match в «ID», выберите элементы «Value» в as1 для заполнения:

 as1$Values[match(as2$ID, as1$ID)] <- as2$Values

as1
  ID pID Values
1  1  21    435
2  2  22     33
3  3  23     45
4  4  24    544
5  5  25    676
6  6  26     12
  

Это работает, только если ID является истинным идентификатором для обоих наборов данных (то есть pid «не имеет значения»). Во-вторых, в случае, если также необходим pid, вы могли бы использовать merge , а затем «свернуть» два столбца значений следующим образом:

 df <- merge(as1, as2, by.x=c("ID", "pID"), by.y=c("ID", "pid"), all=TRUE)
  

Это создает фрейм данных с четырьмя столбцами и двумя столбцами значений. Сверните их в один столбец с помощью ifelse :

 df <- cbind(df[c(1,2)], "Values"=with(df, ifelse(is.na(Values.y), Values.x, Values.y)))

df
  ID pID Values
1  1  21    435
2  2  22     33
3  3  23     45
4  4  24    544
5  5  25    676
6  6  26     12
  

Комментарии:

1. Я думаю, что это отличный ответ, потому что он позволяет вам вставлять числа на место без очистки dplyr left_join() , где данные дублируются. Одна вещь, на которую я хочу обратить внимание, это то, что порядок параметров внутри match() имеет значение, поэтому обратите на это внимание.

Ответ №2:

Попробуйте с dplyr библиотекой. Сначала объедините обе таблицы, а затем создайте новый столбец со значениями вместо NA ‘s:

 library("dplyr")

as1 <- data.frame(ID = c(1,2,3,4,5,6), pid = c(21,22,23,24,25,26),Values = c(435,33,45,NA, NA,12))
as2 <- data.frame(ID = c(4,5),pid = c(24,25), Values = c(544, 676))

left_join(as1, as2, by = c("ID", "pid")) %>% 
    mutate(Values = ifelse(is.na(Values.x), Values.y, Values.x)) %>% 
    select(ID, pid, Values)

# ID pid Values
# 1  1  21    435
# 2  2  22     33
# 3  3  23     45
# 4  4  24    544
# 5  5  25    676
# 6  6  26     12
  

Ответ №3:

Следуя dplyr решению Марты, мы можем использовать coalesce вместо этого для объединения объединенных Value.x и Value.y :

 library(dplyr)
res <- as1 %>% left_join(as2, by = c("ID", "pID"="pid")) %>%
               mutate(Values=coalesce(Values.x,Values.y)) %>%
               select(-Values.x,-Values.y)
##  ID pID Values
##1  1  21    435
##2  2  22     33
##3  3  23     45
##4  4  24    544
##5  5  25    676
##6  6  26     12
  

Обратите также внимание на синтаксис, используемый для by параметра в left_join . Здесь мы объединяем по ID и по pID для as1 и pid для as2 .

Ответ №4:

Или другой вариант data.table

 library(data.table)
setDT(as1)[as2, Values := i.Values , on =.(ID, pid)]
as1
#    ID pid Values
#1:  1  21    435
#2:  2  22     33
#3:  3  23     45
#4:  4  24    544
#5:  5  25    676
#6:  6  26     12