Новая переменная основана на первом появлении другой переменной в каждой группе в R - PullRequest
0 голосов
/ 24 июня 2018

У меня есть длинный фрейм данных, подобный этому:

set.seed(17)
players<-rep(1:2, c(5,5))
decs<-sample(1:3,10,replace=TRUE)
world<-sample(1:2,10,replace=TRUE)
gamematrix<-cbind(players,decs,world)
gamematrix<-data.frame(gamematrix)
gamematrix

     players decs world
1        1    1     1
2        1    3     1
3        1    2     2
4        1    3     2
5        1    2     2
6        2    2     2
7        2    1     2
8        2    1     1
9        2    3     2
10       2    1     2

Я хочу создать для каждого игрока новую переменную, основанную на first появление переменной decs == 3 и состояние мира.

То есть, если при первом появлении «decs» состояние мира было «1», то новая переменная должна получить значение «6», в противном случае «7», следующим образом:

    players decs world player_type
1        1    1     1           6
2        1    3     1           6
3        1    2     2           6
4        1    3     2           6
5        1    2     2           6
6        2    2     2           7
7        2    1     2           7
8        2    1     1           7
9        2    3     2           7
10       2    1     2           7

Есть идеи как это сделать?

Ответы [ 3 ]

0 голосов
/ 24 июня 2018

Можно использовать cumsum(decs==3) == 1, чтобы найти первое вхождение decs == 3 для игрока. Теперь dplyr::case_when можно использовать для назначения типа игрока.

library(dplyr)

gamematrix %>% group_by(players) %>%
mutate(player_type = case_when(
   world[first(which(cumsum(decs==3)==1))] == 1 ~ 6L,
   world[first(which(cumsum(decs==3)==1))] == 2 ~ 7L,
  TRUE                              ~ NA_integer_))


# # A tibble: 10 x 4
# # Groups: players [2]
#   players  decs world player_type
#     <int> <int> <int>       <int>
# 1       1     1     1           6
# 2       1     3     1           6
# 3       1     2     2           6
# 4       1     3     2           6
# 5       1     2     2           6
# 6       2     2     2           7
# 7       2     1     2           7
# 8       2     1     1           7
# 9       2     3     2           7
# 10       2     1     2           7  
0 голосов
/ 24 июня 2018

Мы могли бы использовать data.table

library(data.table)
setDT(gamematrix)[, player_type := c(7, 6)[any(decs == 3& world == 1) + 1],
              by =  players]
gamematrix
#    players decs world player_type
# 1:       1    1     1           6
# 2:       1    3     1           6
# 3:       1    2     2           6
# 4:       1    3     2           6
# 5:       1    2     2           6
# 6:       2    2     2           7
# 7:       2    1     2           7
# 8:       2    1     1           7
# 9:       2    3     2           7
#10:       2    1     2           7
0 голосов
/ 24 июня 2018

Этот tidyverse подход может быть немного громоздким, но он должен дать вам то, что вы хотите.

library(tidyverse)
left_join(
  gamematrix,
  gamematrix %>%
    filter(decs == 3) %>%
    group_by(players) %>%
    slice(1) %>%
    mutate(player_type = ifelse(world == 1, 6, 7)) %>%
    select(players, player_type),
  by = 'players'
)
#   players decs world player_type
#1        1    1     1           6
#2        1    3     1           6
#3        1    2     2           6
#4        1    3     2           6
#5        1    2     2           6
#6        2    2     2           7
#7        2    1     2           7
#8        2    1     1           7
#9        2    3     2           7
#10       2    1     2           7

Идея состоит в том, чтобы filter получить данные для наблюдений, где decs == 3, извлечь первый элемент для каждого "игрока", добавить player_type в зависимости от состояния "мира" и, наконец, объединить с вашими исходными данными.

...