使用R循环读取CSV文件并填充目标DataFrame的技术求助
R语言数据处理需求与代码优化求助
需求说明
- 循环读取指定目录下的90个CSV文件;
- 对每个CSV文件执行两个计算:
- Einsatzaufkommen:计算
E_NR列的唯一值数量; - Einsatzfahrtaufkommen:计算
E_NR列的总行数;
- Einsatzaufkommen:计算
- 将上述两个计算结果,通过匹配ID(目标DataFrame的
ID列与CSV文件的ERHEBUNGSSTELLE列),填充到bast_ansprechpartner_erhebungsstellen这个DataFrame对应的Einsatzaufkommen和Einsatzfahrtaufkommen列,最终填满90行的这两列。
现有代码
# This is the dataframe where i want to add all the values(in columns "Einsatzfahrt" and "Einsatzaufkommen") bast_ansprechpartner_erhebungsstellen <- read_csv2("/Users/pablotrutnau/aktenschrank/Datenbericht/BASt/212-744 Einzelberichte - Beispielordner/BAST_Leistungsanalyse-Ansprechpartner_Erhebungsstellen.csv", col_types = "c") # directory of all the 90 csv files verzeichnis <- "/Users/pablotrutnau/aktenschrank/Datenbericht/BASt/212-744 Einzelberichte - Beispielordner/Einsatzdaten" # All csv files in the directory datensätze <- list.files(path = verzeichnis, pattern = ".csv", full.names = TRUE) # start of loop for (daten in datensätze){ # Reading the csv files datensatz <- read_csv2(daten, col_types = "c") # "datensatz" is being renamed to "daten_gefiltert" after applying a function that filters some data of "datensatz" # Einsatz- und Einsatzfahrtaufkommen ###################################### # Function that adds value to bast_ansprechpartner_erhebungsstellen(to column Einsatzaufkommen) einsatzaufkommen <- function(){ einsätze = round(length(unique(daten_gefiltert$E_NR)), digits = 0) # Matches between the IDs join_id <- match(bast_ansprechpartner_erhebungsstellen$ID, daten_gefiltert$ERHEBUNGSSTELLE) # Value is being added to bast_ansprechpartner_erhebungsstellen at the row where the id matches bast_ansprechpartner_erhebungsstellen$Einsatzaufkommen <- ifelse(!is.na(join_id), einsätze, NA) return(bast_ansprechpartner_erhebungsstellen) } # Function that adds value to dbast_ansprechpartner_erhebungsstellen(to column Einsatzfahrtaufkommen) einsatzfahrtaufkommen <- function(){ fahrten = length(daten_gefiltert$E_NR) # Matches between the IDs join_id <- match(bast_ansprechpartner_erhebungsstellen$ID, daten_gefiltert$ERHEBUNGSSTELLE) # Value is being added to bast_ansprechpartner_erhebungsstellen at the row where the id matches bast_ansprechpartner_erhebungsstellen$Einsatzfahrtaufkommen <- ifelse(!is.na(join_id), fahrten, NA) return(bast_ansprechpartner_erhebungsstellen) } # values are being added to bast_ansprechpartner_erhebungsstellen bast_ansprechpartner_erhebungsstellen <- einsatzaufkommen() bast_ansprechpartner_erhebungsstellen <- einsatzfahrtaufkommen() }
原代码存在的问题
- 函数定义放在循环内部,每次循环都会重复定义,完全没必要,还会降低运行效率;
match逻辑错误:match(bast_ansprechpartner_erhebungsstellen$ID, daten_gefiltert$ERHEBUNGSSTELLE)会把所有匹配到的行设置为当前文件的计算值,后续文件会覆盖之前的结果,最终只有最后一个文件的数据被保留;- 未处理
daten_gefiltert的定义(仅注释提及); - 直接覆盖整个列的方式容易导致数据丢失,不符合“填满90行”的需求。
优化后的代码
# 读取目标DataFrame bast_ansprechpartner_erhebungsstellen <- read_csv2( "/Users/pablotrutnau/aktenschrank/Datenbericht/BASt/212-744 Einzelberichte - Beispielordner/BAST_Leistungsanalyse-Ansprechpartner_Erhebungsstellen.csv", col_types = "c" ) # 初始化需要填充的列 bast_ansprechpartner_erhebungsstellen$Einsatzaufkommen <- NA_integer_ bast_ansprechpartner_erhebungsstellen$Einsatzfahrtaufkommen <- NA_integer_ # 定义文件目录 verzeichnis <- "/Users/pablotrutnau/aktenschrank/Datenbericht/BASt/212-744 Einzelberichte - Beispielordner/Einsatzdaten" datensätze <- list.files(path = verzeichnis, pattern = ".csv", full.names = TRUE) # 处理每个CSV文件 for (daten in datensätze) { # 读取文件 datensatz <- read_csv2(daten, col_types = "c") # 替换为你的实际过滤逻辑 daten_gefiltert <- datensatz # 示例:暂时直接使用原数据,需替换为你的过滤代码 # 获取当前文件对应的唯一ERHEBUNGSSTELLE(假设每个文件对应一个ID) current_id <- unique(daten_gefiltert$ERHEBUNGSSTELLE) if (length(current_id) != 1) { warning(paste("文件", daten, "包含多个ERHEBUNGSSTELLE值,跳过处理")) next } # 计算两个指标 einsatz_count <- length(unique(daten_gefiltert$E_NR)) fahrt_count <- nrow(daten_gefiltert) # 用nrow更准确,避免E_NR列有NA时length()的误差 # 定位目标DataFrame中匹配的行 target_row <- which(bast_ansprechpartner_erhebungsstellen$ID == current_id) # 填充对应列 if (length(target_row) > 0) { bast_ansprechpartner_erhebungsstellen$Einsatzaufkommen[target_row] <- einsatz_count bast_ansprechpartner_erhebungsstellen$Einsatzfahrtaufkommen[target_row] <- fahrt_count } else { warning(paste("文件", daten, "的ERHEBUNGSSTELLE", current_id, "在目标DataFrame中未找到匹配ID")) } }
优化说明
- 移除循环内的函数定义,直接在循环中计算指标,简化逻辑;
- 假设每个CSV文件对应唯一的
ERHEBUNGSSTELLE(匹配90个文件对应90行的需求),精准定位目标行填充,避免覆盖其他行的数据; - 使用
nrow()计算总行数,比length(E_NR)更可靠(当E_NR列存在NA时,length会把NA算入,而nrow统计的是有效行数); - 添加警告提示,便于排查异常文件(比如一个文件对应多个ID、ID未匹配的情况);
- 提前初始化目标列,逻辑更清晰,避免出现列不存在的错误。
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

