Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
^cran-comments\.md$
^pull_request_template$
PULL_REQUEST_TEMPLATE.md
.claude
.idea
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
.Rproj.user
.DS_Store
.Rapp.history
.claude
.idea
19 changes: 14 additions & 5 deletions R/corDS.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
#' sum of squares of each variable. The first disclosure control checks that the number of variables is
#' not bigger than a percentage of the individual-level records (the allowed percentage is pre-specified
#' by the 'nfilter.glm'). The second disclosure control checks that none of them is dichotomous with a
#' level having fewer counts than the pre-specified 'nfilter.tab' threshold.
#' level having fewer counts than the pre-specified 'nfilter.tab' threshold. The list also includes
#' \code{class}, the class of the input object for client-side consistency checking.
#' @author Paul Burton, and Demetris Avraam for DataSHIELD Development Team
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#' @export
#'
corDS <- function(x=NULL, y=NULL){
Expand All @@ -27,14 +29,21 @@ corDS <- function(x=NULL, y=NULL){
nfilter.glm <- as.numeric(thr$nfilter.glm)
#############################################################

x.val <- eval(parse(text=x), envir = parent.frame())
x.val <- .loadServersideObject(x)
.checkClass(obj = x.val, obj_name = x, permitted_classes = c("numeric", "integer", "matrix", "data.frame"))

if (!is.null(y)){
y.val <- eval(parse(text=y), envir = parent.frame())
y.val <- .loadServersideObject(y)
.checkClass(obj = y.val, obj_name = y, permitted_classes = c("numeric", "integer", "matrix", "data.frame"))
}
else{
y.val <- NULL
}


if (is.null(y.val) && any(class(x.val) %in% c("numeric", "integer"))) {
stop("If x is a numeric vector, y must also be a numeric vector.", call. = FALSE)
}

# create a data frame for the variables
if (is.null(y.val)){
dataframe <- as.data.frame(x.val)
Expand Down Expand Up @@ -165,7 +174,7 @@ corDS <- function(x=NULL, y=NULL){

}

return(list(sums.of.products=sums.of.products, sums=sums, complete.counts=complete.counts, na.counts=na.counts, sums.of.squares=sums.of.squares))
return(list(sums.of.products=sums.of.products, sums=sums, complete.counts=complete.counts, na.counts=na.counts, sums.of.squares=sums.of.squares, class=class(x.val)))

}
# AGGREGATE FUNCTION
Expand Down
16 changes: 10 additions & 6 deletions R/corTestDS.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,28 @@
#' @param conf.level confidence level for the returned confidence interval. Currently
#' only used for the Pearson product moment correlation coefficient if there are at least
#' 4 complete pairs of observations.
#' @return the results of the correlation test.
#' @return a list with the results of the correlation test and \code{class}, the class of the
#' input object for client-side consistency checking.
#' @author Demetris Avraam, for DataSHIELD Development Team
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#' @export
#'
corTestDS <- function(x, y, method, exact, conf.level){

x.var <- eval(parse(text=x), envir = parent.frame())
y.var <- eval(parse(text=y), envir = parent.frame())
x.var <- .loadServersideObject(x)
.checkClass(obj = x.var, obj_name = x, permitted_classes = c("numeric", "integer"))
y.var <- .loadServersideObject(y)
.checkClass(obj = y.var, obj_name = y, permitted_classes = c("numeric", "integer"))

# get the number of pairwise complete cases
n <- sum(stats::complete.cases(x.var, y.var))

# runs a two-sided correlation test
corTest <- stats::cor.test(x=x.var, y=y.var, method=method, exact=exact, conf.level=conf.level)

out <- list(n, corTest)
names(out) <- c("Number of pairwise complete cases", "Correlation test")
out <- list(n, corTest, class = class(x.var))
names(out)[1:2] <- c("Number of pairwise complete cases", "Correlation test")

# return the results
return(out)

Expand Down
19 changes: 14 additions & 5 deletions R/covDS.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
#' of variables is not bigger than a percentage of the individual-level records (the allowed percentage is pre-specified
#' by the 'nfilter.glm'). The second disclosure control checks that none of them is dichotomous with a level having fewer
#' counts than the pre-specified 'nfilter.tab' threshold. If any of the input variables do not pass the disclosure
#' controls then all the output values are replaced with NAs.
#' controls then all the output values are replaced with NAs. The list also includes \code{class}, the class
#' of the input object for client-side consistency checking.
#' @author Amadou Gaye, Paul Burton, and Demetris Avraam for DataSHIELD Development Team
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#' @export
#'
covDS <- function(x=NULL, y=NULL, use=NULL){
Expand All @@ -36,14 +38,21 @@ covDS <- function(x=NULL, y=NULL, use=NULL){
#nfilter.string <- as.numeric(thr$nfilter.string)
#############################################################

x.val <- eval(parse(text=x), envir = parent.frame())
x.val <- .loadServersideObject(x)
.checkClass(obj = x.val, obj_name = x, permitted_classes = c("numeric", "integer", "matrix", "data.frame"))

if (!is.null(y)){
y.val <- eval(parse(text=y), envir = parent.frame())
y.val <- .loadServersideObject(y)
.checkClass(obj = y.val, obj_name = y, permitted_classes = c("numeric", "integer", "matrix", "data.frame"))
}
else{
y.val <- NULL
}


if (is.null(y.val) && any(class(x.val) %in% c("numeric", "integer"))) {
stop("If x is a numeric vector, y must also be a numeric vector.", call. = FALSE)
}

# create a data frame for the variables
if (is.null(y.val)){
dataframe <- as.data.frame(x.val)
Expand Down Expand Up @@ -298,7 +307,7 @@ covDS <- function(x=NULL, y=NULL, use=NULL){

}

return(list(sums.of.products=sums.of.products, sums=sums, complete.counts=complete.counts, na.counts=na.counts, errorMessage=errorMessage))
return(list(sums.of.products=sums.of.products, sums=sums, complete.counts=complete.counts, na.counts=na.counts, errorMessage=errorMessage, class=class(x.val)))

}
# AGGREGATE FUNCTION
Expand Down
15 changes: 7 additions & 8 deletions R/kurtosisDS1.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
#' @param method an integer between 1 and 3 selecting one of the algorithms for computing kurtosis
#' detailed in the headers of the client-side \code{ds.kurtosis} function.
#' @return a list including the kurtosis of the input numeric variable, the number of valid observations and
#' the study-side validity message.
#' \code{class}, the class of the input object for client-side consistency checking.
#' @author Demetris Avraam, for DataSHIELD Development Team
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#' @export
#'
kurtosisDS1 <- function (x, method){
Expand All @@ -19,8 +20,9 @@ kurtosisDS1 <- function (x, method){
nfilter.tab <- as.numeric(thr$nfilter.tab)
#############################################################

x <- eval(parse(text=x), envir = parent.frame())
x <- x[stats::complete.cases(x)]
x.val <- .loadServersideObject(x)
.checkClass(obj = x.val, obj_name = x, permitted_classes = c("numeric", "integer"))
x <- x.val[stats::complete.cases(x.val)]

if(length(x) < nfilter.tab){
kurtosis.out <- NA
Expand All @@ -32,19 +34,16 @@ kurtosisDS1 <- function (x, method){

if(method==1){
kurtosis.out <- g2
studysideMessage <- "VALID ANALYSIS"
}
if(method==2){
kurtosis.out <- ((length(x) + 1) * g2 + 6) * (length(x) - 1)/((length(x) - 2) * (length(x) - 3))
studysideMessage <- "VALID ANALYSIS"
}
if(method==3){
kurtosis.out <- (g2 + 3) * (1 - 1/length(x))^2 - 3
studysideMessage <- "VALID ANALYSIS"
}
}
out.obj <- list(Kurtosis=kurtosis.out, Nvalid=length(x), ValidityMessage=studysideMessage)

out.obj <- list(Kurtosis=kurtosis.out, Nvalid=length(x), class=class(x.val))
return(out.obj)

}
Expand Down
26 changes: 12 additions & 14 deletions R/kurtosisDS2.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
#' @param global.mean a numeric, the combined mean of the input variable across all studies.
#' @return a list including the sum of quartic differences between the values of x and the global mean of x across
#' all studies, the sum of squared differences between the values of x and the global mean of x across all studies,
#' the number of valid observations (i.e. the length of x after excluding missing values), and a validity message
#' indicating indicating a valid analysis if the number of valid observations are above the protection filter
#' nfilter.tab or invalid analysis otherwise.
#' the number of valid observations (i.e. the length of x after excluding missing values), and \code{class},
#' the class of the input object for client-side consistency checking.
#' @author Demetris Avraam, for DataSHIELD Development Team
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#' @export
#'
kurtosisDS2 <- function(x, global.mean){
Expand All @@ -23,20 +23,18 @@ kurtosisDS2 <- function(x, global.mean){
nfilter.tab <- as.numeric(thr$nfilter.tab)
#############################################################

x <- eval(parse(text=x), envir = parent.frame())
x <- x[stats::complete.cases(x)]
x.val <- .loadServersideObject(x)
.checkClass(obj = x.val, obj_name = x, permitted_classes = c("numeric", "integer"))
x <- x.val[stats::complete.cases(x.val)]

if(length(x) < nfilter.tab){
sum_quartics.out <- NA
sum_squares.out <- NA
studysideMessage <- "FAILED: Nvalid less than nfilter.tab"
}else{
sum_quartics.out <- sum((x - global.mean)^4)
sum_squares.out <- sum((x - global.mean)^2)
studysideMessage <- "VALID ANALYSIS"
stop("FAILED: Nvalid less than nfilter.tab", call. = FALSE)
}

out.obj <- list(Sum.quartics=sum_quartics.out, Sum.squares=sum_squares.out, Nvalid=length(x), ValidityMessage=studysideMessage)

sum_quartics.out <- sum((x - global.mean)^4)
sum_squares.out <- sum((x - global.mean)^2)

out.obj <- list(Sum.quartics=sum_quartics.out, Sum.squares=sum_squares.out, Nvalid=length(x), class=class(x.val))
return(out.obj)

}
Expand Down
17 changes: 10 additions & 7 deletions R/meanDS.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
#' @description Calculates the mean value.
#' @details if the length of input vector is less than the set filter
#' a missing value is returned.
#' @param xvect a vector
#' @return a numeric, the statistical mean
#' @param x a character string, the name of a numeric or integer vector
#' @return a list, with the estimated mean, the number of missing values, the number of
#' valid values, the total number of values, and \code{class}, the class of the input
#' object for client-side consistency checking
#' @author Gaye A, Burton PR
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#' @export
#'
meanDS <- function(xvect){
meanDS <- function(x){

#############################################################
# MODULE 1: CAPTURE THE nfilter SETTINGS
Expand All @@ -19,18 +22,18 @@ meanDS <- function(xvect){
#nfilter.string <- as.numeric(thr$nfilter.string)
#############################################################

xvect <- .loadServersideObject(x)
.checkClass(obj = xvect, obj_name = x, permitted_classes = c("numeric", "integer"))

out.mean <- mean(xvect, na.rm=TRUE)
out.numNa <- length(which(is.na(xvect)))
out.totN <- length(xvect)
out.validN <- out.totN-out.numNa
studysideMessage <- "VALID ANALYSIS"

if((out.validN != 0) && (out.validN < nfilter.tab)){
out.mean <- NA
stop("FAILED: Nvalid less than nfilter.tab", call. = FALSE)
}

out.obj <- list(EstimatedMean=out.mean,Nmissing=out.numNa,Nvalid=out.validN,Ntotal=out.totN,ValidityMessage=studysideMessage)
out.obj <- list(EstimatedMean=out.mean,Nmissing=out.numNa,Nvalid=out.validN,Ntotal=out.totN,class=class(xvect))
return(out.obj)

}
Expand Down
28 changes: 18 additions & 10 deletions R/meanSdGpDS.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
#' @description Server-side function called by ds.meanSdGp
#' @details Computes the mean and standard deviation across groups defined by one
#' factor
#' @param X a client-side supplied character string identifying the variable for which
#' @param x a client-side supplied character string identifying the variable for which
#' means/SDs are to be calculated
#' @param INDEX a client-side supplied character string identifying the factor across
#' @param index a client-side supplied character string identifying the factor across
#' which means/SDs are to be calculated
#' @author Burton PR
#'
#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#'
#' @return List with results from the group statistics
#' @export
#'
meanSdGpDS <- function (X, INDEX){
meanSdGpDS <- function (x, index){

#############################################################
# MODULE 1: CAPTURE THE nfilter SETTINGS
thr <- dsBase::listDisclosureSettingsDS()
Expand All @@ -23,9 +24,16 @@ meanSdGpDS <- function (X, INDEX){
#nfilter.string <- as.numeric(thr$nfilter.string)
#############################################################

X <- .loadServersideObject(x)
.checkClass(obj = X, obj_name = x, permitted_classes = c("numeric", "integer"))
INDEX <- .loadServersideObject(index)
.checkClass(obj = INDEX, obj_name = index, permitted_classes = c("factor", "character", "integer"))
x.class <- class(X)
index.class <- class(INDEX)

FUN.mean <- function(x) {mean(x,na.rm=TRUE)}
FUN.var <- function(x) {stats::var(x,na.rm=TRUE)}

#Strip missings from both X and INDEX
analysis.matrix<-cbind(X,INDEX)

Expand Down Expand Up @@ -114,17 +122,17 @@ meanSdGpDS <- function (X, INDEX){
{
table.valid<-TRUE
cell.count.warning<-paste0("All tables valid")
result<-list(table.valid,ansmat.mean,ansmat.sd,ansmat.count,Nvalid,Nmissing,Ntotal,cell.count.warning)
names(result)<-list("Table_valid","Mean_gp","StDev_gp", "N_gp","Nvalid","Nmissing","Ntotal","Message")
result<-list(table.valid,ansmat.mean,ansmat.sd,ansmat.count,Nvalid,Nmissing,Ntotal,cell.count.warning,x.class,index.class)
names(result)<-list("Table_valid","Mean_gp","StDev_gp", "N_gp","Nvalid","Nmissing","Ntotal","Message","class.x","class.index")
return(result)
}

if(any.invalid.cell)
{
table.valid<-FALSE
cell.count.warning<-paste0("At least one group has between 1 and ", nfilter.tab-1, " observations. Please change groups")
result<-list(table.valid,Nvalid,Nmissing,Ntotal,cell.count.warning)
names(result)<-list("Table_valid","Nvalid","Nmissing","Ntotal","Warning")
result<-list(table.valid,Nvalid,Nmissing,Ntotal,cell.count.warning,x.class,index.class)
names(result)<-list("Table_valid","Nvalid","Nmissing","Ntotal","Warning","class.x","class.index")
return(result)
}

Expand Down
26 changes: 16 additions & 10 deletions R/quantileMeanDS.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@
#' @title Generates quantiles and mean information without maximum and minimum
#' @description the probabilities 5%, 10%, 25%, 50%, 75%, 90%, 95% and the mean
#' are used to compute the corresponding quantiles.
#' @param xvect a numerical vector
#' @return a numeric vector that represents the sample quantiles
#' @param x a character string, the name of a numeric or integer vector
#' @return a list, with \code{quantiles}, a numeric vector that represents the sample
#' quantiles, and \code{class}, the class of the input object for client-side consistency
#' checking
#' @export
#' @author Burton, P.; Gaye, A.
#'
quantileMeanDS <- function (xvect) {

#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands
#'
quantileMeanDS <- function (x) {

xvect <- .loadServersideObject(x)
.checkClass(obj = xvect, obj_name = x, permitted_classes = c("numeric", "integer"))

# check if the input vector is valid (i.e. meets DataSHIELD criteria)
check <- isValidDS(xvect)

if(check){
# if the input vector is valid
# if the input vector is valid
qq <- stats::quantile(xvect,c(0.05,0.1,0.25,0.5,0.75,0.9,0.95), na.rm=TRUE)
mm <- mean(xvect,na.rm=TRUE)
quantile.obj <- c(qq, mm)
names(quantile.obj) <- c("5%","10%","25%","50%","75%","90%","95%","Mean")
names(quantile.obj) <- c("5%","10%","25%","50%","75%","90%","95%","Mean")
}else{
quantile.obj <- NA
}
return(quantile.obj)

return(list(quantiles = quantile.obj, class = class(xvect)))
}
Loading
Loading