Обновить значение в одной колонке на основе критериев в других столбцах

Если мой кадр данных (df) выглядит так:

Name        State
John Smith  MI
John Smith  WI
Jeff Smith  WI

Я хочу переименовать Джона Смита из WI "John Smith1". Каков самый чистый R-эквивалент инструкции SQL?

update df 
set Name = "John Smith1"
where Name = "John Smith"
and State = "WI"

Ответы

Ответ 1

df <- data.frame(Name=c('John Smith', 'John Smith', 'Jeff Smith'),
                 State=c('MI','WI','WI'), stringsAsFactors=F)

df <- within(df, Name[Name == 'John Smith' & State == 'WI'] <- 'John Smith1')

> df
         Name State
1  John Smith    MI
2 John Smith1    WI
3  Jeff Smith    WI

Ответ 2

В одну сторону:

df[df$Name == "John_Smith" & df$State == "WI", "Name"] <- "John_Smith1"

Другой способ использования dplyr:

df %>% mutate(Name = ifelse(State == "WI" & Name == "John_Smith", "John_Smith1", Name))

Примечание. Как говорит Дэвид Аренбург, первая колонка не должна быть фактором. Для этого, считывая stringsAsFactors = FALSE набора stringsAsFactors = FALSE.

Ответ 3

Вы также можете использовать пакет data.table:

library(data.table)
setDT(df)[State=="WI", Name:=paste0(Name,"1")]

Ответ 4

Поскольку ОП упомянул, что у него "очень большой фрейм данных", может быть полезно использовать двоичный поиск

library(data.table)
setDT(DF)[.("John Smith",  "WI"), on = .(Name=V1, State=V2), 
          Name := paste0(Name, 1)][]
          Name State
1:  John Smith    MI
2: John Smith1    WI
3:  Jeff Smith    WI

вместо векторной развертки

setDT(df)[State == "WI" & Name == "John Smith", Name := paste0(Name, "1")]

В обоих вариантах объект данных обновляется ссылкой, т.е. Без копирования всего объекта, который экономит время и память.