在R中通过循环自动选列并批量计算存至三维数组的问题
解决R语言循环选取列并写入三维数组的问题
我来帮你梳理下当前遇到的问题,并给出完整的解决方案:
问题分析
你当前的核心问题有两个:
- 列选取的逻辑错误:手动计算列位置(
seq(from=5, to=7984,by=20))容易出错,且动态生成变量名(paste0("maille",j-4)=select(...))不是R的正确赋值方式; - 数组索引写入错误:使用
[[i-1958,,]]的索引方式不符合三维数组的访问规则,应该明确指定[行, 列, 地点]的位置。
完整解决方案代码
首先确保你加载了必要的包:
library(dplyr) library(stringr)
1. 预处理列名,按地点分组
先把所有气候变量列按地点后缀分组,这样能精准获取每个地点对应的20列:
# 提取所有气候变量列(排除前4列日期相关列) climate_cols <- colnames(donnees_SAFRAN)[-c(1:4)] # 从列名中提取地点编号(匹配`.数字`格式的后缀) site_ids <- str_extract(climate_cols, "\\.(\\d+)$") %>% str_remove("\\.") %>% as.integer() # 按地点编号分组列名,得到每个地点对应的20个气候列 site_col_list <- split(climate_cols, site_ids)
2. 初始化三维数组(你的原代码没问题,保留)
Indice_clim <- array(NA, dim = c(60, 8, 399), dimnames = list(c(1959:2018), c("Huglin","CNI","HD","VHD","SHS","DoF","FreqLF","SLF"), c(1:399)))
3. 循环处理每个地点,计算并写入数组
# 遍历所有399个地点 for (site in 1:399) { # 选取当前地点的所有列:前4列日期 + 当前地点的20个气候列 current_cols <- c(colnames(donnees_SAFRAN)[1:4], site_col_list[[as.character(site)]]) maille <- donnees_SAFRAN %>% select(all_of(current_cols)) # 遍历每个年份计算8个气候指标 for (year in 1959:2018) { # 计算Huglin指数 huglin <- maille %>% filter(an == year, mois %in% 4:9) %>% # 简化月份判断 summarise(val = sum(((T_moy.1 - 10) + (T_max.1 - 10))/2 * 1.03)) %>% pull(val) # 直接提取数值 # 计算CNI cni <- maille %>% filter(an == year, mois == 9) %>% summarise(val = mean(T_min.1)) %>% pull(val) # 计算HD hd <- maille %>% filter(an == year) %>% summarise(val = sum(T_max.1 >= 30)) %>% pull(val) # 计算VHD vhd <- maille %>% filter(an == year) %>% summarise(val = sum(T_max.1 >= 35)) %>% pull(val) # 计算SHS shs <- maille %>% filter(an == year, mois %in% 4:9, T_moy.1 >= 28) %>% summarise(val = sum(T_moy.1 - 28)) %>% pull(val) # 计算DoF dof <- maille %>% filter(an == year) %>% summarise(val = sum(T_min.1 <= 0)) %>% pull(val) # 计算FreqLF freqlf <- maille %>% filter(an == year, mois %in% 4:9) %>% summarise(val = sum(T_min.1 <= 0)) %>% pull(val) # 计算SLF slf <- maille %>% filter(an == year, mois %in% 4:9, T_moy.1 < 2) %>% summarise(val = sum(abs(2 - T_moy.1))) %>% pull(val) # 将结果写入三维数组:年份索引=year-1958,指标顺序对应列名,地点=site Indice_clim[year - 1958, , site] <- c(huglin, cni, hd, vhd, shs, dof, freqlf, slf) } }
关键说明
- 列选取的可靠性:通过
stringr提取列名中的地点编号并分组,避免了手动计算列位置的错误,即使列顺序变化也能正确匹配; - 变量赋值规范:不再使用动态生成变量名的方式,直接在循环内处理当前地点的数据,节省内存且逻辑清晰;
- 数组索引正确性:明确使用
[年份索引, 指标列, 地点]的三维索引方式,确保结果写入正确的位置; - 代码简化:用
mois %in% 4:9代替多个mois==的判断,让代码更简洁易读;用pull(val)直接提取计算结果的数值,避免返回数据框导致的类型错误。
内容的提问来源于stack exchange,提问作者mayp
相关产品推荐
相关产品推荐

