R语言:如何通过for循环自动合并目标字符列表?
问题:R语言中用for循环结合
c()生成字符向量失败,cols始终为NULL 问题背景
尝试通过c()嵌套for循环生成目标字符向量,控制台能打印出正确内容,但最终cols变量始终为NULL,无法保存生成的结果。
原代码
cols <- c( for(j in periods) { if(is.na(df[grep(j, df$Period),]$Scenario[[1]])) { print(j, collapse = ",") } else { for (k in ssp) { print(paste(j, k, sep="_", collapse = ",")) } } } )
控制台输出
# Console [1] "1951-1980" [1] "1981-2010" [1] "2011-2040_ssp126" [1] "2011-2040_ssp370" [1] "2011-2040_ssp585" [1] "2041-2070_ssp126" [1] "2041-2070_ssp370" [1] "2041-2070_ssp585" [1] "2071-2100_ssp126" [1] "2071-2100_ssp370" [1] "2071-2100_ssp585" > cols NULL
期望生成的cols向量
cols <- c("1951-1980","1981-2010","2011-2040_ssp126","2011-2040_ssp370","2011-2040_ssp585","2041-2070_ssp126","2041-2070_ssp370","2041-2070_ssp585","2071-2100_ssp126","2071-2100_ssp370","2071-2100_ssp585")
附数据框
df <- structure(list(rowname = c("fr2041-2070_ssp126_5521", "fr2071-2100_ssp370_9962", "fr2071-2100_ssp585_6140", "fr2041-2070_ssp126_10362", "fr2071-2100_ssp585_2461", "fr2071-2100_ssp370_5668", "fr2011-2040_ssp585_5251", "fr2041-2070_ssp370_7120", "fr2071-2100_ssp126_7171", "fr2041-2070_ssp126_6092", "fr2071-2100_ssp370_12266", "fr2041-2070_ssp370_4224", "fr2041-2070_ssp370_3195", "fr2071-2100_ssp585_5245", "fr2041-2070_ssp126_5228", "fr2071-2100_ssp370_3492", "fr1951-1980_13223", "fr2071-2100_ssp585_4505", "fr2041-2070_ssp585_6574", "fr1981-2010_9649", "fr1981-2010_8049", "fr2071-2100_ssp370_1269", "fr2041-2070_ssp126_4494", "fr2071-2100_ssp370_2894", "fr2071-2100_ssp585_3951", "fr2041-2070_ssp126_3324", "fr2071-2100_ssp585_4510", "fr2041-2070_ssp370_7156", "fr2071-2100_ssp585_3029", "fr2041-2070_ssp585_2580"), Period = c("2041-2070", "2071-2100", "2071-2100", "2041-2070", "2071-2100", "2071-2100", "2011-2040", "2041-2070", "2071-2100", "2041-2070", "2071-2100", "2041-2070", "2041-2070", "2071-2100", "2041-2070", "2071-2100", "1951-1980", "2071-2100", "2041-2070", "1981-2010", "1981-2010", "2071-2100", "2041-2070", "2071-2100", "2071-2100", "2041-2070", "2071-2100", "2041-2070", "2071-2100", "2041-2070"), Scenario = c("ssp126", "ssp370", "ssp585", "ssp126", "ssp585", "ssp370", "ssp585", "ssp370", "ssp126", "ssp126", "ssp370", "ssp370", "ssp370", "ssp585", "ssp126", "ssp370", NA, "ssp585", "ssp585", NA, NA, "ssp370", "ssp126", "ssp370", "ssp585", "ssp126", "ssp585", "ssp370", "ssp585", "ssp585" )), row.names = c(NA, -30L), class = c("data.table", "data.frame" ))
解决方案
核心原因
R的for循环本身不返回值,用c()包裹循环只能得到NULL;且print()仅输出内容到控制台,不会将值赋值给变量。需要先初始化空向量,再在循环中逐个添加元素。
修改后的代码
方法1:基础循环实现
# 定义periods和ssp(从数据中提取) periods <- unique(df$Period) ssp <- unique(df$Scenario[!is.na(df$Scenario)]) # 初始化空向量 cols <- c() for(j in periods) { # 检查该Period对应的第一个Scenario是否为NA if(is.na(df[df$Period == j, ]$Scenario[[1]])) { cols <- c(cols, j) } else { for (k in ssp) { cols <- c(cols, paste(j, k, sep="_")) } } } # 按期望顺序排序 target_order <- c("1951-1980","1981-2010","2011-2040_ssp126","2011-2040_ssp370","2011-2040_ssp585","2041-2070_ssp126","2041-2070_ssp370","2041-2070_ssp585","2071-2100_ssp126","2071-2100_ssp370","2071-2100_ssp585") cols <- cols[match(target_order, cols)]
方法2:高效向量化实现(推荐)
避免循环,用向量化操作提升效率:
library(dplyr) # 分组判断每个Period是否包含Scenario period_data <- df %>% group_by(Period) %>% summarise(has_scenario = any(!is.na(Scenario))) %>% ungroup() # 生成目标向量 cols <- c( # 无Scenario的Period直接保留 period_data$Period[!period_data$has_scenario], # 有Scenario的Period与ssp组合 outer(period_data$Period[period_data$has_scenario], ssp, paste, sep="_") %>% as.vector() ) # 按目标顺序排序 target_order <- c("1951-1980","1981-2010","2011-2040_ssp126","2011-2040_ssp370","2011-2040_ssp585","2041-2070_ssp126","2041-2070_ssp370","2041-2070_ssp585","2071-2100_ssp126","2071-2100_ssp370","2071-2100_ssp585") cols <- cols[match(target_order, cols)]
验证结果
运行代码后,cols将完全匹配期望的向量:
> cols [1] "1951-1980" "1981-2010" "2011-2040_ssp126" "2011-2040_ssp370" "2011-2040_ssp585" "2041-2070_ssp126" [7] "2041-2070_ssp370" "2041-2070_ssp585" "2071-2100_ssp126" "2071-2100_ssp370" "2071-2100_ssp585"
内容的提问来源于stack exchange,提问作者Tristan
相关产品推荐
相关产品推荐

