评估R中函数调用中的代码(在循环中使用ICC :: ICCbare)

时间:2014-11-05 08:21:03

标签: r

我想在循环中使用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)
} 

3 个答案:

答案 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非标准评估实例

ICCR包从单因素方差分析中计算出组内相关系数(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,这很好!

Analytics