按组将DataFrame行转为嵌套列表元素,寻求更简便实现方法
更简洁的DataFrame分组嵌套列表生成方法
嘿,我完全懂你想要的效果——按id分组后,每个id对应一个列表,里面的每个key又对应着它的子列表值对吧?嵌套lapply加split确实有点绕,这里有几个更直接清爽的实现方式,覆盖不同的R工具链,你可以按需选:
1. 使用tidyverse(dplyr + purrr)
这是最符合直觉的写法,用分组嵌套+映射拆分的组合,代码可读性拉满:
library(dplyr) library(purrr) # 假设你的数据框是df,包含id、key、value三列 result <- df %>% group_by(id) %>% # 先按id把数据嵌套起来 nest() %>% # 对每个嵌套的子数据框,按key拆分value列 mutate(data = map(data, ~ split(.$value, .$key))) %>% # 把结果转换成以id为名称的列表 deframe()
最终result就是你要的结构:每个元素是对应id的列表,列表里的每个key对应着它的所有值组成的子列表。
2. 使用data.table(适合大数据场景)
如果你的数据量很大,data.table的速度优势会很明显,写法也相当紧凑:
library(data.table) setDT(df) # 简洁版写法 result <- df[, split(value, key), by = id] %>% split(by = "id", keep.by = FALSE) %>% lapply(function(x) setNames(x$V1, x$key))
或者更直白的分步写法:
# 先按id分组,每个组内按key拆分value temp <- df[, .(key_list = list(split(value, key))), by = id] # 提取结果并设置名称 result <- temp$key_list names(result) <- temp$id
3. Base R简化写法
不用额外装包,用tapply替代嵌套lapply,代码更简洁:
result <- tapply(seq_len(nrow(df)), df$id, function(idx) { sub_df <- df[idx, ] split(sub_df$value, sub_df$key) })
tapply会自动按id分组处理每行的索引,每个组内直接拆分对应的值,一步到位。
这些方法都能达到和你现有实现一样的效果,但代码更简洁易读,维护起来也更方便~
内容的提问来源于stack exchange,提问作者Julien Navarre
相关产品推荐
相关产品推荐

