You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用R循环读取CSV文件并填充目标DataFrame的技术求助

R语言数据处理需求与代码优化求助

需求说明

  • 循环读取指定目录下的90个CSV文件;
  • 对每个CSV文件执行两个计算:
    • Einsatzaufkommen:计算E_NR列的唯一值数量;
    • Einsatzfahrtaufkommen:计算E_NR列的总行数;
  • 将上述两个计算结果,通过匹配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()
}

原代码存在的问题

  1. 函数定义放在循环内部,每次循环都会重复定义,完全没必要,还会降低运行效率;
  2. match逻辑错误:match(bast_ansprechpartner_erhebungsstellen$ID, daten_gefiltert$ERHEBUNGSSTELLE)会把所有匹配到的行设置为当前文件的计算值,后续文件会覆盖之前的结果,最终只有最后一个文件的数据被保留;
  3. 未处理daten_gefiltert的定义(仅注释提及);
  4. 直接覆盖整个列的方式容易导致数据丢失,不符合“填满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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:14:56