R语言:使用paste0、get与for循环批量处理列的实现问题
数据结构说明
以下是我的数据结构:
(数字代表不同种类的水果;CT1_100_FQ、CT1_100_AM、CT1_100_SS为预设数值)
library(plyr); library(dplyr) library(magrittr) library(ExclusionTable) library(lubridate) totfr <- list('095', '096', '097', '098', '099', '100', '101', '102', '103', '104', '105', '106') hgi <- list('096', '097', '099') mgi <- list('100', '101', '105') lgi <- list('095', '098', '102', '103', '104', '106') hgl <- list('097', '099', '104', '105') mgl <- list('096', '100') lgl <- list('095', '098', '101', '102', '103', '106') classification <- list( totfr, hgi, mgi, lgi, hgl, mgl, lgl ) names(classification) <- c( "totfr", "hgi", "mgi", "lgi", "hgl", "mgl", "lgl" )
现有代码
ct <- ct %>% for (i in 1:length(classification)) for (j in 1:length(classification[[i]])){ get(paste("ct$CT1_F", classification[[i]][j], sep="")) <- get(paste("ct$CT1_F", paste0(classification[[i]][j], "_FQ"), sep="")[i])*paste("ct$CT1_F", paste0(classification[[i]][j], "_SS"), sep="")*paste("CT1_F", paste0(classification[[i]][j], "_AM"), sep="") } %>% lapply(List, function(x) lapply(x, rowSums)) for (i in 1:length(classification)) paste("ct$CT1_", names(classification[i]), sep="") = rowSums(paste("ct$CT1_F", classification[[i]], sep=""), na.rm = T)
需求与问题
我希望上述代码实现以下手动代码的效果,但用get()函数始终失败,get()只返回字符类型:
# 所有列均属于名为ct的data.frame。 ct$CT1_F095 = ct$CT1_F095_FQ*ct$CT1_F095_SS*ct$CT1_F095_AM, ct$CT1_F096 = ct$CT1_F096_FQ*ct$CT1_F096_SS*ct$CT1_F096_AM, ct$CT1_F097 = ct$CT1_F097_FQ*ct$CT1_F097_SS*ct$CT1_F097_AM, ct$CT1_F098 = ct$CT1_F098_FQ*ct$CT1_F098_SS*ct$CT1_F098_AM, ct$CT1_F099 = ct$CT1_F099_FQ*ct$CT1_F099_SS*ct$CT1_F099_AM, ct$CT1_F100 = ct$CT1_F100_FQ*ct$CT1_F100_SS*ct$CT1_F100_AM, ct$CT1_F101 = ct$CT1_F101_FQ*ct$CT1_F101_SS*ct$CT1_F101_AM, ct$CT1_F102 = ct$CT1_F102_FQ*ct$CT1_F102_SS*ct$CT1_F102_AM, ct$CT1_F103 = ct$CT1_F103_FQ*ct$CT1_F103_SS*ct$CT1_F103_AM, ct$CT1_F104 = ct$CT1_F104_FQ*ct$CT1_F104_SS*ct$CT1_F104_AM, ct$CT1_F105 = ct$CT1_F105_FQ*ct$CT1_F105_SS*ct$CT1_F105_AM, ct$CT1_F106 = ct$CT1_F106_FQ*ct$CT1_F106_SS*ct$CT1_F106_AM, ct$CT1_TOTFR = rowSums(pick(ct$CT1_F095:ct$CT1_F106), na.rm = T), ct$CT1_GI_L_F = rowSums(lgi, na.rm = T), ct$CT1_GI_M_F = rowSums(mgi, na.rm = T), ct$CT1_GI_H_F = rowSums(hgi, na.rm = T), ct$CT1_GL_L_F = rowSums(lgl, na.rm = T), ct$CT1_GL_M_F = rowSums(mgl, na.rm = T), ct$CT1_GL_H_F = rowSums(hgl, na.rm = T)
测试结果
执行代码:
paste("ct$CT1_F", classification[[1]], sep="")
返回结果:
[1] "ct$CT1_F095" "ct$CT1_F096" "ct$CT1_F097" "ct$CT1_F098" "ct$CT1_F099" "ct$CT1_F100" [7] "ct$CT1_F101" "ct$CT1_F102" "ct$CT1_F103" "ct$CT1_F104" "ct$CT1_F105" "ct$CT1_F106"
执行:
str(paste("ct$CT1_F", classification[[1]], sep=""))
返回:
chr [1:12] "ct$CT1_F095" "ct$CT1_F096" "ct$CT1_F097" "ct$CT1_F098" "ct$CT1_F099" ...
手动输入:
> ct$CT1_F095
得到数值型结果:
> [1] 7.00000000 1.75000000 0.75000000 3.50000000 0.75000000 1.75000000 3.50000000 [8] 0.11627907 0.00000000 0.05813953 0.75000000 5.25000000 0.11627907 0.00000000 [15] 0.75000000 1.75000000 1.75000000 0.29069767 0.37500000 2.62500000 0.37500000 [22] 0.29069767 0.87500000 1.74418605 1.75000000 1.50000000 0.75000000 0.14534884 [29] 1.12500000 2.75000000 0.75000000 1.75000000 3.50000000 0.05813953 4.12500000 [36] 0.37500000 3.50000000 0.75000000 0.75000000 0.11627907 1.75000000 1.12500000 [ reached getOption("max.print") -- omitted 64608 entries ]
解决方案
不要用get()操作data.frame的列,直接通过列名字符串索引更可靠。以下是实现需求的代码:
# 提取所有水果编码 fruit_codes <- unlist(classification$totfr) # 批量计算CT1_Fxxx列 for (code in fruit_codes) { col_fq <- paste0("CT1_F", code, "_FQ") col_ss <- paste0("CT1_F", code, "_SS") col_am <- paste0("CT1_F", code, "_AM") col_target <- paste0("CT1_F", code) ct[[col_target]] <- ct[[col_fq]] * ct[[col_ss]] * ct[[col_am]] } # 批量计算各类分组的行和 group_mapping <- list( "TOTFR" = classification$totfr, "GI_L_F" = classification$lgi, "GI_M_F" = classification$mgi, "GI_H_F" = classification$hgi, "GL_L_F" = classification$lgl, "GL_M_F" = classification$mgl, "GL_H_F" = classification$hgl ) for (group_name in names(group_mapping)) { col_names <- paste0("CT1_F", unlist(group_mapping[[group_name]])) ct[[paste0("CT1_", group_name)]] <- rowSums(ct[col_names], na.rm = TRUE) }
说明
- 用
ct[[列名字符串]]的方式直接访问和赋值data.frame的列,避免get()的字符解析问题 - 先提取所有水果编码,循环计算每个CT1_Fxxx列
- 定义分组映射,循环计算每个分组的行和,代码更简洁易维护
内容的提问来源于stack exchange,提问作者HJ WHY
相关产品推荐
相关产品推荐

