如何在R中缓存需用户输入的向量化调用?以taxize包查询为例
嘿,这个需求我太有共鸣了!处理大型生物分类数据集的时候,反复手动选择匹配结果真的能把人折腾疯,给用户选择加个缓存绝对是提升效率的核心。我给你分享两个实用的方案,你可以根据需求选:
方案1:用
memoise快速实现缓存(简单省心) memoise包是R里做函数结果缓存的神器,它能自动帮你记住函数的输入和对应的输出,完全不用自己写复杂的缓存逻辑。
比如你用taxize里的get_tsn(或者其他类似的查询函数),只需要简单包装一下就行:
library(taxize) library(memoise) # 创建一个基于文件系统的缓存(重启R也不会丢失缓存内容) taxon_cache <- cache_filesystem("~/taxon_id_cache") # 包装查询函数,加上缓存功能 get_tsn_cached <- memoise(get_tsn, cache = taxon_cache)
之后你调用get_tsn_cached("Quercus robur")的时候,第一次遇到多结果会让你手动选择,选择后的结果会被存在本地的taxon_id_cache文件夹里。下次再查同一个学名,直接从缓存里取结果,完全不用再重复选择了!
方案2:自定义缓存机制(更灵活可控)
如果memoise的默认逻辑满足不了你的需求(比如要自定义缓存的存储格式、或者要和其他工作流程联动),自己写一个缓存函数也很简单,比如用JSON文件来持久化缓存:
library(taxize) library(jsonlite) # 定义缓存文件的存储路径 cache_path <- "taxon_id_cache.json" # 初始化缓存文件(如果不存在就创建一个空列表) if (!file.exists(cache_path)) { write_json(list(), cache_path) } # 自定义带缓存的查询函数 get_cached_taxon_id <- function(scientific_name) { # 读取现有的缓存内容 current_cache <- read_json(cache_path) # 检查缓存里有没有这个学名的结果 if (scientific_name %in% names(current_cache)) { message(glue::glue("✅ 从缓存加载 {scientific_name} 的ID")) return(current_cache[[scientific_name]]) } # 缓存里没有结果,调用taxize查询并让用户选择 message(glue::glue("🔍 首次查询 {scientific_name},请选择匹配结果")) selected_id <- get_tsn(scientific_name, ask = TRUE) # 把新选择的结果存入缓存 current_cache[[scientific_name]] <- selected_id write_json(current_cache, cache_path, auto_unbox = TRUE) return(selected_id) }
这个函数的逻辑很清晰:每次先查缓存文件,有结果直接返回;没有的话就调用taxize的查询函数,让用户选择后把结果存进缓存,下次再查就不用重复操作了。
一些小提示
- 不管用哪种方案,都要确保taxize查询函数的
ask参数设为TRUE,这样多结果时才会触发用户选择 - 如果需要更新某个学名的缓存,直接删除对应的缓存条目(或者整个缓存文件/文件夹)就行
- 处理大型数据集时,用
lapply或者purrr::map批量调用缓存函数即可,第一次遇到新学名会暂停让你选,之后全程自动运行
内容的提问来源于stack exchange,提问作者choff
相关产品推荐
相关产品推荐

