通过索引获取data.table数值列列名失效问题排查
问题原因分析
你遇到的问题核心是对which()返回值的结构理解有误,我们一步步拆解:
- 首先,
sapply(TDT, is.numeric)会返回一个命名逻辑向量,每个元素对应TDT的一列,名字是列名,值表示该列是否为数值型。针对你的数据集,这个向量的结果大概是:Group Id Time norm x1 x2 x3 x4 x5 FALSE TRUE FALSE TRUE TRUE TRUE TRUE TRUE TRUE - 当你用
which()处理这个逻辑向量时,返回的是一个命名整数向量:它的名字是原逻辑向量中为TRUE的列名,而值是这些列在数据集中的位置索引。所以你的xnumcols实际是这样的:Id norm x1 x2 x3 x4 x5 2 4 5 6 7 8 9 - 接下来你执行
names(xnumcols)[xnumcols]时,names(xnumcols)是一个长度为7的向量(c("Id","norm","x1","x2","x3","x4","x5")),但你用xnumcols里的数值(2,4,5,6,7,8,9)去索引它——其中8和9超出了这个向量的长度(只有7个元素),所以这两个位置返回NA;同时前面的索引取到的也不是你想要的列名(比如索引2取到的是"norm",而你实际想要的是第2列的列名"Id")。
正确的解决方案
这里有几种简单高效的方法可以获取所有数值列的列名:
方法一:直接从原逻辑向量提取列名
这是最直接的方式,不需要借助which():
xstringnumcols <- names(TDT)[sapply(TDT, is.numeric)]
方法二:用已有的位置索引提取列名
如果你已经得到了xnumcols(位置索引),直接用它去索引原数据集的列名即可:
xnumcols <- which(sapply(TDT, is.numeric)) xstringnumcols <- names(TDT)[xnumcols]
方法三:更安全的vapply替代sapply
sapply的返回类型可能会根据输入变化,用vapply可以强制返回逻辑向量,更稳定:
xstringnumcols <- names(TDT)[vapply(TDT, is.numeric, logical(1))]
执行以上任意一种方法,你都会得到正确的数值列名:"Id" "norm" "x1" "x2" "x3" "x4" "x5"
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

