Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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