dplyr решение для группировки и подсчета вхождения выбранных значений - PullRequest
0 голосов
/ 29 февраля 2020

У меня есть такие данные:

       inpput <- read_table2("id    genre   rank    gamewin
1   R.B 1   0
1   Pop NA  0
1   Hip.Hop 5   0
1   Pop 1   0
1   Rock    1   0
1   R.B 15  0
1   Hip.Hop 1   0
1   Electronic  1   0
1   Electronic  1   0
1   Hip.Hop 1   0
1   Pop 1   0
1   Rock    NA  0
1   Electronic  NA  0
1   Pop 1   0
1   gameWin gameWin game-restart
1   Rap NA  0
1   Rock    NA  0
1   Pop NA  0
1   Electronic  NA  0
1   R.B NA  0
1   Rap 5   0
1   Pop 5   0
1   Hip.Hop 5   0
1   Pop 1   0
1   Rap NA  0
1   gameWin gameWin game-restart
")

Я хотел бы создать фрейм данных, такой как этот,

  1. Переменная «игра». Указание номера игры для каждого ID. Каждая новая игра обозначается флагом «gameWin». Когда когда-либо gameWin == "game-restart", запускается новая игра. Хотя в образце набора данных есть только один идентификатор, в действительности их гораздо больше.

  2. Переменная «gamewinrank <10», которая подсчитывает случаи, когда переменная rank равна 1 или rank <= 10 для уникальных жанров. Таким образом, если «rank = 1» для хип-хопа дважды в одной и той же игре, он учитывается только один раз. </p>

    3) Переменная «gamewin_rank1», которая считает случаи, когда rank = 1 для уникальных жанров. Таким образом, в пределах идентификатора игры (сгруппированного по игре, идентификатору), если rank = 1 для рэпа и rank = 1 для рока, поле будет выводить 2. Аналогично, в пределах идентификатора игры rank = 1 для рэпа, rank = 1 для камень и другой ранг = 1 для камня, поле все равно выдает два.

Вывод должен выглядеть следующим образом:

output <- read_table2("id   genre   rank    gamewin game    gamewin_rank<10 gamewin_rank1
1   R.B 1   0   1       
1   Pop NA  0   1       
1   Hip.Hop 5   0   1       
1   Pop 1   0   1       
1   Rock    1   0   1       
1   R.B 15  0   1       
1   Hip.Hop 1   0   1       
1   Electronic  1   0   1       
1   Electronic  1   0   1       
1   Hip.Hop 1   0   1       
1   Pop 1   0   1       
1   Rock    NA  0   1       
1   Electronic  NA  0   1       
1   Pop 1   0   1       
1   gameWin gameWin game-restart    1   5   5
1   Rap NA  0   2       
1   Rock    NA  0   2       
1   Pop NA  0   2       
1   Electronic  NA  0   2       
1   R.B NA  0   2       
1   Rap 5   0   2       
1   Pop 5   0   2       
1   Hip.Hop 5   0   2       
1   Pop 1   0   2       
1   Rap NA  0   2       
1   gameWin gameWin game-restart    2   3   1
")

Я думал об использовании case_when и mutate для выполнения sh этого, но я не знаю как определить уникальность жанра в пределах установленного ранга, любая помощь приветствуется!

1 Ответ

1 голос
/ 29 февраля 2020

Без полного вывода трудно точно сказать, что вы ищете, но это должно быть близко:

input %>% 
  mutate_at(vars(rank), as.numeric) %>% 
  group_by(id) %>% 
  mutate(
    gamewin = gamewin == "game-restart",
    game = lag(cumsum(gamewin) + 1) %>% ifelse(is.na(.),1, .)
    ) %>%
  group_by(id,game) %>% 
  mutate( 
    'gamewin_rank<10' = case_when(
      gamewin ~ length(unique(genre[which(rank <= 10)])),
      TRUE    ~ NA_integer_),
    gamewin_rank1 = case_when(
      gamewin ~ length(unique(genre[which(rank == 1)])),
      TRUE    ~ NA_integer_)
    ) 

Переменная «игра». Указание номера игры для каждого ID. Каждая новая игра обозначается флагом «gameWin». Когда когда-либо gameWin == "game-restart", запускается новая игра. Хотя в образце набора данных есть только один идентификатор, в действительности их гораздо больше.

Мы можем сделать это легко, преобразовав столбец gamewin в логическое состояние, которое мы можем посчитать, а затем выполнив команду cumsum вдоль нее. (Как правило, хранение 0 и строки занимает больше памяти, чем логический столбец, поэтому я рекомендую использовать это в другом месте, плюс вы получите замечательные преимущества ИСТИНЫ, равные 1 для математических целей.) Поскольку вы хотите добавить один после всплывает gamewin, мы добавляем лаг, а затем бит ifelse(is.na(.)) должен указывать на первое значение, являющееся NA из-за отставания.

Переменная «gamewinrank <10», которая считает случаи где переменная ранг равна 1 или ранг <= 10 для уникальных жанров. Таким образом, если "rank = 1" для хип-хопа дважды в одной и той же игре, он считается только один раз. </p>

Я реализовал то, что вы просили, но я не уверен, что это действительно то, что вы имели в виду, потому что вы получили значение 3 и определенно есть пять уникальных жанров, где ранг <= 10 (мы не нужно оценивать ранг == 1, потому что это входит в ранг <= 10). Возможно, вы могли бы перефразировать, и я могу отредактировать это, чтобы помочь? </p>

Переменная "gamewin_rank1", которая считает случаи, где rank = 1 для уникальных жанров. Таким образом, в пределах идентификатора игры (сгруппированного по игре, идентификатору), если rank = 1 для рэпа и rank = 1 для рока, поле выдает 2. Также в рамках идентификатора игры rank = 1 для рэпа, rank = 1 для рок и другой ранг = 1 для рок, поле все равно будет выводить два.

Та же реализация, что и выше, ограничиваясь рангом == 1.

Редактировать: Вот что я думаю, что вы на самом деле после re: итоговая статистика с использованием суммирования вместо мутирования, как обсуждалось в комментариях:

input %>% 
  mutate_at(vars(rank), as.numeric) %>% 
  group_by(id) %>% 
  mutate(
    gamewin = gamewin == "game-restart",
    game = lag(cumsum(gamewin) + 1) %>% ifelse(is.na(.),1, .)
  ) %>%
  group_by(id,game) %>% 
  summarize( 
    'gamewin_rank<10' = length(unique(genre[which(rank <= 10)])),
    gamewin_rank1 = length(unique(genre[which(rank == 1)])),
    hiphop = sum(genre=="Hip.Hop" & rank == 1) 
  )
...