Условная замена строки во фрейме данных - PullRequest
2 голосов
/ 12 июня 2019
DF <- data.frame("ID" = c(901, 902, 903, 904, 909), "INT" = c(0, 1, 0, 1, 1))

> DF
   ID INT
1 901   0
2 902   1
3 903   0
4 904   1
5 909   1

Я хочу заменить "9" в столбце идентификатора, когда INT = 1, поэтому он должен выглядеть следующим образом:

 New_DF
   ID INT
1 901   0
2 802   1
3 903   0
4 804   1
5 809   1

Я пробовал это

if(DF$INT == "1") {
  gsub("^9", "8", DF$ID) 
}

Это дает мне следующую ошибку:

Предупреждающее сообщение: In if (DF $ INT == "1") {: условие имеет длину> 1, и будет использоваться только первый элемент

Ответы [ 5 ]

2 голосов
/ 12 июня 2019

Вы можете использовать log, чтобы найти количество цифр, а затем вычесть 10 из числа, увеличенного до количества цифр, если INT равно 1.Таким образом, ID все равно будет numeric.

digits = floor(log(DF$ID, 10))
transform(DF, ID = ID - (10^digits) * (floor(ID/(10^digits)) == 9) * (INT))
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1
2 голосов
/ 12 июня 2019

Вам необходимо использовать функцию ifelse().

DF$ID <- ifelse(DF$INT == 1,  gsub("^9", "8", DF$ID), DF$ID)

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

DF %>% 
   mutate(ID=ifelse(INT==1,gsub("^9","8",ID),ID))

Это будет запускать gsub в строках, где DF$INT == 1, и если это не 1, то он останется прежним.

Используемая вами функция if():

if(DF$INT == "1") { }

не предназначен для работы на data.frame с. Функция if() используется только , чтобы проверить, является ли что-то (например, оператор) ИСТИНА или ЛОЖЬ. Например:

if(use_new_function == "on"){ 
    run_new_function() 
}
1 голос
/ 12 июня 2019

substring может использоваться для назначения. Создайте логический индекс на основе столбца «INT» и, проверив, является ли первый символ «ID» 9 («i1»), затем используйте substring для назначения первого символа «ID» для «8»

i1 <- as.logical(DF$INT) & substr(DF$ID, 1, 1) =='9'
substring(DF$ID[i1], 1, 1) <- '8'
DF
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1

данные

DF <- structure(list(ID = c("901", "902", "903", "904", "909"), 
 INT = c(0, 
  1, 0, 1, 1)), row.names = c(NA, -5L), class = "data.frame")
1 голос
/ 12 июня 2019

Сначала можно найти индексы, где INT равно 1, а затем использовать sub для замены значений этих индексов.

inds <- DF$INT == 1
DF$ID[inds] <- as.integer(sub("^9", "8", DF$ID[inds]))

DF
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1

Или мы также можем использовать ifelse

as.integer(ifelse(DF$INT == 1, sub("^9", "8", DF$ID), DF$ID))
#[1] 901 802 903 804 809
0 голосов
/ 12 июня 2019

Как в данных вашего примера DF оба столбца числовые , вы можете просто использовать

DF$ID[DF$INT==1] <- DF$ID[DF$INT==1] - 100

Если столбец ID является строкой , выможно использовать gsub как:

DF$ID <- as.character(DF$ID)
DF$ID[DF$INT==1] <- gsub("^9", "8", DF$ID[DF$INT==1])
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1

, который помещает ваш if(DF$INT == "1") в подмножество данных [DF$INT==1]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...