#r #loops #for-loop #if-statement
#r #циклы #for-цикл #if-оператор
Вопрос:
Это пример фрейма данных, с которым я работаю:
numbers <- data.frame(value=c(-5000,1,2,100,200,300,400,500, 1000, 2000, 10000, 12000))
Я хочу создать новый столбец в этом фрейме данных под названием «output», который содержит следующие значения:
— То же значение, что и в столбце «значение», если значение от 1 до 10000
-10000, если значение в столбце «значение» больше 10000 и
-1, если значение в столбце «значение» меньше 1
Желаемый результат в новом столбце «вывод»: 1,1,2,100,200,300,400,500, 1000,2000, 10000, 10000.
Я бы очень хотел узнать, как использовать операторы for loop, if, else if и else для получения этого вывода, и попробовал следующее:
for (i in 1:nrow (numbers$value)){
if (numbers$value[i] >10000){
numbers$output <- 10000)
} else if (numbers$value[i] < 1){
numbers$output <- 1)
} else {
numbers$output <- numbers$value)
}
}
К сожалению, это выдает ошибку, ошибка: неожиданный ‘}’ в «}»
Ценю вашу помощь в исправлении этого кода!
Комментарии:
1. Это не вопрос, но я предлагаю рассмотреть
case_when
в случаях с более чем двумяif
.library(dplyr) numbers %>% mutate(newCol = case_when(between(value, 1,10000) ~ value, value > 10000 ~ 10000, value < 1 ~ 1))
Ответ №1:
Я понимаю, почему вы пытаетесь решить эту проблему с помощью цикла for (я был там ..). В R есть полезная вещь, называемая векторизацией. Вы можете использовать семейство *apply для применения функции к входному вектору. Таким образом, вы предоставляете функции входные данные и автоматически получаете выходные данные той же длины.
sapply(numbers$value, function(x){
if (x >10000) return(10000)
else if (x < 1) return(1)
else return(x)
}) -> numbers$output
Комментарии:
1. Большое спасибо! Это отлично работает.
2. В качестве продолжения могу ли я спросить, как я мог бы реплицировать этот код для нескольких столбцов в одном и том же фрейме данных. Пример фрейма данных: numbersnew <- data.frame(value1=c(-5000,1,2,100,200,300,400,500, 1000, 2000, 10000, 12000), значение2= c(-4000, 3,4, 150, 250, 350, 450, 550, 1050, 2050, 10050, 12050))
3. purrr.tidyverse.org/reference/map_if.html — map_if позволит вам выбрать столбцы для применения функции
Ответ №2:
В исходном коде есть несколько ошибок: не инициализация выходной переменной, несоответствующее и ненужное «)», не использование индексов при необходимости и другие ошибки. Смотрите Исправленный код ниже.
numbers <- data.frame(value=c(-5000,1,2,100,200,300,400,500, 1000, 2000, 10000, 12000))
numbers$output<-NA
for (i in 1:nrow(numbers)){
if (numbers$value[i] >10000){
numbers$output[i] <- 10000
} else if (numbers$value[i] < 1){
numbers$output[i] <- 1
} else {
numbers$output[i] <- numbers$value[i]
}
}
numbers
Вот более простое решение, использующее case_when
функцию из пакета dplyr:
numbers <- data.frame(value=c(-5000,1,2,100,200,300,400,500, 1000, 2000, 10000, 12000))
library(dplyr)
numbers$output <-case_when(
numbers$value >10000 ~ 10000,
numbers$value < 1 ~ 1,
TRUE ~ numbers$value. #default case
)
numbers
Комментарии:
1. Большое спасибо за исправление кода и предложение другого решения! Ценю это
Ответ №3:
в духе ifelse-ness вы также можете использовать ifelse()
функцию.
numbers$output <- ifelse(numbers$value > 1000, 1000, ifelse(numbers$value < 0, 1, numbers$value))
Комментарии:
1. ifelse(число$value, < 1, -1, min(число$value, 10000))
2. умный, все еще слишком много запятой