для цикла в R, не дающего желаемого результата

#r #for-loop #tidyverse

#r #цикл for #tidyverse

Вопрос:

В R, когда я ввожу следующий код в набор данных iris:

 iris %>% 
  filter(Petal.Width == 0.2 amp; Species == "setosa") %>% 
  dim()
  

Я получаю

 [1] 29  5
  

Я хотел бы перебирать значения, где Petal.Ширина = 0.1, 0.2, 0.3, 0.4, 0.5 и получаем 5 разных результатов.

 list1 = list(0.1, 0.2, 0.3, 0.4, 0.5)
for(i in list1){
  df_test <- iris %>% 
    filter(Petal.Width == i amp; Species == "setosa") %>% 
    dim()
}
df_test
  

Однако приведенный выше код возвращает только один результат:

 [1] 1 5
  

Почему это происходит и как я могу заставить его возвращать 5 результатов вместо этого?

Комментарии:

1. вам нужно создать пустой список и заполнять его на каждой итерации. Будет лучше, если вы сначала определите измерение, если вы знаете его заранее.

2. l <- list() вне цикла, затем назначьте с l[i] <- внутри.

3. df_test изменяется на каждой итерации, в конце остается только последняя

4. @RLave Создание пустого списка и его динамическое заполнение возможно, но не очень эффективно. Лучше использовать map (или lapply ).

5. Согласен, я просто указывал на ошибки. Также я предположил, что лучше сначала определить размер выходных данных.

Ответ №1:

Здесь нет необходимости в явном for цикле; вместо этого лучше использовать map (или lapply в базовом R)

 library(tidyverse)
map(list1, ~iris %>%
  filter(Petal.Width == .x amp; Species == "setosa") %>%
  dim())
#[[1]]
#[1] 5 5
#
#[[2]]
#[1] 29  5
#
#[[3]]
#[1] 7 5
#
#[[4]]
#[1] 7 5
#
#[[5]]
#[1] 1 5
  

Выходным объектом является list .


В ответ на ваш комментарий вы могли бы использовать вложенный map

 map(setNames(list1, list1), function(x) map(setNames(list2, list2), function(y) iris %>%
    filter(Petal.Width == x amp; Species == y) %>%
    dim()))
#$`0.1`
#$`0.1`$setosa
#[1] 5 5
#
#$`0.1`$versicolor
#[1] 0 5
#
#$`0.1`$virginica
#[1] 0 5
#
#
#$`0.2`
#$`0.2`$setosa
#[1] 29  5
#
#$`0.2`$versicolor
#[1] 0 5
#
#$`0.2`$virginica
#[1] 0 5
#
#
#$`0.3`
#$`0.3`$setosa
#[1] 7 5
#
#$`0.3`$versicolor
#[1] 0 5
#
#$`0.3`$virginica
#[1] 0 5
#
#
#$`0.4`
#$`0.4`$setosa
#[1] 7 5
#
#$`0.4`$versicolor
#[1] 0 5
#
#$`0.4`$virginica
#[1] 0 5
#
#
#$`0.5`
#$`0.5`$setosa
#[1] 1 5
#
#$`0.5`$versicolor
#[1] 0 5
#
#$`0.5`$virginica
#[1] 0 5
  

Комментарии:

1. что я могу сделать, если теперь я хочу также выполнить цикл по списку1 и всем значениям Species? В этом случае я создаю list2 = list("setosa", "versicolor", "virginica") . Я бы ожидал 15 результатов, поскольку мне нужны все комбинации list1 и list2?

2. @wussyx Я бы использовал вложенный map подход, смотрите Мое обновление. Затем flatten вложенное list по мере необходимости.