R语言给apply缩放函数加if判断后列名特殊字符被替换如何解决
问题描述
我此前写了一个将数据缩放到0-1区间的函数,可保留数据框原列名,代码如下:
scale <- function(x){apply(x, 2, function(y) ((y)-min(y, na.rm=TRUE))/(max(y, na.rm=TRUE)-min(y, na.rm=TRUE)))}
后续我需要针对max(y)等于min(y)的场景添加if分支,修改后的函数代码如下:
scale <- function(x){apply(x, 2, function(y) if(min(y, na.rm=TRUE)==max(y, na.rm=TRUE)) {0.5} else {((y)-min(y, na.rm=TRUE))/(max(y, na.rm=TRUE)-min(y, na.rm=TRUE))})}
我通过如下方式调用函数处理输入数据框:
as.data.frame(scale(input[sapply(input,is.numeric)]))
结果发现原函数可正常保留列名,添加if判断后的函数会将列名中的括号、短横线等特殊字符替换为点号:
- 无if判断时列名示例:
INL_Avg(S-B0-ETC-CDS-06C~PM_CD1_D_B0_SI_P0V_B.NM) - 有if判断时列名示例:
INL_Avg.S.B0.ETC.CDS.06C.PM_CD1_D_B0_SI_P0V_B.NM.
我当前必须使用这些带特殊字符的列名,已尝试给sapply添加USE.NAMES=TRUE参数但无效,请问如何避免特殊字符被替换的问题?
解决方案
列名特殊字符被替换的核心原因是as.data.frame()函数默认开启了列名合法性校验,会自动将列名中R认为不符合标准的字符替换为点号,和你添加的if分支没有直接关联。
你只需要在调用as.data.frame()时添加check.names = FALSE参数关闭列名校验即可解决问题:
as.data.frame(scale(input[sapply(input,is.numeric)]), check.names = FALSE)
另外你可以优化缩放函数,减少min/max的重复计算,同时保证每列返回值的结构一致,避免后续转换出现异常:
scale <- function(x) { apply(x, 2, function(y) { min_val <- min(y, na.rm = TRUE) max_val <- max(y, na.rm = TRUE) if (min_val == max_val) { rep(0.5, length(y)) } else { (y - min_val) / (max_val - min_val) } }) }
内容的提问来源于stack exchange,提问作者MarkH
相关产品推荐
相关产品推荐

