1

This is an extension of the question here.

I have a dataframe like so:

df<-structure(list(person = c("p1", "p1", "p1", "p1", "p1", "p1", 
"p1", "p2", "p2", "p2", "p3", "p3", "p3", "p4", "p4", "p4", "p5", 
"p5", "p5", "p6", "p6", "p6", "p7", "p7", "p7"), hp_char = c("hp1", 
"hp2", "hp3", "hp4", "hp5", "hp6", "hp7", "hp8", "hp9", "hp10", 
"hp1", "hp2", "hp3", "hp5", "hp6", "hp7", "hp8", "hp9", "hp10", 
"hp3", "hp4", "hp5", "hp1", "hp2", "hp3")), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -25L), .Names = c("person", 
"hp_char"), spec = structure(list(cols = structure(list(person = structure(list(), class = c("collector_character", 
"collector")), hp_char = structure(list(), class = c("collector_character", 
"collector"))), .Names = c("person", "hp_char")), default = structure(list(), class = c("collector_guess", 
"collector"))), .Names = c("cols", "default"), class = "col_spec"))

Following the really efficient self-join/data.table answer provided by Uwe I get the number of instances of co-ocurrence of any TWO "hp_id" as follows:

df_by2<- setDT(df)[df, on = "person", allow = TRUE][
    hp_char < i.hp_char, .N, by = .(HP_ID1 = hp_char, HP_ID2 = i.hp_char)]

This gives me:

    HP_ID1 HP_ID2 N
 1:    hp1    hp2 3
 2:    hp1    hp3 3
 3:    hp2    hp3 3
 4:    hp1    hp4 1
 5:    hp2    hp4 1
 6:    hp3    hp4 2
 7:    hp1    hp5 1
 8:    hp2    hp5 1
 9:    hp3    hp5 2
10:    hp4    hp5 2
11:    hp1    hp6 1
12:    hp2    hp6 1
13:    hp3    hp6 1
14:    hp4    hp6 1
15:    hp5    hp6 2
16:    hp1    hp7 1
17:    hp2    hp7 1
18:    hp3    hp7 1
19:    hp4    hp7 1
20:    hp5    hp7 2
21:    hp6    hp7 2
22:   hp10    hp8 2
23:    hp8    hp9 2
24:   hp10    hp9 2

However I was wondering if an extension of this method could be made where the number of instance of co-ocurrence of greater than two "hp_char" could be calculated. In other words I was looking for an output (e.g. for number of times 3 events occurring) in like so:

  HP_ID1 HP_ID2 HP_ID3 N
1    hp1    hp2    hp3 3
2    hp3    hp4    hp5 2
3    hp5    hp6    hp7 2
4    hp8    hp9   hp10 2

So far I have been able to find multiple solutions for cooccurrence of two events but they do not seem to be generalizable to counting instances of >2 events. Thanks for any help!

thisisrg
  • 596
  • 3
  • 12

2 Answers2

2

It is prob cleaner if you use the combination approach:

library(data.table)
setDT(df)

nset <- 3
cols <- paste0("hp_char", seq_len(nset))

#create combinations of nset number of skills
combi <- do.call(CJ, rep(df[,.(unique(hp_char))], nset))
setnames(combi, cols)

#create for each person the combinations of nset number of skills
nsetSkills <- df[, do.call(CJ, rep(.(hp_char), nset)), by=.(person)]
setnames(nsetSkills, names(nsetSkills)[-1L], cols)

#join the above 2 sets and calculate the occurrence for each row in combi
ans <- nsetSkills[combi, on=cols, .N, by=.EACHI]
ans

output:

      hp_char1 hp_char2 hp_char3 N
   1:      hp1      hp1      hp1 3
   2:      hp1      hp1     hp10 0
   3:      hp1      hp1      hp2 3
   4:      hp1      hp1      hp3 3
   5:      hp1      hp1      hp4 1
  ---                             
 996:      hp9      hp9      hp5 0
 997:      hp9      hp9      hp6 0
 998:      hp9      hp9      hp7 0
 999:      hp9      hp9      hp8 2
1000:      hp9      hp9      hp9 2
chinsoon12
  • 25,005
  • 4
  • 25
  • 35
1

You can do a double self-join, the rest of it is pretty much the same:

df2 <- setDT(df)[df, on = "person", allow = TRUE][df, 
                     on = "person", allow = TRUE]

df2[hp_char < i.hp_char & i.hp_char < i.hp_char.1,
    .N,  by = .(HP_ID1 = hp_char, 
                HP_ID2 = i.hp_char,
                HP_ID3 = i.hp_char.1)][N >= 2]
#   HP_ID1 HP_ID2 HP_ID3 N
#1:    hp1    hp2    hp3 3
#2:    hp3    hp4    hp5 2
#3:    hp5    hp6    hp7 2
#4:   hp10    hp8    hp9 2
mtoto
  • 23,919
  • 4
  • 58
  • 71
  • Great thanks! this works great . Also works really fast with large dataframes. Sorry I am not too familiar with data.table.. for combinations of 4 , 5 ..., n I would just do a triple, quadruple,.., n-1 join and so forth. Do you know of a general syntax for this , if there are any? Thanks. – thisisrg Aug 24 '18 at 22:54