使用dplyr为data.frame新增列时读取CSV行数报错问题排查
问题分析与解决
问题场景
现有一个包含植物拉丁名的data.frame,同时有存储GBIF下载数据的GBIF_data文件夹,其中CSV文件以替换空格为下划线的植物拉丁名命名。已通过字符串操作生成CSVPATH列(示例路径如../GBIF_data/Lycopodium_cernuum.csv),尝试用dplyr::mutate新增OCCURRENCES列,存储对应CSV文件的行数,代码如下:
read.csv("data.csv") %>% mutate(OCCURRENCES = nrow(read.delim(CSVPATH))) # GBIF的CSV用制表符分隔,所以用read.delim
运行时报错:
Error in `mutate()`: ! Problem while computing `OCCURRENCES = nrow(read.delim(CSVPATH))`. Caused by error in `h()`: ! error in evaluating the argument 'x' in selecting a method for function 'nrow': invalid 'description' argument
失效原因
dplyr::mutate是向量化操作,会把整个CSVPATH列(字符向量)直接传给read.delim,但read.delim本身不支持接收向量格式的文件路径——它只期望单个字符串路径,传入向量会导致函数无法正确解析,进而让nrow接收到无效参数,最终触发报错。
解决方案
有两种常用的修复方式:
方式1:用rowwise()逐行处理
通过rowwise()让mutate对每一行单独执行文件读取逻辑,确保每次read.delim只接收单个路径:
library(dplyr) read.csv("data.csv") %>% rowwise() %>% mutate(OCCURRENCES = nrow(read.delim(CSVPATH, stringsAsFactors = FALSE))) %>% ungroup() # 处理完记得取消逐行模式,避免后续操作性能问题
方式2:用purrr::map_int向量化处理
借助purrr包的map_int函数,对CSVPATH向量中的每个路径单独计算行数,返回整数向量直接赋值给新列:
library(dplyr) library(purrr) read.csv("data.csv") %>% mutate(OCCURRENCES = map_int(CSVPATH, ~nrow(read.delim(.x, stringsAsFactors = FALSE))))
优化建议
如果CSV文件较大,读取整个文件只为获取行数会很耗时,可以用更高效的方式统计行数(无需加载整个文件):
# 自定义高效统计行数的函数 count_lines <- function(path) { con <- file(path, "r") on.exit(close(con)) # GBIF CSV通常第一行是表头,所以统计行数后减1 length(readLines(con)) - 1 } # 结合map_int使用 read.csv("data.csv") %>% mutate(OCCURRENCES = map_int(CSVPATH, count_lines))
内容的提问来源于stack exchange,提问作者passiflora
相关产品推荐
相关产品推荐

