如何对tibble每行与嵌套数据框列表执行自定义函数
解决方案
我们可以通过映射函数来处理这种嵌套结构的对应计算需求,以下是具体实现方式:
核心逻辑
source的第i行,需要匹配dest[[1]][[i]]和dest[[2]][[i]]两个数据框,再对这两个数据框的每一行,与source的第i行共同传入目标函数。
示例实现(以计算两点欧氏距离为例)
1. 定义目标函数
先写一个示例函数,用来计算两组经纬度点之间的欧氏距离:
calc_distance <- function(source_point, dest_point) { sqrt((source_point$lon - dest_point$lon)^2 + (source_point$lat - dest_point$lat)^2) }
2. 用tidyverse工具实现(推荐)
借助purrr的映射函数和dplyr的行处理能力,代码更简洁易读:
library(purrr) library(dplyr) # 遍历source的每一行,同时获取行索引i result <- imap(source, function(source_row, i) { # 取出dest中对应i的两个数据框 target_dfs <- list(dest[[1]][[i]], dest[[2]][[i]]) # 对每个数据框的每一行应用计算函数 map(target_dfs, ~ rowwise(.x) %>% mutate(distance = calc_distance(source_row, cur_data())) %>% ungroup()) })
3. 基础R实现(无依赖)
如果不想使用tidyverse包,用基础R的lapply和apply也能实现:
result <- lapply(1:nrow(source), function(i) { current_row <- source[i, ] target_dfs <- list(dest[[1]][[i]], dest[[2]][[i]]) lapply(target_dfs, function(df) { apply(df, 1, function(dest_row) { sqrt((current_row$lon - dest_row[1])^2 + (current_row$lat - dest_row[2])^2) }) }) })
结果说明
- 最终的
result是一个长度为6的列表(对应source的6行) - 每个子列表包含两个元素,分别是
dest[[1]][[i]]和dest[[2]][[i]]处理后的结果(如果是数据框版本,会新增计算列;如果是基础版,会返回每行的计算值向量)
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

