Эквивалент dplyr rowwsie combn в data.table

#r #data.table

#r #data.table

Вопрос:

У меня есть этот код, который выполняет combn для всех значений определенного фрейма данных. Это делается с помощью dplyr rowwise

 library(dplyr,warn.conflicts = FALSE)
library(tidyr)
Column1<-c("red","blue")#creating column1
Column2<-c("green","white")#creating column2
Column3<-c("aqua","magenta")#creating column2
df_1<-data.frame(Column1, Column2, Column3)#creating data frame
df_2 <- df_1 %>% rowwise() %>% 
  mutate(COMB=list(combn(c_across(Column1:Column3),2,simplify = FALSE))) %>% 
  unnest(cols = COMB) %>% 
  unnest(cols=COMB)
  

Создано 2020-11-07 пакетом reprex (версия 0.3.0)

Это приводит к следующему

 | # A tibble: 12 x 4                |
|------------------------------------|
|    Column1 Column2 Column3 COMB    |
|    <chr>   <chr>   <chr>   <chr>   |
|  1 red     green   aqua    red     |
|  2 red     green   aqua    green   |
|  3 red     green   aqua    red     |
|  4 red     green   aqua    aqua    |
|  5 red     green   aqua    green   |
|  6 red     green   aqua    aqua    |
|  7 blue    white   magenta blue    |
|  8 blue    white   magenta white   |
|  9 blue    white   magenta blue    |
| 10 blue    white   magenta magenta |
| 11 blue    white   magenta white   |
| 12 blue    white   magenta magenta |
  

Возможно ли выполнить функцию rowwise combn в data.table. Например, для следующего

 library(data.table)
Column1<-c("red","blue")#creating column1
Column2<-c("green","white")#creating column2
Column3<-c("aqua","magenta")#creating column2
df_1<-data.table(Column1, Column2, Column3)#creating DT
  

Создано 2020-11-07 пакетом reprex (версия 0.3.0)

Ответ №1:

С data.table помощью мы можем создать «ГРЕБЕНКУ», используя Map

 library(data.table)
setDT(df_1)[, COMB := list(do.call(Map, c(f1, .SD)))]
  

где

 f1 <- function(...) combn(c(...), m = 2, simplify = FALSE)
  

Или, если мы хотим расширить строки

 out <- df_1[, grp := seq_len(.N)][df_1[,
      combn(unlist(.SD), 2), .(grp)], on = .(grp)][, grp := NULL]
setnames(out, 'V1', 'COMB')
  

-вывод

 out
#    Column1 Column2 Column3    COMB
# 1:     red   green    aqua     red
# 2:     red   green    aqua   green
# 3:     red   green    aqua     red
# 4:     red   green    aqua    aqua
# 5:     red   green    aqua   green
# 6:     red   green    aqua    aqua
# 7:    blue   white magenta    blue
# 8:    blue   white magenta   white
# 9:    blue   white magenta    blue
#10:    blue   white magenta magenta
#11:    blue   white magenta   white
#12:    blue   white magenta magenta
  

Комментарии:

1. Большое спасибо @akrun. «out» был желаемым результатом, который я искал. Это сработало прекрасно. Я новичок в data.table, и у меня есть к вам дополнительный вопрос. Вместо Column1, Column2, Column3 если DT состоял из Column1, Column2, Column3, Column4, Column5, и я хотел передать только Column1, Column4, Column5 как x в combn(x,2), как я могу адаптировать ваше решение df_1[, grp := seq_len(.N)][df_1[, combn(unlist(.SD), 2), .(grp)], on = .(grp)][, grp := NULL] к этому?

2. Карта AFAIR переносится только в mapply, а с API mapply мне всегда было проще работать.

3. Если в DT присутствуют нежелательные столбцы combn, то адаптируйте решение akrun к тому сценарию df_1<-data.table(Column1, Column1_1, Column2, Column2_1, Column3) out <- df_1[, grp := seq_len(.N)] out1<-out[df_1[,combn(unlist(.SD), 2), by=.(grp,Column1_1,Column2_1)], on = .(grp,Column1_1,Column2_1)] out1[,!c("Column1_1","Column2_1","grp")] , когда Column1_1 и Column2_1 нежелательны в combn

Ответ №2:

Вы можете получать данные в длинном формате и создавать комбинации для каждой строки.

 library(data.table)

df_1[, row := seq_len(.N)]
df_2 <- melt(df_1, id.vars = 'row')
df_1[df_2[, combn(value, 2), row], on = 'row'][, row := NULL][]

#    Column1 Column2 Column3      V1
# 1:     red   green    aqua     red
# 2:     red   green    aqua   green
# 3:     red   green    aqua     red
# 4:     red   green    aqua    aqua
# 5:     red   green    aqua   green
# 6:     red   green    aqua    aqua
# 7:    blue   white magenta    blue
# 8:    blue   white magenta   white
# 9:    blue   white magenta    blue
#10:    blue   white magenta magenta
#11:    blue   white magenta   white
#12:    blue   white magenta magenta