Отправка значений в столбце списка в отдельные столбцы - PullRequest
5 голосов
/ 30 октября 2019

У меня есть data.table с list столбцом "c":

df <- data.table(a = 1:3, c = list(1L, 1:2, 1:3))
df
   a     c
1: 1     1
2: 2   1,2
3: 3 1,2,3

Я хочу создать отдельные столбцы для значений в "c".

Я создаюнабор новых столбцов F_1, F_2, F_3:

mmax <- max(df$a)
flux <- paste("F", 1:mmax, sep = "_")
df[, (flux) := 0]

df
   a     c F_1 F_2 F_3
1: 1     1   0   0   0
2: 2   1,2   0   0   0
3: 3 1,2,3   0   0   0

Я хочу отправить значения в "c" в столбцы F_1, F_2, F_3 следующим образом:

df

   a     c F_1 F_2 F_3
1: 1     1   1   0   0
2: 2   1,2   1   2   0
3: 3 1,2,3   1   2   3

Что япробовал:

comp_vect <- function(vec, mmax){
  vec   <- vec %>% unlist()
  n     <- length(vec)
  answr <- c(vec, rep(0, l = mmax -n)) 
}


df[ , ..flux := mapply(comp_vect, c, mmax)]

Ожидаемая таблица данных:

> df

   a     c F_1 F_2 F_3
1: 1     1   1   0   0
2: 2   1,2   1   2   0
3: 3 1,2,3   1   2   3

Ответы [ 2 ]

1 голос
/ 31 октября 2019

Я следовал радикально другому подходу. Я rbind редактировал столбец списка, а затем dcast редактировал его, получая желаемый результат. Последняя часть заключается в установке имен.

library(data.table)
df <- data.table(a = 1:3, d = list(1L, c(1L, 2L), c(1L, 2L, 3L)))

df2 <- df[, rbind(d), by = a][, dcast(.SD, a ~ V1, fill = 0)]

setnames(df2, 2:4, flux)[]
   a F_1 F_2 F_3
1: 1   1   0   0
2: 2   1   2   0
3: 3   1   2   3

, где flux - это переменная имен, которые вы определили в своем вопросе.

Обратите внимание, что следует избегать использования имени столбца c, как это можно спутать с функцией c().

1 голос
/ 31 октября 2019

Решение :

for(idx in seq(max(sapply(df$c, length)))){  # maximum number of values according to all the elements of the list
  set(x = df,
      i = NULL,
      j = paste0("F_",idx),  # column's name
      value = sapply(df$c, function(x){
        if(is.na(x[idx])){
          return(0)  # 0 instead of NA
        } else {
          return(x[idx])
        }
      })
  )
}

Объяснения :

Мы можем извлечь значения из списка следующим образом:

sapply(df$c, function(ll) return(ll[1])) # first value
[1] 1 1 1
sapply(df$c, function(ll) return(ll[2])) # second value
[1] NA  2  2
sapply(df$c, function(ll) return(ll[3])) # third value
[1] NA NA  3

Мы видим, что если значения нет, у нас есть NA.
Нам нужен итератор для извлечения всех значений в позиции idx. Для этого мы найдем количество значений в каждом элементе df$c (список) и сохраним максимум.

max(sapply(df$c, length))
[1] 3

Если нам нужны нули вместо NAs, нам нужно создатьфункция в sapply для их преобразования:

vec <- c(NA, 5, 1, NA)
> sapply(vec, function(x) if(is.na(x)) return(0) else return(x))
[1] 0 5 1 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...