我正在进行方法比较研究,比较来自两个不同系统的测量结果。我的数据集有大量列,其中包含来自两个系统之一的测量值的变量。
aX和bX都是X的度量,但是来自系统a和b。我有大约80对像这样的变异。
我的数据的简化版本如下所示:
set.seed(1)
df <- data.frame(
ID = as.factor(rep(1:2, each=10)),
aX = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
bX = rep(1:10+rnorm(10,mean=1,sd=0.5),2),
aY = rep(1:10+rnorm(10,mean=1,sd=0.5), 2),
bY = rep(1:10-rnorm(10,mean=1,sd=0.5),2))
head(df)
ID aX bX aY bY
1 1 1.686773 2.755891 2.459489 -0.6793398
2 1 3.091822 3.194922 3.391068 1.0513939
3 1 3.582186 3.689380 4.037282 1.8061642
4 1 5.797640 3.892650 4.005324 3.0269025
5 1 6.164754 6.562465 6.309913 4.6885298
6 1 6.589766 6.977533 6.971936 5.2074973
我试图循环遍历字符向量的元素,并使用元素指向数据框中的列。但是当我尝试调用循环中生成的变量名称的函数时,我不断收到错误消息。
为简单起见,我已经将循环更改为包含线性模型,因为这会产生与原始脚本中相同类型的错误。
#This line is only included to show that
#the formula used in the loop works when
#called with directly with the "real" column names
(broom::glance(lm(aX~bX, data = df)))$r.squared
[1] 0.9405218
#Now I try the loop
varlist <- c("X", "Y")
for(i in 1:length(varlist)){
aVAR <- paste0("a", varlist[i])
bVAR <- paste0("b", varlist[i])
#VAR and cVAR appear to have names identical column names in the df dataframe
print(c(aVAR, bVAR))
#Try the formula with the loop variable names
print((broom::glance(lm(aVAR~bVAR, data = df)))$r.squared)
}
从循环内部调用函数时得到的错误消息因我调用的函数而异,所有错误的共同点是当我尝试使用字符向量(varlist)时出现的错误具体栏目。
错误消息示例:
rmcorr(ID, aVAR, bVAR, df)
Error in rmcorr(ID, aVAR, bVAR, df) :
'Measure 1' and 'Measure 2' must be numeric
或
broom::glance(lm(aVAR~bVAR, data = df))
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) :
contrasts can be applied only to factors with 2 or more levels
In addition: Warning message:
In storage.mode(v) <- "double" : NAs introduced by coercion
你能帮我理解循环中出了什么问题吗?或建议并展示另一种方式来完成我想要做的事情。
答案 0 :(得分:2)
变量不在公式中评估(具有~
的东西)。
您可以输入
bert ~ ernie
即使名为bert
和ernie
的变量不存在也不会出错。符号/名称之间的公式存储关系并不试图评估它们。另请注意,我们这里没有使用引号。变量名称(或符号)不能与字符值互换(即aX
与"aX"
非常不同。
因此,当从字符串值中汇总公式时,我建议您使用reformualte()
函数。它采用右侧的名称向量和左侧的可选值。因此,您将使用
reformulate("ernie", "bert")
# bert ~ ernie
你可以使用你的lm
lm(reformulate(bVAR, aVAR), data = df)
答案 1 :(得分:1)
我懒得搜索关于如何以编程方式构造公式的副本,所以这是一个解决方案:
varlist <- c("X", "Y")
for(i in 1:length(varlist)){
#make these symbols:
aVAR <- as.symbol(paste0("a", varlist[i]))
bVAR <- as.symbol(paste0("b", varlist[i]))
#VAR and cVAR appear to have names identical column names in the df dataframe
print(c(aVAR, bVAR))
#Try the formula with the loop variable names
#construct the call to `lm` with `bquote` and `eval` the expression
print((broom::glance(eval(bquote(lm(.(aVAR) ~ .(bVAR), data = df)))))$r.squared)
}