You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何拆解含子DataFrame的复杂DataFrame并保留ResourceId

问题描述

我正在尝试拆解一个每行包含子DataFrame的复杂DataFrame。问题在于,各列中的子DataFrame尺寸不同(如1x3、2x3和2x2),且子DataFrame的Conversions.Value列存在数值与字符混合的数据格式,拆解时出现can't recycle input of size 3 to size 2.等报错。

DataFrame结构

structure(list
(Conversions = list(structure(list(Field = "Volume", 
    Unit = "m3", Value = 338L), class = "data.frame", row.names = 1L), 
    structure(list(Field = "Volume", Unit = "m3", Value = 450L), class = "data.frame", row.names = 1L)),     

Categories = list(structure(list(CategorySystem = c("Base", 
    NA), Title = c("Mineral materials and glass (excluding concrete)", "213.7 Kevytbetoni, Aerated concrete"), ClassificationType = c(NA, 
    "Talo2000")), class = "data.frame", row.names = 1:2), structure(list(
        CategorySystem = c("Base", NA), Title = c("Mineral materials and glass (excluding concrete)", 
        "213.7 Kevytbetoni, Aerated concrete"), ClassificationType = c(NA, 
        "Talo2000")), class = "data.frame", row.names = 1:2)), 
   
DataItems.DataValueItems = list(structure(list(DataModuleCode = c("A1-A3 Conservative",  "A1-A3 Typical"), Value = c(0.43, 0.36)), class = "data.frame", row.names = 1:2), 
        structure(list(DataModuleCode = c("A1-A3 Conservative", 
        "A1-A3 Typical"), Value = c(0.41, 0.34)), class = "data.frame", row.names = 1:2)), 
   
ResourceId = c(7000000995, 7000000996)), row.names = 1:2, class = "data.frame")

已尝试的方法及报错

  • 方法1:
unnest_wider(df, col = 1:3, names_repair = "universal") 
# 能运行但同一行仍有多个列表形式的观测,且长度不一致
  • 方法2:
unnest_longer(df, col = 1:3, names_repair = "universal") %>%
mutate(across(.fns = as.character)) %>%
  type_convert()
# 报错:Can't combine `..1$Conversions$Value` <integer> and `..6$Conversions$Value` <character>.
  • 方法3:
df$Conversions=lapply(df$Conversions, FUN=as.character)
unnest_longer(df, col = 1:3, names_repair = "universal") %>%
  mutate(across(.fns = as.character)) %>%
  type_convert()
# 报错:! In row 1, can't recycle input of size 3 to size 2.

补充:单独对各列使用rbindlist可合并,但会丢失唯一标识ResourceId,导致数据无法关联。需要为各列子DataFrame添加对应ResourceId后再合并。

解决方案

方法1:使用tidyverse工具链(dplyr + purrr)

核心思路是为每个子DataFrame绑定对应的ResourceId,再分别展开各列,最后按需合并:

  1. 处理Conversions列(统一Value类型避免冲突):
library(dplyr)
library(purrr)

conversions_df <- df %>%
  select(ResourceId, Conversions) %>%
  mutate(Conversions = map(Conversions, ~ .x %>% mutate(Value = as.character(Value)))) %>%
  unnest(Conversions)
  1. 处理Categories列:
categories_df <- df %>%
  select(ResourceId, Categories) %>%
  unnest(Categories)
  1. 处理DataItems.DataValueItems列(重命名Value避免冲突):
data_items_df <- df %>%
  select(ResourceId, DataItems.DataValueItems) %>%
  unnest(DataItems.DataValueItems) %>%
  rename(DataValue = Value)
  1. 按需合并(按ResourceId关联所有信息):
combined_df <- conversions_df %>%
  left_join(categories_df, by = "ResourceId") %>%
  left_join(data_items_df, by = "ResourceId")

方法2:使用data.table的rbindlist+map

利用map2将ResourceId和每个子DataFrame绑定,再用rbindlist合并:

library(data.table)

# 处理Conversions
conversions_dt <- rbindlist(map2(df$ResourceId, df$Conversions, ~ .y %>% 
                                  mutate(ResourceId = .x, Value = as.character(Value))))

# 处理Categories
categories_dt <- rbindlist(map2(df$ResourceId, df$Categories, ~ .y %>% mutate(ResourceId = .x)))

# 处理DataItems.DataValueItems
data_items_dt <- rbindlist(map2(df$ResourceId, df$DataItems.DataValueItems, ~ .y %>% 
                                  mutate(ResourceId = .x))) %>%
  setnames("Value", "DataValue")

# 合并数据集
final_dt <- conversions_dt[categories_dt, on = "ResourceId"][data_items_dt, on = "ResourceId"]

关键说明

  • 针对Conversions.Value的类型混合问题,提前转为字符型(后续可按需转换为合适类型),避免合并时的类型冲突。
  • 通过绑定ResourceId到每个子DataFrame,确保拆分后的数据集保留唯一标识,解决数据关联问题。
  • 分列拆分再合并的方式,规避了不同尺寸子DataFrame直接unnest时的回收错误。

内容的提问来源于stack exchange,提问作者schlindd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:10:25