【问题标题】:Convert a column of lists into a column of vector将一列列表转换为一列向量
【发布时间】:2021-02-24 23:15:51
【问题描述】:

我有一个data.table,由于某种原因有几列list。我需要找到一种快速方法将这些列转换为具有integer 值的常规向量列。

请参阅下面的可重现示例和我的尝试。

代表

dt = structure(list(fromId = c("89a901291abffff", "89a901295b7ffff", 
      "89a9012809bffff", "89a901285cfffff"), travel_time_p001 = c(45L, 
      43L, 38L, 27L), travel_time_p050 = list(54L, 52L, 44L, 35L), 
      travel_time_p098 = list(62L, 60L, 55L, 44L)), row.names = c(NA, 
      -4L), class = c("data.table", "data.frame"))


head(dt)
>             fromId travel_time_p001 travel_time_p050 travel_time_p098
> 1: 89a901291abffff               45               54               62
> 2: 89a901295b7ffff               43               52               60
> 3: 89a9012809bffff               38               44               55
> 4: 89a901285cfffff               27               35               44

sapply(dt, class)
>     fromId travel_time_p001 travel_time_p050 travel_time_p098 
>"character"        "integer"           "list"           "list" 

class(dt$travel_time_p098[1])
> [1] "list"

我发现这种方法可以修复单个列,但我不确定这是否可以更快地完成。

dt[, travel_time_p098 := Reduce(rbind, travel_time_p098)]

现在,当我尝试为多个列执行此操作时,挑战变得更加困难。这是我尝试过但没有成功的方法。我希望有人能想出一个快速的解决方案,或许可以使用data.table 循环和set()


# identify which columns need to be transformed.
colpositions <- sapply(dt, class) == 'list'
colnms <- names(dt)[colpositions]

# failed attempt
dt[, colnms := Reduce(rbind, .SD), .SDcols = colnms]

有什么建议吗?

【问题讨论】:

    标签: r list dataframe data.table


    【解决方案1】:

    如果list 元素的长度与行数相同,则可以选择循环遍历所有列,使用if/elseunlist 进行检查

    dt1 <- dt[,  lapply(.SD, function(x) if(is.list(x)) unlist(x) else x)]
    str(dt1)
    #Classes ‘data.table’ and 'data.frame': 4 obs. of  4 variables:
    # $ fromId          : chr  "89a901291abffff" "89a901295b7ffff" "89a9012809bffff" "89a901285cfffff"
    # $ travel_time_p001: int  45 43 38 27
    # $ travel_time_p050: int  54 52 44 35
    # $ travel_time_p098: int  62 60 55 44
    

    或者没有任何检查

    dt[, lapply(.SD, unlist)] 
    

    如果我们需要使用set

    for(j1 in seq_along(dt)) {
         cl1 <- class(dt[[j1]])
         if(cl1 == 'list') {
              set(dt, i = NULL, j = j1, value = unlist(dt[[j1]]))
            }
      }
       
    
    str(dt)
    #Classes ‘data.table’ and 'data.frame': 4 obs. of  4 variables:
    # $ fromId          : chr  "89a901291abffff" "89a901295b7ffff" "89a9012809bffff" "89a901285cfffff"
    # $ travel_time_p001: int  45 43 38 27
    # $ travel_time_p050: int  54 52 44 35
    # $ travel_time_p098: int  62 60 55 44
    

    【讨论】:

    • 这个使用set循环的解决方案效果很好。谢谢
    猜你喜欢
    • 1970-01-01
    • 2011-07-07
    • 2016-04-10
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    相关资源
    最近更新 更多