Группировка по двум переменным и выбор лучших значений одной из них в dplyr - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть некоторые данные о выборах за несколько лет в нескольких штатах с различным числом кандидатов каждый год. Примерное представление ниже.

library(tidyverse)

set.seed(1124)

df <- cbind(
  sample(LETTERS[1:3], size = 40, replace = TRUE),
  as.numeric(sample(2009:2013, size = 40, replace = TRUE)), 
  sample(letters, size = 40, replace = TRUE),
  as.numeric(sample(1:5000, size = 40))
)

colnames(df) <- c("states", "year", "candidate", "votes")

df <- as.tibble(df)

df
#> # A tibble: 40 x 4
#>    states year  candidate votes
#>    <chr>  <chr> <chr>     <chr>
#>  1 B      2010  w         1402 
#>  2 A      2012  o         3646 
#>  3 A      2009  x         4073 
#>  4 A      2012  w         713  
#>  5 A      2012  n         4810 
#>  6 C      2011  i         4096 
#>  7 B      2010  u         215  
#>  8 A      2012  j         1928 
#>  9 C      2013  e         1889 
#> 10 B      2013  z         4888 
#> # ... with 30 more rows

Я просто хотел бы хранить в отдельном файле строки последних n лет выборов в каждом штате. Например, последние два могут быть: A 2012, A 2010, B 2013, B 2010, C 2012, C 2009 и все связанные с ними сведения о кандидате и голосовании (а также другие, которые я не включил в репрезентацию как ненужные ).

Я думал, что мог бы просто добиться этого с помощью кода, приведенного ниже, но я выбираю все выделенное ... group_by(states) и top_n(2, wt = year) также не дают ожидаемого результата.

Я не вижу другого пути. Другие решения, такие как , это не совсем подходят.

select_df <- df %>% 
  group_by(states, year) %>% 
  top_n(n = 2, wt = year)

Буду очень признателен за любые указатели!

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Чтобы избежать проблем со связями для top_n, вы можете сделать следующее:

df %>% 
  arrange(states, year) %>%  # For clearer ordering
  group_by(states, year) %>%  
  nest() %>%                 # nest everything which is not state or year  
  group_by(states) %>%       # We want to have top years by states
  top_n(n = 2, year) %>%     # No ties and no problems with top_n
  unnest()                   # Duplicated rows for several candidates per state and year

# A tibble: 16 x 4
# Groups:   states [3]
   states year  candidate votes
   <chr>  <chr> <chr>     <chr>
 1 A      2012  o         3646 
 2 A      2012  w         713  
 3 A      2012  n         4810 
 4 A      2012  j         1928 
 5 A      2012  h         1699 
 6 A      2013  c         2873 
 7 B      2012  n         3502 
 8 B      2012  z         1079 
 9 B      2012  k         3207 
10 B      2013  z         4888 
11 B      2013  l         3483 
12 C      2012  x         2241 
13 C      2012  b         4994 
14 C      2013  e         1889 
15 C      2013  h         3858 
16 C      2013  z         186  

Без вложенности (что может быть неудобно при слишком больших наборах данных) вы сначала извлекаете верхние годы по штатам, а затем фильтруете по ним, как показано ниже:

df %>% 
  arrange(states, year) %>%   # Sorting is important to select correct years
  group_by(states) %>% 
  mutate(top_year = list(tail(unique(year), 2))) %>%  # If not pre sorted, use sort() here
  rowwise() %>% 
  filter(year %in% top_year)

Пояснение к первому решению
Почему мы должны использовать nest()? Давайте посмотрим, что произойдет, если мы пропустим это:

df %>% 
  arrange(states, year) %>%  
  group_by(states, year) %>% 
  group_by(states) %>%       
  top_n(n = 2, year)         

# A tibble: 11 x 4
# Groups:   states [3]
#    states year  candidate votes
#    <chr>  <chr> <chr>     <chr>
#  1 A      2012  o         3646 
#  2 A      2012  w         713  
#  3 A      2012  n         4810 
#  4 A      2012  j         1928 
#  5 A      2012  h         1699 
#  6 A      2013  c         2873 
#  7 B      2013  z         4888 
#  8 B      2013  l         3483 
#  9 C      2013  e         1889 
# 10 C      2013  h         3858 
# 11 C      2013  z         186  

Для состояния A это не имеет значения, но для B и C. Это связано с тем, как работает top_n. Он выберет 2 верхние строки, взвешенные по переменному году. Для состояния А это год 2013, а затем 2012. Существует несколько строк с состоянием А и 2012 годом, поэтому top_n выбирает все из них. Для штатов B и C верхний год (2013) уже заполняет 2 или более строк, поэтому top_n выбирает их и готово. Таким образом, он выбирает строки с верхним годом и выбирает годы, пока количество строк не будет заполнено.

Посмотрим, что произойдет, если мы вложим данные:

df %>% 
  arrange(states, year) %>%  
  group_by(states, year) %>%  
  nest() 

# A tibble: 14 x 3
#    states year  data            
#    <chr>  <chr> <list>          
#  1 A      2009  <tibble [3 x 2]>
#  2 A      2011  <tibble [2 x 2]>
#  3 A      2012  <tibble [5 x 2]>
#  4 A      2013  <tibble [1 x 2]>
#  5 B      2009  <tibble [2 x 2]>
#  6 B      2010  <tibble [7 x 2]>
#  7 B      2011  <tibble [1 x 2]>
#  8 B      2012  <tibble [3 x 2]>
#  9 B      2013  <tibble [2 x 2]>
# 10 C      2009  <tibble [3 x 2]>
# 11 C      2010  <tibble [2 x 2]>
# 12 C      2011  <tibble [4 x 2]>
# 13 C      2012  <tibble [2 x 2]>
# 14 C      2013  <tibble [3 x 2]>

Теперь у нас нет нескольких строк в год, поэтому мы действительно выбираем два верхних года с top_n.

0 голосов
/ 07 ноября 2018

Рекомендую попробовать slice

df %>% 
  mutate(year = as.numeric(year)) %>%
  arrange(-desc(states), -desc(year)) %>%
  group_by(states) %>%
  mutate(id = row_number()) %>%
  slice((n()-1):n())

enter image description here

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