如何用for循环在data.table中仅计算选定变量的相关性
解决data.table中按组计算指定变量相关性的报错问题
你遇到的'y' must be numeric错误,本质是调用cor(.SD, xcor)时,xcor是字符向量(列名),但cor函数的第二个参数需要接收数值向量,而不是列名。.SD是一个data.table对象,直接把列名传给cor,它无法自动识别为对应的数值列,所以触发了报错。
下面给你两种靠谱的解决方案,一种是更简洁的向量化写法(不用循环),另一种是修正后的for循环实现:
方案一:用lapply实现向量化计算(推荐)
这种写法更符合data.table的风格,代码简洁效率也高:
set.seed(1) TDT <- data.table(Group = c(rep("A",40),rep("B",60)), Id = c(rep(1,20),rep(2,20),rep(3,20),rep(4,20),rep(5,20)), Time = rep(seq(as.Date("2010-01-03"), length=20, by="1 month") - 1,5), norm = round(runif(100)/10,2), y = sample(100,100), x2 = round(rnorm(100,0.75,0.3),2), x3 = round(rnorm(100,0.75,0.3),2), x4 = round(rnorm(100,0.75,0.3),2), x5 = round(rnorm(100,0.75,0.3),2)) # 获取数值型变量 numcols <- names(Filter(is.numeric, TDT)) # 定义需要计算相关性的目标自变量 xcor <- c("x2","x3") # 按Time分组,计算每个xcor变量与所有数值变量的相关性 TDT.x.cor <- TDT[, lapply(xcor, function(var) cor(.SD, .SD[[var]])), .SDcols = numcols, by = Time] # 重命名列,让结果更直观 setnames(TDT.x.cor, paste0("V", seq_along(xcor)), paste0("cor_with_", xcor))
这里用lapply遍历xcor中的每个变量名,通过.SD[[var]]提取对应的数值向量,再和.SD(所有数值列)计算相关性。最后用setnames给结果列重命名,方便后续查看。
方案二:修正后的for循环写法
如果你更习惯用循环,只需修正原代码的语法问题即可:
set.seed(1) TDT <- data.table(Group = c(rep("A",40),rep("B",60)), Id = c(rep(1,20),rep(2,20),rep(3,20),rep(4,20),rep(5,20)), Time = rep(seq(as.Date("2010-01-03"), length=20, by="1 month") - 1,5), norm = round(runif(100)/10,2), y = sample(100,100), x2 = round(rnorm(100,0.75,0.3),2), x3 = round(rnorm(100,0.75,0.3),2), x4 = round(rnorm(100,0.75,0.3),2), x5 = round(rnorm(100,0.75,0.3),2)) numcols <- names(Filter(is.numeric, TDT)) xcor <- c("x2","x3") # 初始化空list存储每个变量的相关性结果 cor_results <- list() for (var in xcor) { # 计算当前变量与所有数值变量的相关性,并给结果列命名 cor_results[[var]] <- TDT[, setNames(cor(.SD, .SD[[var]]), paste0("cor_with_", var)), .SDcols = numcols, by = Time] } # 按Time列合并所有结果 TDT.x.cor <- Reduce(function(a,b) merge(a,b, by = "Time"), cor_results)
原循环的问题在于:
- 不需要把
xcor定义为list,用普通字符向量即可 - 不能用
TDT.xcor[[i]].cor这种错误的赋值语法,先初始化list存储每个变量的结果,最后再合并成一个data.table
两种方案最终都会得到按Time分组的相关性结果,包含所有数值变量与x2、x3的相关性,也会自动包含y与这两个变量的相关性,和你之前计算的TDT.y.cor可以对应上。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

