-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathds.boundedMeanDP.R
49 lines (41 loc) · 2.25 KB
/
ds.boundedMeanDP.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
source("R/utils.R")
#' @title Differentially private mean
#'
#' @param input_data the input vector
#' @param epsilon privacy budget
#' @param lower_bound lower bound for input values
#' @param upper_bound upper bound for input values
#' @param type a character string that represents the type of analysis to carry out.
#' This can be set as \code{'combine'}, \code{'split'} or \code{'both'}.
#' @param datasources a list of \code{\link{DSConnection-class}}
#' objects obtained after login. If the \code{datasources} argument is not specified
#' the default set of connections will be used: see \code{\link{datashield.connections_default}}.
#'
#' @return \code{ds.boundedMeanDP} returns to the client-side a list including: \cr
#' \code{Mean.by.Study} (private mean) and
#' \code{Ntotal} (sum of missing and valid observations)
#' separately for each study (if \code{type = split} or \code{type = both}). \cr
#' \code{Global.Mean} (private mean) and \code{Ntotal}
#' across all studies combined (if \code{type = combine} or \code{type = both}). \cr
#' \code{Nstudies}: number of studies being analysed.
#' @export
ds.boundedMeanDP <- function(input_data, epsilon, lower_bound, upper_bound, type="combine", datasources=NULL) {
if (is.null(datasources)) {
datasources <- DSI::datashield.connections_find()
}
if (!type %in% c("both", "split", "combine")) {
stop("Type must be one of 'both', 'split' or 'combine'")
}
mean.data <- callAggregationMethod(datasources, paste0("boundedMeanDP(", input_data, ", ", epsilon, ", ", lower_bound, ", ", upper_bound, ")"))
Nstudies <- length(datasources)
mean.mat <- matrix(as.numeric(unlist(mean.data)),nrow=Nstudies,byrow=TRUE)
mean.split <- mean.mat
dimnames(mean.split) <- c(list(names(mean.data), names(mean.data[[1]])))
mean.combine <- t(matrix(mean.mat[1,]))
mean.combine[1,1] <- ((t(matrix(mean.mat[,2]))%*%mean.mat[,1])/sum(mean.mat[,2]))
mean.combine[1,2] <- sum(mean.mat[,2])
dimnames(mean.combine) <- c(list("studiesCombined"),list(names(mean.data[[1]])))
if (type=="combine") return(list(Global.Mean=mean.combine,Nstudies=Nstudies))
if (type=="split") return(list(Mean.by.Study=mean.split,Nstudies=Nstudies))
if (type=="both") return(list(Mean.by.Study=mean.split,Global.Mean=mean.combine,Nstudies=Nstudies))
}