заменить определенные значения в df согласно нескольким условиям - PullRequest
1 голос
/ 12 марта 2020

basi c вопрос, но я ищу хорошее решение (не для циклов) для условной замены в DF1 на значения DF2, ЕСЛИ выполняются несколько условий:

DF1
Name  Year   Val1
A    2010     x1
A    2012     x2
B    2012     x3
C    2015     x4
C    2012     x5
DF2
Name  Year   Val1
A    2012     y1
B    2012     y2
C    2012     y3

Если год имеет определенное значение, например 2012 в этом случае, и имя DF1 и DF2 совпадают, затем присвойте Val1 от DF2 до DF1.

Я пробовал несколько вещей: DF1$Val1[DF1$Year=="2012"&DF1$Name==DF2$Name,] <-DF2$Val1 DF1$Val1<-replace(DF1$Val1, DF1$Year=="2012" & DF1$Name==DF2$Name, DF2$Val1)

Но я, к сожалению, получаю ошибку, потому что DF1 и DF2 не имеют одинаковую длину.

Ожидается:

DF1
Name  Year   Val1
A    2010     x1
A    2012     y1
B    2012     y2
C    2015     x4
C    2012     y3

СПАСИБО ЗА ПОМОЩЬ!

Ответы [ 4 ]

1 голос
/ 12 марта 2020

Мы можем использовать объединение on столбцов с data.table и обновить 'Val'

librar(data.table)
setDT(DF1)[DF2, Val1 := i.Val1, on = .(Name, Year)]
DF1
#   Name Year Val1
#1:    A 2010   x1
#2:    A 2012   y1
#3:    B 2012   y2
#4:    C 2015   x4
#5:    C 2012   y3

data

DF1 <- structure(list(Name = c("A", "A", "B", "C", "C"), Year = c(2010L, 
2012L, 2012L, 2015L, 2012L), Val1 = c("x1", "x2", "x3", "x4", 
"x5")), class = "data.frame", row.names = c(NA, -5L))

DF2 <- structure(list(Name = c("A", "B", "C"), Year = c(2012L, 2012L, 
2012L), Val1 = c("y1", "y2", "y3")), class = "data.frame", row.names = c(NA, 
-3L))
0 голосов
/ 13 марта 2020

Мы можем left_join df1 и df2 на Name и Year и использовать coalesce для выбора значений не-NA из двух столбцов Val1.

library(dplyr)

DF1 %>%
  left_join(DF2, by = c('Name', 'Year')) %>%
  mutate(Val1 = coalesce(Val1.y, Val1.x)) %>%
  select(names(df1))

#  Name Year Val1
#1    A 2010   x1
#2    A 2012   y1
#3    B 2012   y2
#4    C 2015   x4
#5    C 2012   y3
0 голосов
/ 13 марта 2020

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

- Использование match:

inds <- match(data.frame(t(DF2[-3]),stringsAsFactors = FALSE),
              data.frame(t(DF1[-3]),stringsAsFactors = FALSE))
DF1$Val1[inds] <- DF2$Val1

такое, что

> DF1
  Name Year Val1
1    A 2010   x1
2    A 2012   y1
3    B 2012   y2
4    C 2015   x4
5    C 2012   y3

- Использование merge + subset:

DF1 <- subset(within(merge(DF1,DF2,by=c("Name","Year"),all.x = TRUE), 
                     Val1 <- ifelse(is.na(Val1.y),Val1.x,Val1.y)),
              select = names(DF1))

таким, что

> DF1
  Name Year Val1
1    A 2010   x1
2    A 2012   y1
3    B 2012   y2
4    C 2012   y3
5    C 2015   x4
0 голосов
/ 12 марта 2020

Я думаю, что самый простой способ сделать это - отфильтровать DF2, а затем добавить его в DF1.

Итак

    DF2 <- dplyr::filter(DF2, Year==2012,
                     Name %in% unique(DF1$Name)
    DF1 <- dplyr::bind_rows(DF1, DF2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...