Evaluate code inside a function call in R (use ICC :: ICCbare in a loop)

I want to use a function ICC::ICCbare

in a loop. However, it ICCbare

uses the names of specific variables as input, for example:

ICCbare(x = group, y = variable1, data = dat)

      

resulting in both "group" and "variable1" are columns of data.frame "dat" (ie dat $ variable1); ICCbare

cannot be used with y = dat[, i]

.

For loop programming, I therefore have to evaluate some R code in the function call ICCbare

. My idea was as follows:

for(i in 1:10){
  ICCbare(group, names(dat)[i], data = dat)  
}

      

However, this doesn't work. The following error is thrown:

Error in '[.data.frame`(data, yc) : undefined columns selected'

      

Is there a way to evaluate a statement names(dat)[i])

before it is passed to a function call?

Here is a minimal working example for my problem:

# 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


source to share


3 answers


I agree with @agstudy. This is a bad example of substandard evaluation. You can use this as a workaround:



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

      

+4


source


It is a bug in ICCbare

that tries to poorly manage arguments like 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])

      



Personally, I remove the first lines and just use the assumption that the arguments are just column names.

ICCbare_simple <- 
function (xc, yc, data) 
{
  ## remove lines before this one 
  inds <- unique(data[xc])[[1]]
  ## the rest of the code 
  .....
}

      

+3


source


I support ICC

and I want to thank you for a great discussion. I know this is a very late answer, but I just updated the package and the new version ( v2.3.0

) should fix the "ugly" code and the problem the OP is facing. See Examples for this meaning .

I just wanted to post this here in case anyone was looking for a similar issue. Thanks again, sorry for the delay.

Here is the content of the entity:


Examples of non-standard ICC assessment

The ICC package for R computes the intraclass correlation coefficient (ICC) from one-way ANOVA. The package was recently updated to better perform R custom evaluation in every feature (version 2.3.0 and higher). The package functions can now handle a range of possible scenarios for calling functions, which I hope is a less grotesque and more standard way of writing R functions. Some of these scenarios are shown below for demonstration. Note that the examples use a function ICCbare

, but the way the function arguments are supplied applies to all functions in ICC

.

Download the package first (and make sure the version is> 2.3.0)

library(ICC)
packageVersion("ICC")

      

Columns a data.frame

Here we give the names of the columns and data.frame

, containing the data for calculating the ICC. We'll use the glory of data ChickWeight

.

data(ChickWeight)
ICCbare(x = Chick, y = weight, data = ChickWeight)
#$ICC
#[1] 0.1077609

      

Iterating through columns a data.frame

In this case, we can have data.frame

in which we want to estimate the ICC for a number of different types of measurements, each of which has the same grouping or factor variable (for example x

). The extreme part of this can be related to simulation or loading script or even some fantastic high performance phenotyping / data collection. The point is that we want to automate the ICC calculation for each column.

First, we will simulate our own dataset with three traits to be used in the example:

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)))

      

Two ways to start columns come to mind: iteratively pass the name of each column, or iteratively pass the column index. I will demonstrate both. I am doing this in a loop for

so it is easier to see, but an easy extension would be its vector notation using something from the family of functions apply

. First pass the name:

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 

      

or even like this:

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 

      

Alternatively, pass the column index:

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 

      

Passing a character as an argument is deprecated

Note that the function will work if the character is passed directly (for example "t1"

), although with warning

. The warning means this may no longer work in future versions of the package. For example:

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

      

Note, however, that an expression evaluating a character (such as paste0("t", 1)

) doesn't throw warning

, which is nice!

Analytics

+2


source







All Articles