Синтаксис If, else if и else в цикле for в R

#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. умный, все еще слишком много запятой