Nothing
# Test cases for function 'anovaVCA' of R-package VCA
#
# Author: André Schützenmeister
#
# Reference results were obtained by application of SAS 9.2 PROC NESTED to
# test data, SAS PROC VARCOMP or SAS PROC MIXED method=type1.
#
###############################################################################
cat("\n\n***********************************************************************")
cat("\nVariance Component Analysis (VCA) - test cases for function 'anovaVCA'.")
cat("\n***********************************************************************\n\n")
### load all testdata
data(dataEP05A2_1)
data(dataEP05A2_2)
data(dataEP05A2_3)
data(dataEP05A3_MS_1)
data(dataEP05A3_MS_2)
data(dataEP05A3_MS_3)
data(dataRS0003_1)
data(dataRS0003_2)
data(dataRS0003_3)
data(dataRS0005_1)
data(dataRS0005_2)
data(dataRS0005_3)
### check results of function 'anovaVCA' ###
# check whether function 'anovaVCA' throws exceptions as expected
TF001.anovaVCA.exception <- function()
{
checkException(anovaVCA()) # no input at all
checkException(anovaVCA(Data=1))
checkException(anovaVCA(Data=data.frame()))
checkException(anovaVCA(Data=data.frame(y=1:10)))
checkException(anovaVCA(z~day/run, Data=data.frame(y=1:10)))
checkException(anovaVCA(y~day/run, Data=data.frame(y=1:10, day=1:10)))
}
## EP05-A2 20/2/2 Within-Lab Precision Experiments (Single-Site Experiment in EP05-A3) - balanced
TF002.anovaVCA.EP05_A2_intermediate_precision.balanced <- function()
{
res <- anovaVCA(y~day/run, Data=dataEP05A2_1) # call function
checkEquals(round(as.numeric(res$aov.tab[,"VC"]),6), c(3.298986, 0.001096, 1.344492, 1.953397)) # variance components are derived from mean sum of squares --> checking SSQ und MSQ not necessary
res <- anovaVCA(y~day/run, Data=dataEP05A2_2) # call function
checkEquals(round(as.numeric(res$aov.tab[,"VC"]),6), c(8.400103, 1.853772, 2.826050, 3.720281)) # variance components are derived from mean sum of squares --> checking SSQ und MSQ not necessary
res <- anovaVCA(y~day/run, Data=dataEP05A2_3) # call function
checkEquals(round(as.numeric(res$aov.tab[,"VC"]),6), c( 35.546313, 12.231099, 7.031193, 16.284021)) # variance components are derived from mean sum of squares --> checking SSQ und MSQ not necessary
}
# unbalanced
TF003.anovaVCA.EP05_A2_intermediate_precision.unbalanced <- function()
{
res <- anovaVCA(y~day/run, Data=dataEP05A2_1[-c(11, 12, 17, 37, 45, 56, 57, 68),])
checkEquals(round(as.numeric(res$aov.tab[,"VC"]),6), c(3.272031, 0.278178, 0.875624, 2.118229))
res <- anovaVCA(y~day/run, Data=dataEP05A2_2[-c(2, 12, 22, 23, 24, 55, 56, 71),])
checkEquals(round(as.numeric(res$aov.tab[,"VC"]),6), c(8.81105, 1.425126, 3.478988, 3.906936 ))
res <- anovaVCA(y~day/run, Data=dataEP05A2_3[-c(1,6,7,36,61:65),])
checkEquals(round(as.numeric(res$aov.tab[,"VC"]),6), c( 33.701053, 10.384121, 7.937951, 15.378981 ))
}
# check whether the reported SD-values are correctly computed by comparing the square-root values of
# VC-values to values of column "SD"
TF004.anovaVCA.SD_results <- function()
{
res <- anovaVCA(y~day/run, Data=dataEP05A2_1[-c(11, 12, 17, 37, 45, 56, 57, 68),])
checkEquals(round(sqrt(as.numeric(res$aov.tab[,"VC"])),6), round(as.numeric(res$aov.tab[,"SD"]), 6))
res <- anovaVCA(y~day/run, Data=dataEP05A2_2[-c(2, 12, 22, 23, 24, 55, 56, 71),])
checkEquals(round(sqrt(as.numeric(res$aov.tab[,"VC"])),6), round(as.numeric(res$aov.tab[,"SD"]), 6))
res <- anovaVCA(y~day/run, Data=dataEP05A2_3[-c(1,6,7,36,61:65),])
checkEquals(round(sqrt(as.numeric(res$aov.tab[,"VC"])),6), round(as.numeric(res$aov.tab[,"SD"]), 6))
}
# check whether the reported CV-values are correctly computed by comparing 100 times square-root values
# of the VC-value devided by the mean to values of column "CV[%]"
TF005.anovaVCA.CV_perc_results <- function()
{
res <- anovaVCA(y~day/run, Data=dataEP05A2_1[-c(11, 12, 17, 37, 45, 56, 57, 68),])
checkEquals(round(sqrt(as.numeric(res$aov.tab[,"VC"]))*100/res$Mean,6), round(as.numeric(res$aov.tab[,"CV[%]"]), 6))
res <- anovaVCA(y~day/run, Data=dataEP05A2_2[-c(2, 12, 22, 23, 24, 55, 56, 71),])
checkEquals(round(sqrt(as.numeric(res$aov.tab[,"VC"]))*100/res$Mean,6), round(as.numeric(res$aov.tab[,"CV[%]"]), 6))
res <- anovaVCA(y~day/run, Data=dataEP05A2_3[-c(1,6,7,36,61:65),])
checkEquals(round(sqrt(as.numeric(res$aov.tab[,"VC"]))*100/res$Mean,6), round(as.numeric(res$aov.tab[,"CV[%]"]), 6))
}
# check whether values in column "%Total" were correctly computed
TF006.anovaVCA.Percent_Total_results <- function()
{
res <- anovaVCA(y~day/run, Data=dataEP05A2_1)
checkEquals(round(as.numeric(res$aov.tab[,"VC"])*100/sum(as.numeric(res$aov.tab[-1, "VC"])),6), round(as.numeric(res$aov.tab[,"%Total"]), 6)) # exclude total variance in the sum
res <- anovaVCA(y~day/run, Data=dataEP05A2_2)
checkEquals(round(as.numeric(res$aov.tab[,"VC"])*100/sum(as.numeric(res$aov.tab[-1, "VC"])),6), round(as.numeric(res$aov.tab[,"%Total"]), 6))
res <- anovaVCA(y~day/run, Data=dataEP05A2_3)
checkEquals(round(as.numeric(res$aov.tab[,"VC"])*100/sum(as.numeric(res$aov.tab[-1, "VC"])),6), round(as.numeric(res$aov.tab[,"%Total"]), 6))
}
## EP05-A3 3/5/5 Multi-Site Experiments - balanced
TF007.anovaVCA.EP05_A3_Reproducibility.balanced <- function()
{
res <- anovaVCA(y~site/day, Data=dataEP05A3_MS_1)
checkEquals(round(as.numeric(res$aov.tab[,"VC"]), 6), c( 3.635232, 1.017401, 0.345882, 2.271949))
res <- anovaVCA(y~site/day, Data=dataEP05A3_MS_2)
checkEquals(round(as.numeric(res$aov.tab[,"VC"]), 6), c(5.765516, 1.010798, 1.028309, 3.726408))
res <- anovaVCA(y~site/day, Data=dataEP05A3_MS_3)
checkEquals(round(as.numeric(res$aov.tab[,"VC"]), 6), c(38.438903, 17.990790, 5.423654, 15.024459))
}
# unbalanced
TF008.anovaVCA.EP05_A3_Reproducibility.unbalanced <- function()
{
res <- anovaVCA(y~site/day, Data=dataEP05A3_MS_1[-c(11, 12, 17, 37, 45, 56, 57, 68), ])
checkEquals(round(as.numeric(res$aov.tab[,"VC"]), 6), c( 3.244177, 0.785705, 0.396764, 2.061709 ))
res <- anovaVCA(y~site/day, Data=dataEP05A3_MS_2[-c(2, 12, 22, 23, 24, 55, 56, 71), ])
checkEquals(round(as.numeric(res$aov.tab[,"VC"]), 6), c( 5.773996, 0.729652, 0.917329, 4.127015 ))
res <- anovaVCA(y~site/day, Data=dataEP05A3_MS_3[-c(1,6,7,36,61:65),])
checkEquals(round(as.numeric(res$aov.tab[,"VC"]), 6), c(37.092294, 16.872368, 4.773611, 15.446314))
}
## RS0003 21 replications, testing only the residual error component
## WRI = within run imprecision
TF009.anovaVCA.WRI <- function()
{
res <- anovaVCA(y~1, Data=dataRS0003_1)
checkEquals( round(as.numeric(res$aov.tab[2,c("SS", "MS")]),5), c(22.44452, 1.12223) )
res <- anovaVCA(y~1, Data=dataRS0003_2)
checkEquals( round(as.numeric(res$aov.tab[2,c("SS", "MS")]),4), c(367.3480, 18.3674) )
res <- anovaVCA(y~1, Data=dataRS0003_3)
checkEquals( round(as.numeric(res$aov.tab[2,c("SS", "MS")]),2), c(2210.59, 110.53) )
}
## RS0005 - Confirmation of internal data by external labs - balanced
## BDI = between day imprecision
TF010.anovaVCA.BDI.external_labs.balanced <- function()
{
res <- anovaVCA(y~day, Data=dataRS0005_1, NegVC=TRUE)
checkEquals( round(as.numeric(res$aov.tab[,"VC"]), 6), c(5.193341, 1.818128, 3.375212))
res <- anovaVCA(y~day, Data=dataRS0005_2, NegVC=TRUE)
checkEquals( round(as.numeric(res$aov.tab[,"VC"]), 6), c(6.611960, 0.055541, 6.556419))
res <- anovaVCA(y~day, Data=dataRS0005_3, NegVC=TRUE)
checkEquals( round(as.numeric(res$aov.tab[,"VC"]), 5), c(75.69922, 22.45171, 53.24751))
}
# unbalanced
TF011.anovaVCA.BDI.external_labs.unbalanced <- function()
{
res <- anovaVCA(y~day, Data=dataRS0005_1[-c(1,10),], NegVC=TRUE)
checkEquals( round(as.numeric(res$aov.tab[,"VC"]), 6), c(5.460289, 3.592088, 1.868201))
res <- anovaVCA(y~day, Data=dataRS0005_2[-c(4,5,15),], NegVC=FALSE) # NegVC=FALSE, because SAS PROC NESTED does not count negative VCs to total VC
checkEquals( round(as.numeric(res$aov.tab[,"VC"]), 6), c( 8.548521, 0, 8.548521))
res <- anovaVCA(y~day, Data=dataRS0005_3[-c(2,7,9,14),], NegVC=FALSE)
checkEquals( round(as.numeric(res$aov.tab[,"VC"]), 6), c( 62.404131, 0, 62.404131 ))
}
# test whether conversion of variables to factors is correct
TF012.anovaVCA.variable_conversion <- function()
{
data(dataEP05A2_1)
dat1 <- dataEP05A2_1
dat1$day <- as.integer(as.character(dat1$day))
dat1$run <- as.integer(as.character(dat1$run))
res1 <- anovaVCA(y~day/run, dat1)
res2 <- anovaVCA(y~day/run, dataEP05A2_1)
checkEquals( res1$aov.tab, res2$aov.tab )
}
# test whether missing values in response and other variables are correctly handled
TF013.anovaVCA.missing_value_handling <- function()
{
data(dataEP05A2_3)
dat0 <- dataEP05A2_3
dat0[c(5,15,25), "y"] <- NA # generated missing data
dat0[c(3,17,58), "day"] <- NA
dat0[c(51,70,77), "run"] <- NA
datNoNA <- na.omit(dat0)
res1 <- anovaVCA(y~day/run, dat0)
res2 <- anovaVCA(y~day/run, datNoNA)
checkEquals(as.matrix(res1$aov.tab), as.matrix(res2$aov.tab))
checkEquals(res1$Nrm, 9)
checkEquals(res1$Nobs, 71)
checkEquals(res2$Nobs, 71)
}
# check numerical equivalence of a crossed-nested design (balanced)
#
# check vs. SAS PROC MIXED results using this SAS-code:
#
# proc mixed data=sample1 method=type1 cl;
# class lot device day run;
# model y=;
# random lot device lot*device*day lot*device*day*run;
# run;
TF014.anovaVCA.crossed_nested.balanced <- function()
{
data(VCAdata1)
sample1 <- VCAdata1[which(VCAdata1$sample==1),]
sample1$device <- gl(3,28,252) # add device variable
set.seed(505)
sample1$y <- sample1$y + rep(rep(rnorm(3,,.25), c(28,28,28)),3) # add error component according to
# write.table(sample1, file="sample1.txt", quote=FALSE, row.names=FALSE, col.names=TRUE, sep="\t") # export data, import to SAS and apply SAS-code given above
res1 <- anovaVCA(y~lot+device+(lot:device:day)/run, sample1)
checkEquals(round(res1$aov.tab[2, "VC"], 5), 0.01552) # round to default precision of SAS PROC MIXED output
checkEquals(round(res1$aov.tab[3, "VC"], 5), 0.06214)
checkEquals(round(res1$aov.tab[4, "VC"], 5), 0.01256)
checkEquals(round(res1$aov.tab[5, "VC"], 5), 0.05074)
checkEquals(round(res1$aov.tab[6, "VC"], 6), 0.001152)
}
# now test numerical equivalence to SAS PROC MIXED results with unbalanced data
# using following SAS-code:
#
# data sample1UB;
# set sample1;
# obs = _N_;
# if obs in (5,31,55) then delete;
# run;
#
# proc mixed data=sample1UB method=type1 asycov cl;
# class lot device day run;
# model y=;
# random lot device lot*device*day lot*device*day*run;
# run;
TF015.anovaVCA.crossed_nested.unbalanced <- function()
{
data(VCAdata1)
sample1 <- VCAdata1[which(VCAdata1$sample==1),]
sample1$device <- gl(3,28,252) # add device variable
set.seed(505)
sample1$y <- sample1$y + rep(rep(rnorm(3,,.25), c(28,28,28)),3) # add error component according to
sample1UB <- sample1[-c(5,31,55),] # delete some observations
# write.table(sample1UB, file="sample1UB.txt", quote=FALSE, row.names=FALSE, col.names=TRUE, sep="\t") # export data, import to SAS and apply SAS-code given above
res1UB <- anovaVCA(y~lot+device+(lot:device:day)/run, sample1UB)
checkEquals(round(res1UB$aov.tab[2, "VC"], 5), 0.01507) # round to precision of SAS PROC MIXED output
checkEquals(round(res1UB$aov.tab[3, "VC"], 5), 0.06284)
checkEquals(round(res1UB$aov.tab[4, "VC"], 5), 0.01259)
checkEquals(round(res1UB$aov.tab[5, "VC"], 5), 0.05143)
checkEquals(round(res1UB$aov.tab[6, "VC"], 6), 0.001145)
}
# use subset "sample_8" of VCAdata1
TF016.anovaVCA.crossed_nested.balanced <- function()
{
data(VCAdata1)
sample8 <- VCAdata1[which(VCAdata1$sample==8),]
sample8$device <- gl(3,28,252) # add device variable
set.seed(903211)
sample8$y <- sample8$y + rep(rep(rnorm(3,,.75), c(28,28,28)),3) # add error component according to
# write.table(sample8, file="sample8.txt", quote=FALSE, row.names=FALSE, col.names=TRUE, sep="\t") # export data, import to SAS and apply SAS-code given above
res8 <- anovaVCA(y~lot+device+(lot:device:day)/run, sample8)
checkEquals(round(res8$aov.tab[2, "VC"], 4), 7.3463) # round to precision of SAS PROC MIXED output
checkEquals(round(res8$aov.tab[3, "VC"], 4), 2.2716)
checkEquals(round(res8$aov.tab[4, "VC"], 4), 3.4588)
checkEquals(round(res8$aov.tab[5, "VC"], 4), 2.0302)
checkEquals(round(res8$aov.tab[6, "VC"], 4), 1.2219)
}
# use subset "sample_8" of VCAdata1 and generate unbalancedness
TF017.anovaVCA.crossed_nested.unbalanced <- function()
{
data(VCAdata1)
sample8 <- VCAdata1[which(VCAdata1$sample==8),]
sample8$device <- gl(3,28,252) # add device variable
set.seed(903211)
sample8$y <- sample8$y + rep(rep(rnorm(3,,.75), c(28,28,28)),3) # add error component according to
sample8UB <- sample8[-c(7, 18, 19, 101, 191, 193, 202, 203, 204, 222),]
# write.table(sample8UB, file="sample8UB.txt", quote=FALSE, row.names=FALSE, col.names=TRUE, sep="\t") # export data, import to SAS and apply SAS-code given above
res8UB <- anovaVCA(y~lot+device+(lot:device:day)/run, sample8UB)
checkEquals(round(res8UB$aov.tab[2, "VC"], 4), 7.2724) # round to precision of SAS PROC MIXED output
checkEquals(round(res8UB$aov.tab[3, "VC"], 4), 2.2278)
checkEquals(round(res8UB$aov.tab[4, "VC"], 4), 3.6385)
checkEquals(round(res8UB$aov.tab[5, "VC"], 4), 1.9844)
checkEquals(round(res8UB$aov.tab[6, "VC"], 4), 1.2451)
}
# checking the implemented strategy of obtaining the ANOVA Type-I DFs
TF018.anovaDF.balanced <- function()
{
aov.fit <- anova(lm(y~day/run, dataEP05A2_1))
rm.fit <- anovaVCA(y~day/run, dataEP05A2_1)
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
TF019.anovaDF.unbalanced <- function()
{
aov.fit <- anova(lm(y~day/run, dataEP05A2_1[-c(1,7,11,41,50:55),]))
rm.fit <- anovaVCA(y~day/run, dataEP05A2_1[-c(1,7,11,41,50:55),])
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
TF020.anovaDF.balanced <- function()
{
aov.fit <- anova(lm(y~day/run-1, dataEP05A2_1))
rm.fit <- anovaVCA(y~day/run-1, dataEP05A2_1)
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
TF021.anovaDF.unbalanced <- function()
{
aov.fit <- anova(lm(y~day/run-1, dataEP05A2_1[-c(1,7,11,41,50:55),]))
rm.fit <- anovaVCA(y~day/run-1, dataEP05A2_1[-c(1,7,11,41,50:55),])
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
# only interactions no main factors (actually violating marginality principle)
data(VCAdata1)
datS1to2 <- VCAdata1[VCAdata1$sample %in% 1:2,]
datS4to5 <- VCAdata1[VCAdata1$sample %in% 4:5,]
datS1to2.ub <- datS1to2[-c(8, 72, 85, 140, 152, 174, 219, 265, 284, 288, 294, 316, 324, 328, 338, 349, 432, 450, 456, 493),]
datS4to5.ub <- datS1to2[-c(56, 116, 170, 184, 211, 219, 221, 256, 257, 261, 309, 359, 376, 403, 432, 440, 459, 460, 474, 475),]
TF022.anovaDF.balanced <- function()
{
aov.fit <- anova(lm(y~lot:sample+sample:day+sample:day:run, datS1to2))
rm.fit <- anovaVCA(y~lot:sample+sample:day+sample:day:run, datS1to2)
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
TF023.anovaDF.unbalanced <- function()
{
aov.fit <- anova(lm(y~lot:sample+sample:day+sample:day:run-1, datS1to2))
rm.fit <- anovaVCA(y~lot:sample+sample:day+sample:day:run-1, datS1to2)
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
TF024.anovaDF.balanced <- function()
{
aov.fit <- anova(lm(y~lot:sample+sample:day+sample:day:run, datS1to2.ub))
rm.fit <- anovaVCA(y~lot:sample+sample:day+sample:day:run, datS1to2.ub)
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
TF025.anovaDF.unbalanced <- function()
{
aov.fit <- anova(lm(y~lot:sample+sample:day+sample:day:run-1, datS1to2.ub))
rm.fit <- anovaVCA(y~lot:sample+sample:day+sample:day:run-1, datS1to2.ub)
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
}
# checks whether the order of the model terms is kept
TF026.anovaDF.balanced.ordering <- function()
{
aov.fit <- anova(lm(terms(y~lot+lot:day+sample+sample:day, keep.order=TRUE), datS1to2.ub))
rm.fit <- anovaVCA(y~lot+lot:day+sample+sample:day, datS1to2.ub)
checkEquals(as.numeric(rm.fit$aov.tab[-1, "DF"]), as.numeric(aov.fit[,"Df"]))
aov.fit <- anova(lm(terms(y~lot+lot:day+sample+sample:day, keep.order=FALSE), datS1to2.ub)) # ordering not kept --> differences
rm.fit <- anovaVCA(y~lot+lot:day+sample+sample:day, datS1to2.ub)
checkTrue(any(as.numeric(rm.fit$aov.tab[-1, "DF"]) != as.numeric(aov.fit[,"Df"])))
}
# check numerical equivalence of sweep-based computation to reference results
TF027.check.sweep_vs_SAS_computation <- function()
{
SAS.res <- c(1.431413, 0.036431, 0.036123, 0.025228, 0.061443)
data(realData)
dat1 <- realData[realData$PID==1,]
fit.ws <- anovaVCA(y~lot/calibration/day/run, dat1)
R.res.sw <- round(as.numeric(fit.ws$aov.tab[-1, "VC"]), 6)
checkEquals(R.res.sw, SAS.res)
}
#####################################################################################
# define test-function which will not automatically be recognized by RUnit test-suite
placeholderFunction <- function()
{
#memory.limit(7500)
data(HugeData)
try(fit <- anovaVCA(y~VC1/VC2, HugeData), silent=TRUE)
if(class(fit) == "try-error")
{
cat("\n\n########################################################################\n")
cat( "\n'TF033.check.equality.HugeData' cannot be run due to memory limitations!")
cat( "\n########################################################################\n\n")
}
else
checkEquals(round(as.numeric(fit$aov.tab[-1, "VC"]), 4), c(5173.4411, 12268.7307, 13197.6746))
}
# in case RunAllTests.R defines T
if(runTF033.runit.anovaVCA.r) {
assign("TF033.check.equality.HugeData", placeholderFunction)
}
TF034.anovaVCA.zeroVariance <- function()
{
data(dataEP05A2_3)
dat1 <- dataEP05A2_3
dat1$y <- dat1[1,"y"]
dat1$cov <- rnorm(nrow(dat1),15,3)
fit1 <- anovaVCA(y~day, dat1)
checkEquals(as.numeric(fit1$aov.tab[,"VC"]), rep(0,3))
fit2 <- anovaVCA(y~day/run, dat1)
checkEquals(as.numeric(fit2$aov.tab[,"VC"]), rep(0,4))
}
TF035.anovaVCA.MisspecifiedModel <- function()
{
data(dataEP05A2_3)
checkException(anovaVCA(y~day, dataEP05A2_3[seq(1, 77, 4),]))
}
TF036.anovaVCA.byProcessing <- function()
{
# reproducible example taken from ticket 12818
set.seed(42)
dat <- expand.grid(group=c("group1", "group2"), day=rep(c("day1","day2"), times=3))
dat$value <- rnorm(nrow(dat))
dat <- subset(dat, !(group=="group2" & day=="day1")) #dataset with valid vca input for group 1 but invalid input for group 2
# VCA::anovaVCA(value~day, Data = subset(dat, group=="group1"), by="group") #valud result (as epcected)
# VCA::anovaVCA(value~day, Data = subset(dat, group=="group2"), by="group") #invalid result (as expected)
# should generate a warning if quiet=FALSE
checkTrue( tryCatch(
anovaVCA(value~day, Data = dat, by = "group", quiet=FALSE),
warning=function(w) TRUE) )
# should not generate a warning if quiet=TRUE
res <- anovaVCA(value~day, Data = dat, by = "group", quiet=TRUE)
checkTrue( class(res) == "list" &&
length(res) == 2 &&
all.equal(c("VCA", "try-error"), as.character(sapply(res, class))))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.