如何将不等长向量列表转换为长格式dataframe且无需填充NA?
问题描述
现有一个向量列表a,所有向量均为Date类型,但长度各不相同:
> str(a) List of 2 $ item1: Date[1:3], format: "1999-02-06" "1999-10-23" "1999-09-13" $ item2: Date[1:2], format: "1999-12-05" "1999-11-30"
需要将其转换为如下长格式DataFrame结构:
| items | dates |
|---|---|
| item1 | 1999-02-06 |
| item1 | 1999-10-23 |
| item1 | 1999-09-13 |
| item2 | 1999-12-05 |
| item2 | 1999-11-30 |
生成列表a的代码:
a <- list(item1 = structure(c(10628, 10887, 10847), class = "Date"), item2 = structure(c(10930, 10925), class = "Date"), item3 = structure(c(10764, 10671, 10917, 10887), class = "Date"))
常规行/列绑定方法无法实现:
> bind_rows(a) Error: ! Tibble columns must have compatible sizes. • Size 2: Column `item2`. • Size 3: Column `item1`. ℹ Only values of size one are recycled. > bind_cols(a) Error in `bind_cols()`: ! Can't recycle `item1` (size 3) to match `item2` (size 2).
已查找相关方案,但现有方法需要先填充NA再使用pivot_longer(),希望找到无需填充NA的更优方法。
解决方案
方法1:tidyverse 工具链(enframe + unnest)
直接通过tibble和tidyr的组合转换,无需填充NA:
library(tidyverse) a %>% enframe(name = "items", value = "dates") %>% unnest(dates)
enframe将列表名称转为items列,向量内容转为嵌套的dates列,unnest直接展开嵌套的Date向量,一步得到目标结构。
方法2:Base R 的 stack() 函数
用原生函数快速转换,仅需恢复Date类型:
result <- stack(a) colnames(result) <- c("dates", "items") # 恢复Date类 result$dates <- as.Date(result$dates, origin = "1970-01-01") # 调整列顺序为需求格式 result <- result[, c("items", "dates")]
stack默认生成values和ind列,重命名后将数值转回Date类型即可。
方法3:data.table 的 rbindlist()
借助data.table的高效合并能力实现:
library(data.table) rbindlist(lapply(a, as.data.table), idcol = "items") %>% setnames(".", "dates")
先将每个列表元素转为data.table,rbindlist合并时通过idcol参数生成items列,最后重命名日期列即可。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

