如何展开含列表值的DataFrame?列表值转多行不足补NA
如何展开DataFrame中列表类型的列,长度不一致时用NA填充
问题场景
需要将DataFrame内部分为列表类型的列展开,把每个列表元素转为独立行;当不同列的列表长度不一致时,不足的位置用NA填充。示例数据如下:
dat <- data.frame(matrix(ncol = 4, nrow = 2)) colnames(dat)[1:4] <- c("Date","value1","value2","value3") dat$Date <- c(as.Date('1968-06-13'), as.Date('1968-09-17')) dat$value1 <- c(list(c(79,78)),list(c(55,56,57))) dat$value2 <- c(list(c(7.3,7.2)),list(c(6.6,6.7))) dat$value3 <- c(0.27,0.55)
直接使用unnest()会触发错误:
library(tidyverse) dat %>% unnest(cols = c(value1,value2,value3)) # Error in `unnest()`: ! In row 2, can't recycle input of size 3 to size 2.
原因是同一行内不同列的列表长度不匹配(如第二行value1长度为3,value2长度为2),unnest()要求同一行的各列列表长度一致才能直接展开。
ChatGPT提供的代码因参数适配问题报错(旧版本tidyr中unnest_wider的参数格式不同),无法得到预期结果。
理想输出:
Date value1 value2 value3 1 1968-06-13 79 7.3 0.27 2 1968-06-13 78 7.2 NA 3 1968-09-17 55 6.6 0.55 4 1968-09-17 56 6.7 NA 5 1968-09-17 57 NA NA
解决方案
方法1:按行处理自动补NA
利用tibble()组合不同长度向量时自动补NA的特性,按行生成小数据集后展开:
library(tidyverse) dat %>% rowwise() %>% # 将当前行的value列转为tibble,自动补NA到最长列表长度 mutate(expanded_data = list(tibble(value1 = value1, value2 = value2, value3 = value3))) %>% unnest(expanded_data) %>% # 移除原列表列,保留目标列 select(Date, value1, value2, value3)
方法2:统一格式后重新整理宽表
先将非列表列转为列表格式,再通过索引重新组织数据:
library(tidyverse) dat %>% # 将单个值转为长度1的列表,统一所有列格式 mutate(value3 = as.list(value3)) %>% # 展开所有value列,记录元素的行内索引 unnest_longer(cols = starts_with("value"), indices_to = "element_idx") %>% # 按索引重新转为宽表 pivot_wider( names_from = element_idx, values_from = starts_with("value"), names_glue = "{.name}_{.value}" ) %>% # 展开所有列得到目标格式 unnest(cols = starts_with("value"), names_sep = "") %>% select(Date, value1, value2, value3)
说明
- 方法1逻辑直观,适合大多数场景,利用
tibble的自动补NA特性简化处理。 - 方法2通过索引追踪元素位置,适合需要保留元素原始顺序信息的场景。
内容的提问来源于stack exchange,提问作者tassones
相关产品推荐
相关产品推荐

