如何基于条件将DataFrame转换为含子列表的嵌套列表(R语言)
通用实现DataFrame转指定嵌套列表的方法
问题背景
我正在做网页抓取项目,已经获取到目标数据,但无法转换成期望的嵌套列表格式。
示例输入数据
search_result <- structure(list(preferred_name = c("CHICAGO NORTHERLY ISLAND, IL", "CHICAGO MIDWAY AP, IL"), lat = c(41.8558, 41.78412), lng = c(-87.6094, -87.75514), distance = c(7.89027840950889, 17.4390740815157), GHCNMLT = c("USC00111550", "USW00014819"), WMO = c(NA, "72534014819" )), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame" ))
search_result包含站点名称、纬度、经度、距离及两种站点ID(GHCNMLT、WMO)。
转换规则
需要将该DataFrame转换为嵌套列表,保留站点名称、纬度、经度、距离,并按以下规则生成子列表:
- 所有站点需生成对应GHCNMLT ID的
valid_args_1子列表,包含ID、固定数据集和数据类型; - 若站点存在WMO ID(非NA),需额外生成
valid_args_2子列表,包含ID、固定数据集和数据类型。
固定数据集与数据类型定义
GHCNMLT <- list( datasets = c("daily-summaries", "global-summary-of-the-month", "global-summary-of-the-year"), data_types = c("TMAX", "TMIN", "TAVG") ) WMO <- list( datasets = c("local-climatological-data", "global-hourly"), data_types = c("HourlyDryBulbTemperature", "HourlyRelativeHumitidy") )
期望输出结构
out <- list( # search_result第一行对应station_1 station_1 = list( name = "CHICAGO NORTHERLY ISLAND, IL", lat = 41.9, lng = -87.8, distance = 7.89, valid_args_1 = list( ID_1 = "USC00111550", datasets = c("daily-summaries", "global-summary-of-the-month", "global-summary-of-the-year"), data_types = c("TMAX", "TMIN", "TAVG") ) ), # search_result第二行对应station_2 station_2 = list( name = "CHICAGO MIDWAY AP, IL", lat = 41.9, lng = -87.8, distance = 17.4, valid_args_1 = list( ID_1 = "USW00014819", datasets = c("daily-summaries", "global-summary-of-the-month", "global-summary-of-the-year"), data_types = c("TMAX", "TMIN", "TAVG") ), # 仅当WMO ID存在时添加valid_args_2 valid_args_2 = list( ID_2 = "72534014819", datasets = c("local-climatological-data", "global-hourly"), data_types = c("HourlyDryBulbTemperature", "HourlyRelativeHumitidy") ) ) )
请问当站点数量多于2个时,是否有通用的实现方法?
解决方案
可以通过purrr包的map函数遍历DataFrame的每一行,逐行构建嵌套列表,同时处理WMO ID的条件判断,实现通用化转换:
library(purrr) # 定义转换函数,处理单行数据 convert_row <- function(row) { # 基础信息列表 station_list <- list( name = row$preferred_name, lat = round(row$lat, 1), # 按示例保留一位小数 lng = round(row$lng, 1), distance = round(row$distance, 2) ) # 添加valid_args_1 station_list$valid_args_1 <- list( ID_1 = row$GHCNMLT, datasets = GHCNMLT$datasets, data_types = GHCNMLT$data_types ) # 若WMO ID存在,添加valid_args_2 if (!is.na(row$WMO)) { station_list$valid_args_2 <- list( ID_2 = row$WMO, datasets = WMO$datasets, data_types = WMO$data_types ) } return(station_list) } # 遍历所有行,生成站点列表 station_list <- map(1:nrow(search_result), function(i) { convert_row(search_result[i, ]) }) # 为列表元素命名(station_1、station_2...) names(station_list) <- paste0("station_", 1:length(station_list)) # 查看结果 station_list
代码说明
- convert_row函数:接收单行数据,先构建包含基础信息的列表,再添加必填的
valid_args_1,最后根据WMO ID是否存在决定是否添加valid_args_2; - map遍历:使用
map函数遍历DataFrame的每一行,对每行应用convert_row函数; - 命名列表元素:通过
paste0生成station_1、station_2这类命名,确保输出结构与期望一致; - 小数处理:按示例对经纬度保留1位小数,距离保留2位小数,若不需要可去掉
round函数。
这种方法不受站点数量限制,无论有多少个站点都能自动处理。
内容的提问来源于stack exchange,提问作者nightstand
相关产品推荐
相关产品推荐

