简体   繁体   中英

New variable based on first appearance of another variable in each group in R

I have a long data frame like this one:

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

I want to create for each player a new variable, that is based on the first appearance of the decs==3 variable, and the state of the world.

That is, if when the first appearance of "decs", the state of the world was "1", then the new variable should get the value of "6", otherwise, "7", as follows:

    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

Any ideas how to do it?

This tidyverse approach might be a little cumbersome but it should give you what you want.

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

The idea is to filter you data for observations where decs == 3 , extract the first element per 'players', add player_type subject to the state of the 'world' and finally merge with your original data.

An option is to use cumsum(decs==3) == 1 to find first occurrence of decs == 3 for a player. Now, dplyr::case_when can be used to assign player type.

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  

We could use 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM