Использование списков для упрощения кода в R - PullRequest
0 голосов
/ 14 мая 2018

Справочная информация:

Привет всем,

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

Вот ситуация, в которой, я полагаю, можно значительно упростить этот тип кода, который я часто пишу, и который я хочу заменить на более сжатый формат.

Пример:

Давайте представим, что все данные mtcars были за один год наблюдения - скажем, 2018. Давайте также представим, что у нас были данные, возвращающиеся ежегодно до 2000 года. Итак, теперь есть «18» mtcars data.frames со столбцом года, в котором указано год, и мы берем 18 наблюдений и связываем их в один ряд. Это пример типа данных, с которыми я сейчас работаю. Наблюдения разделены по годам.

data <- mtcars %>%
group_by(date) %>%
  mutate(rank = dense_rank(desc(mpg))
         ))

Манипулирование данными, которое я хотел бы упростить:

  • Фильтрация: я хочу отфильтровать все для данного года по разным разрядам миль на галлон

    данные%>% фильтр (передача == 4, дата == '2005')%>% фильтр (ранг% в% c (1: 5))

    данные%>% фильтр (передача == 4, дата == '2005')%>% фильтр (ранг% в% c (6:10))

    данные%>% фильтр (передача == 4, дата == '2005')%>% фильтр (рейтинг% в% c (11:15))

Как лучше всего упростить избыточный блок кода выше?

Например, я хотел бы использовать функцию seq и сделать что-то вроде:

    data %>% 
filter(gear == 4, date == '2005') %>%
filter(rank %in% seq(1, 100, by = 5))

и сохраните результаты каждой группы рангов в список, а затем разместите все эти списки в ggplot.

Буду очень признателен за любую помощь или совет, я пытаюсь улучшить свою игру здесь.

1 Ответ

0 голосов
/ 15 мая 2018

Обучение работе со списками и столбцами списков может быть довольно сложным.Я очень рекомендую purrr учебник Дженни Брайан .Здесь вы пытаетесь избежать многократного выполнения строк filter для различных значений year, gear и rank.Есть несколько шагов:

  1. Выясните, как получить все комбинации значений, которые вы хотите.Мы делаем это здесь с помощью purrr::cross_df, который является очень удобным способом получения комбинаций переменных.
  2. Фактически выполните операцию для каждой комбинации.Поскольку теперь наши данные настроены так, чтобы каждая строка представляла собой набор входных данных, мы можем использовать pmap для хранения каждого отфильтрованного набора данных в качестве элемента списка.В зависимости от графика, который мы хотим, мы можем затем использовать другие инструменты, такие как unnest, чтобы фактически преобразовать данные в формат, который мы хотим построить.

Я надеюсь, что это может проиллюстрировать это в целом, если вы понимаете,вы делаете что-то слишком много раз, в основном это два шага;создайте список или списки, которые вы можете перебирать, и используйте функцию map, чтобы применить операцию, которую вы хотите, к каждому элементу списка.

library(tidyverse)
data <- mtcars %>%
  bind_rows(
    mtcars %>% mutate(year = 2005),
    mtcars %>% mutate(year = 2006)
    ) %>% 
  group_by(year) %>%
  mutate(rank = dense_rank(desc(mpg)))

combos <- cross_df(list(
  year = 2005:2006,
  gear = 3:5,
  start = seq(1, 100, by = 5)
  ))

combos %>%
  mutate(
    rank_range = map(start, ~ .x:(.x + 4)),
    filtered = pmap(
      .l = list(year, gear, rank_range),
      .f = ~ data %>%
        filter(gear == ..2, year == ..1) %>%
        filter(rank %in% ..3)
        )
    )
#> # A tibble: 120 x 5
#>     year  gear start rank_range filtered         
#>    <int> <int> <dbl> <list>     <list>           
#>  1  2005     3     1 <int [5]>  <tibble [0 x 13]>
#>  2  2006     3     1 <int [5]>  <tibble [0 x 13]>
#>  3  2005     4     1 <int [5]>  <tibble [4 x 13]>
#>  4  2006     4     1 <int [5]>  <tibble [4 x 13]>
#>  5  2005     5     1 <int [5]>  <tibble [2 x 13]>
#>  6  2006     5     1 <int [5]>  <tibble [2 x 13]>
#>  7  2005     3     6 <int [5]>  <tibble [2 x 13]>
#>  8  2006     3     6 <int [5]>  <tibble [2 x 13]>
#>  9  2005     4     6 <int [5]>  <tibble [6 x 13]>
#> 10  2006     4     6 <int [5]>  <tibble [6 x 13]>
#> # ... with 110 more rows

Создано в 2018-05-14 с помощью Представить пакет (v0.2.0).

...