我想在循环中使用ICC::ICCbare
函数。但是,ICCbare
使用具体的变量名作为输入,例如:
ICCbare(x = group, y = variable1, data = dat)
其中" group"和"变量1"是data.frame" dat"的列。 (即dat $ variable1); ICCbare
不能与y = dat[, i]
一起使用。
为了编写循环,我需要在ICCbare
的函数调用中评估一些R代码。我的想法如下:
for(i in 1:10){
ICCbare(group, names(dat)[i], data = dat)
}
然而,这不起作用。打印以下错误:
Error in '[.data.frame`(data, yc) : undefined columns selected'
有没有办法在语句names(dat)[i])
传递给函数调用之前先对其进行评估?
以下是我的问题的最低工作示例:
# Create data set
dat <- data.frame(group=c(rep("A",5),
rep("B",5)),
variable1=1:10,
variable2=rnorm(10))
# Loop
for (i in names(dat)[2:3]){
ICCbare("group", i, data = dat)
}
答案 0 :(得分:4)
我同意@agstudy。这是非标准评估的一个不好的例子。您可以将其用作解决方法:
v <- "variable1"
ICCbare("group", v, data = dat)
#Error in `[.data.frame`(data, yc) : undefined columns selected
eval(bquote(ICCbare("group", .(v), data = dat)))
#$ICC
#[1] 0.8275862
答案 1 :(得分:3)
ICCbare
中的一个错误是尝试以错误的方式将参数作为name
进行管理。
function (x, y, data)
{
ICCcall <- Call <- match.call()
xc <- as.character(ICCcall[[2L]]) ## this is ugly!
yc <- as.character(ICCcall[[3L]])
inds <- unique(data[xc])[[1]]
tdata <- data.frame(data[yc], data[xc])
我个人会删除第一行,只是假设参数只是列名。
ICCbare_simple <-
function (xc, yc, data)
{
## remove lines before this one
inds <- unique(data[xc])[[1]]
## the rest of the code
.....
}
答案 2 :(得分:3)
我是ICC
的维护者,我想感谢你们的精彩讨论。我知道这是一个非常晚的回复,但我刚刚更新了包,新版本(v2.3.0
)应该修复“丑陋”代码和OP遇到的问题。请参阅this gist中的示例。
我只是想发布此处以防万一有人在搜索类似的问题。再次感谢,抱歉延误。
以下是要点的内容:
ICC的R包从单因素方差分析中计算出组内相关系数(ICC)。最近,该软件包已更新,以便在每个函数(版本2.3.0及更高版本)中更好地执行R的非标准评估。包函数现在应该能够处理一系列可能的场景,用于调用函数,我希望,这是一种不那么怪诞且更标准的编写R函数的方法。为了演示,以下是其中一些场景。注意,这些示例使用ICCbare
函数,但提供函数参数的方式将应用于ICC
中的所有函数。
首先,加载包(并确保版本为&gt; 2.3.0)
library(ICC)
packageVersion("ICC")
data.frame
这里我们提供列名和包含数据的data.frame
来计算ICC。我们将使用ChickWeight
数据名称。
data(ChickWeight)
ICCbare(x = Chick, y = weight, data = ChickWeight)
#$ICC
#[1] 0.1077609
data.frame
在这种情况下,我们可能会有一个data.frame
我们想要估算ICC的多种不同类型的测量值,每种测量值都具有相同的分组或因子变量(例如x
) 。这种情况的极端可能出现在模拟或自举场景中,甚至可能是一些奇特的高通量表型/数据收集。关键是,我们希望自动计算每列的ICC。
首先,我们将模拟我们自己的数据集,其中包含3个特征:
set.seed(101)
n <- 15 # number of individuals/groups/categories/factors
k <- 3 # number of measures per 'n'
va <- 1 # variance among
icc <- 0.6 # expected ICC
vw <- (va * (1 - icc)) / icc # solve for variance within
simdf <- data.frame(ind = rep(LETTERS[1:n], each = k),
t1 = rep(rnorm(n, 10, sqrt(va)), each = k) + rnorm(n*k, 0, sqrt(vw)),
t2 = rep(rnorm(n, 10, sqrt(va)), each = k) + rnorm(n*k, 0, sqrt(vw)),
t3 = rep(rnorm(n, 10, sqrt(va)), each = k) + rnorm(n*k, 0, sqrt(vw)))
我想到了两种运行列的方法:迭代传递每列的名称或迭代传递列索引。我将在下面演示。我在for
循环中执行这些操作,因此更容易看到,但通过使用apply
函数族中的某些内容,可以轻松扩展它。首先,传递名称:
for(i in names(simdf)[-1]){
cat(i, ":")
tmp.icc <- ICCbare(x = ind, y = i, data = simdf)
cat(tmp.icc, "\n")
}
#t1 : 0.60446
#t2 : 0.6381197
#t3 : 0.591065
甚至是这样:
for(i in 1:3){
cat(paste0("t", i), ": ")
tmp.icc <- ICCbare(x = ind, y = paste0("t", i), data = simdf)
cat(tmp.icc, "\n")
}
#t1 : 0.60446
#t2 : 0.6381197
#t3 : 0.591065
或者,传递列索引:
for(i in 2:ncol(simdf)){
cat(names(simdf)[i], ": ")
tmp.icc <- ICCbare(x = ind, y = simdf[, i], data = simdf)
cat(tmp.icc, "\n")
}
#t1 : 0.60446
#t2 : 0.6381197
#t3 : 0.591065
请注意,如果直接传递字符(例如"t1"
),该函数仍然有效,尽管有warning
。警告只是意味着这可能不再适用于包的未来版本。例如:
ICCbare(x = ind, y = "t1", data = simdf)
#[1] 0.60446
#Warning message:
#In ICCbare(x = ind, y = "t1", data = simdf) :
# passing a character string to 'y' is deprecated since ICC version
# 2.3.0 and will not be supported in future versions. The argument
# to 'y' should either be an unquoted column name of 'data' or an object
但请注意,评估字符的表达式(例如paste0("t", 1)
)不会抛出warning
,这很好!