使用dplyr导入多个CSV至tibble并添加文件名字段的问题
用dplyr合并多个CSV文件并添加文件名的正确方案
问题根源
你原来的循环方法出错,是因为每次bind_rows后用row_number()判断行范围的逻辑不成立:
- 当i=2时,bind后tmp变成6行,你用
row_number()>3 & <=6给第4-6行(file02的内容)设置了正确的文件名; - 但i=3时,bind后tmp变成9行,第一个
mutate的条件row_number()>3 & <=6会选中第4-6行(原本是file02的内容),把它们的Fnm改成了file03.txt,这就覆盖了之前的正确值,导致最终file02的行都变成了file03的文件名。
而且这种依赖固定行数的判断非常脆弱——只要某个文件的行数不是3,整个逻辑就彻底失效。
正确的dplyr解决方案
方法1:用purrr::map_dfr(推荐,tidyverse标准写法)
map_dfr会遍历文件名向量,对每个文件执行读取+添加文件名的操作,最后自动合并成一个tibble,完全不需要手动循环:
library(tidyverse) # 加载dplyr和purrr Fnms <- c("file01.txt", "file02.txt", "file03.txt") combined_data <- map_dfr(Fnms, function(file) { read_csv(file) %>% mutate(Fnm = file) # 给当前文件的数据添加文件名 })
或者用更简洁的公式写法:
combined_data <- map_dfr(Fnms, ~ read_csv(.x) %>% mutate(Fnm = .x))
方法2:用for循环配合dplyr(如果一定要用循环)
核心思路是先给单个文件的数据加好文件名,再合并,而不是先合并再修改:
library(dplyr) library(readr) Fnms <- c("file01.txt", "file02.txt", "file03.txt") # 初始化空的tibble tmp <- tibble() for (file in Fnms) { # 读取当前文件,添加文件名 current_df <- read_csv(file) %>% mutate(Fnm = file) # 合并到tmp中 tmp <- tmp %>% bind_rows(current_df) }
这样每个文件的Fnm列在读取时就已经正确设置,不会出现覆盖错误。
最终效果
两种方法都会得到正确的结果:
# A tibble: 9 × 3 F1 F2 Fnm <chr> <dbl> <chr> 1 A 1 file01.txt 2 B 2 file01.txt 3 C 3 file01.txt 4 D 4 file02.txt 5 E 5 file02.txt 6 F 6 file02.txt 7 H 7 file03.txt 8 I 8 file03.txt 9 J 9 file03.txt
内容的提问来源于stack exchange,提问作者Markm0705
相关产品推荐
相关产品推荐

