присоединиться к data.table, сохраняя идентификаторы столбцов - PullRequest
0 голосов
/ 27 августа 2018

Я хочу сохранить столбец (= "персона" в кадре данных) после выполнения соединения в таблице data.table.Мне удалось получить что-то близкое к желаемому выводу, но для этого потребовалось переключение между data.table и dplyr из-за моего ограниченного опыта работы с data.table:

Здесь фрейм данных:

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"))

Я делаю самосоединение, чтобы получить количество экземпляров совместного появления любых двух «hp_id» следующим образом (аналогично тому, что было разработано в в этом вопросе ).Я держу «человека» в by=.(...), чтобы узнать, кто был вовлечен в комбинации «случайности» (например, hp1 и hp2, которые совместно встречались у людей p1, p3 и p7):

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

Однако из-за включения »person "в by =.(person,..., количество (= N) разделяется в соответствии с комбинацией" person "," hp_id "и" hp_id2 ".Поэтому я переключился на dplyr, чтобы приблизиться к тому, что я хочу, следующим образом.

dfx<- df_by2 %>% group_by(HP_ID1,HP_ID2) %>% mutate (counts=length(person)) %>% spread(person,person) %>% select (-N) %>% unique() %>% filter(counts>1) %>% unite(person,p1:p7, sep="") %>% mutate (involved_id=gsub('?NA', ' ', person)) %>% select (-person)

Это вывод, который я получаю:

# A tibble: 12 x 4
   HP_ID1 HP_ID2 counts   involved_id
    <chr>  <chr>  <int>      <chr>
 1    hp1    hp2      3 p1 p3   p7
 2    hp1    hp3      3 p1 p3   p7
 3   hp10    hp8      2   p2  p5  
 4   hp10    hp9      2   p2  p5  
 5    hp2    hp3      3 p1 p3   p7
 6    hp3    hp4      2  p1    p6 
 7    hp3    hp5      2  p1    p6 
 8    hp4    hp5      2  p1    p6 
 9    hp5    hp6      2  p1  p4   
10    hp5    hp7      2  p1  p4   
11    hp6    hp7      2  p1  p4   
12    hp8    hp9      2   p2  p5 

Это близко, но желаемый вывод (с правильно отформатированным, хотя и неопрятным столбцом "used_id"):

# A tibble: 12 x 4
   HP_ID1 HP_ID2 counts   involved_id
    <chr>  <chr>  <int>      <chr>
 1    hp1    hp2      3 p1, p3, p7
 2    hp1    hp3      3 p1, p3, p7
 3   hp10    hp8      2     p2, p5
 4   hp10    hp9      2     p2, p5
 5    hp2    hp3      3 p1, p3, p7
 6    hp3    hp4      2     p1, p6
 7    hp3    hp5      2     p1, p6
 8    hp4    hp5      2     p1, p6
 9    hp5    hp6      2     p1, p4
10    hp5    hp7      2     p1, p4
11    hp6    hp7      2     p1, p4
12    hp8    hp9      2     p2, p5

Все это очень громоздко, и мне было интересно, есть ли более простой подход к этому.Я только недавно натолкнулся на data.table и с удовольствием изучаю его.Любая помощь с использованием data.table высоко ценится.

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Продолжая ответ, отправленный ранее здесь (также скопированный здесь для удобства), вместо этого используйте .(.N, involved_id=paste(x.person, collapse=", ")) для конечного желаемого результата:

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)

ans <- nsetSkills[combi, on=cols, 
    .(.N, involved_id=paste(x.person, collapse=", ")), by=.EACHI]
ans

вывод:

      hp_char1 hp_char2 hp_char3 N involved_id
   1:      hp1      hp1      hp1 3  p1, p3, p7
   2:      hp1      hp1     hp10 0          NA
   3:      hp1      hp1      hp2 3  p1, p3, p7
   4:      hp1      hp1      hp3 3  p1, p3, p7
   5:      hp1      hp1      hp4 1          p1
  ---                                         
 996:      hp9      hp9      hp5 0          NA
 997:      hp9      hp9      hp6 0          NA
 998:      hp9      hp9      hp7 0          NA
 999:      hp9      hp9      hp8 2      p2, p5
1000:      hp9      hp9      hp9 2      p2, p5
0 голосов
/ 27 августа 2018

Возможно, вы заинтересованы в подходе "все tidyverse" (самостоятельное объединение с использованием combn плюс суммирование)?

df %>%
    group_by(person) %>%
    summarise(tmp = list(setNames(
        as_tibble(t(combn(hp_char, 2))),
        c("HP_ID1", "HP_ID2")))) %>%
    unnest() %>%
    group_by(HP_ID1, HP_ID2) %>%
    summarise(
        counts = n(),
        involved_id = toString(person)) %>%
    filter(counts > 1)
## A tibble: 12 x 4
## Groups:   HP_ID1 [8]
#   HP_ID1 HP_ID2 counts involved_id
#   <chr>  <chr>   <int> <chr>
# 1 hp1    hp2         3 p1, p3, p7
# 2 hp1    hp3         3 p1, p3, p7
# 3 hp2    hp3         3 p1, p3, p7
# 4 hp3    hp4         2 p1, p6
# 5 hp3    hp5         2 p1, p6
# 6 hp4    hp5         2 p1, p6
# 7 hp5    hp6         2 p1, p4
# 8 hp5    hp7         2 p1, p4
# 9 hp6    hp7         2 p1, p4
#10 hp8    hp10        2 p2, p5
#11 hp8    hp9         2 p2, p5
#12 hp9    hp10        2 p2, p5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...