Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
b6c4253
Merge pull request #341 from datashield/v6.3.1-dev
StuartWheater Jul 10, 2024
9dc690b
Update to documentation
StuartWheater Jul 10, 2024
8ff6924
Merge pull request #342 from StuartWheater/origin/v6.4.0-dev
StuartWheater Jul 10, 2024
8582866
Merge pull request #30 from StuartWheater/origin/v6.4.0-dev
StuartWheater Jul 10, 2024
ac427fa
Merge branch 'datashield:v6.4.0-dev' into v6.4.0-dev
StuartWheater Jul 10, 2024
1d1332f
Merge pull request #343 from StuartWheater/v6.4.0-dev
StuartWheater Jul 10, 2024
ca1aa36
Merge pull request #345 from datashield/v6.3.1-dev
StuartWheater Aug 8, 2024
580de03
Update docs
StuartWheater Nov 4, 2024
6909967
Merge pull request #352 from StuartWheater/v6.4.0-dev
StuartWheater Nov 4, 2024
ab0ad25
Merge pull request #353 from datashield/v6.4.0-dev
StuartWheater Nov 4, 2024
4548316
Merge pull request #354 from datashield/v6.4.0-dev
StuartWheater Nov 4, 2024
5290308
feat: added standardise function
timcadman Nov 5, 2024
8846c54
chore: added additional dependencies
timcadman Nov 5, 2024
2ffa318
test: added tests
timcadman Nov 5, 2024
c2ffbe9
docs: added docs for functions
timcadman Nov 5, 2024
fa1b631
Merge pull request #355 from datashield/v6.4.0-dev-feat/standardise-df
StuartWheater Nov 8, 2024
75ace3c
Changes from 6.3.1 and documents update
StuartWheater Nov 15, 2024
d9c3274
Merge pull request #365 from StuartWheater/v6.4.0-dev
StuartWheater Nov 15, 2024
d55127c
Restructure recode and dependencies
StuartWheater Jan 14, 2025
69899e4
Merge pull request #369 from StuartWheater/v6.4.0-dev
StuartWheater Jan 15, 2025
e16c6da
Merge pull request #33 from datashield/v6.4.0-dev
davraam Jan 17, 2025
b50d796
remove deprecated ds.subset/subsetDS and tidy up some code
davraam Jan 17, 2025
3ea7406
Merge pull request #370 from davraam/v6.4.0-dev
davraam Jan 17, 2025
57ae658
Merge pull request #34 from datashield/v6.4.0-dev
davraam Jan 24, 2025
675cc56
remove deprecated ds.subset and ds.subsetByClass
davraam Jan 24, 2025
9198bb3
Merge pull request #371 from davraam/v6.4.0-dev
davraam Jan 24, 2025
ce6c28e
Merge pull request #35 from datashield/v6.4.0-dev
davraam Jan 26, 2025
a7fccbe
feat: first commit asDataFrame
timcadman Feb 10, 2025
ac1937b
test: added tests for data frame
timcadman Feb 10, 2025
bf169db
docs: ran check
timcadman Feb 10, 2025
f7a96cb
Merge branch 'v6.4.0-dev' into v6.4.0-dev-feat/as-data-frame
StuartWheater Apr 15, 2025
5224c75
Merge pull request #372 from datashield/v6.4.0-dev-feat/as-data-frame
StuartWheater Apr 15, 2025
0c71f4d
Merge pull request #36 from datashield/v6.4.0-dev
davraam May 14, 2025
89837f0
improve code and increase test coverage
davraam May 14, 2025
35df3d2
Merge pull request #377 from davraam/v6.4.0-dev
davraam May 14, 2025
bdd3cd8
Merging with v6.3.3-dev plus document update
StuartWheater Jul 12, 2025
65e46e6
Merge pull request #396 from StuartWheater/v6.4.0-dev
StuartWheater Jul 12, 2025
55a7644
Added packages
StuartWheater Jul 13, 2025
c84372d
Remove 'tidyverse'
StuartWheater Jul 13, 2025
7891613
Merge branch 'datashield:v6.4.0-dev' into v6.4.0-dev
StuartWheater Jul 13, 2025
182041b
Merge pull request #397 from StuartWheater/v6.4.0-dev
StuartWheater Jul 13, 2025
220d586
Initial fixes due to update
StuartWheater Jul 13, 2025
e8840ac
Merge branch 'v6.4.0-dev' of github.com:StuartWheater/dsBase into v6.…
StuartWheater Jul 13, 2025
b2231ee
Merge of changes made to 'v6.3.5-dev'
StuartWheater Nov 28, 2025
e9663b9
update output call object to include actual formula
davraam Feb 4, 2026
e7bd556
Merge pull request #453 from davraam/v6.4.0-dev
davraam Feb 4, 2026
e672990
Merge branch 'datashield:v6.4.0-dev' into v6.4.0-dev
StuartWheater Feb 4, 2026
23019c0
New implementations (date, predict, round, scale)
Feb 5, 2026
95fd460
Documentations for new implementations (date, predict, round, scale)
Feb 5, 2026
c0ea149
Changes required to address devtools::check issues
StuartWheater Feb 6, 2026
e35a0ae
Update files
Feb 10, 2026
267c528
Merge branch 'v6.4.0-dev' of github.com:zeyzul/dsBase into zeyzul_6.4.0
StuartWheater Feb 10, 2026
03ca1cd
Update files
Feb 10, 2026
f658521
Update files
Feb 10, 2026
4b07310
Merge branch 'v6.4.0-dev' of github.com:zeyzul/dsBase into zeyzul_6.4.0
StuartWheater Feb 10, 2026
c4e2872
Update files
Feb 10, 2026
a1119e9
Merge branch 'v6.4.0-dev' of https://github.com/zeyzul/dsBase into v6…
Feb 10, 2026
f7c8a17
Merge branch 'v6.4.0-dev' of github.com:zeyzul/dsBase into zeyzul_6.4.0
StuartWheater Feb 10, 2026
85f78cf
Update with CRAN changes in v6.3.5
StuartWheater Feb 10, 2026
0db81a0
Updates needed to pass 'devtools'
StuartWheater Feb 10, 2026
8bd45f9
Further issue fixes
StuartWheater Feb 10, 2026
5205ed8
Merge pull request #445 from StuartWheater/v6.4.0-dev
StuartWheater Feb 10, 2026
bbeadd3
Update test
StuartWheater Feb 10, 2026
1789c99
Updated RoxygenNote to 8.0.0
StuartWheater Jun 12, 2026
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
14 changes: 10 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Description: Base 'DataSHIELD' functions for the server side. 'DataSHIELD' is a
been designed to only share non disclosive summary statistics, with built in automated output
checking based on statistical disclosure control. With data sites setting the threshold values for
the automated output checks. For more details, see 'citation("dsBase")'.
Version: 6.3.5.9000
Version: 6.4.0.9000
Authors@R: c(person(given = "Paul",
family = "Burton",
role = c("aut"),
Expand Down Expand Up @@ -71,10 +71,16 @@ Imports:
gamlss,
gamlss.dist,
mice,
childsds
childsds,
purrr,
tibble,
tidyselect,
stats,
lubridate
Suggests:
spelling,
testthat
RoxygenNote: 7.3.3
testthat,
tidytable
RoxygenNote: 8.0.0
Encoding: UTF-8
Language: en-GB
19 changes: 19 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export(BooleDS)
export(absDS)
export(asCharacterDS)
export(asDataFrameDS)
export(asDataMatrixDS)
export(asFactorDS1)
export(asFactorDS2)
Expand Down Expand Up @@ -35,13 +36,19 @@ export(dataFrameFillDS)
export(dataFrameSortDS)
export(dataFrameSubsetDS1)
export(dataFrameSubsetDS2)
export(dateDS)
export(densityGridDS)
export(dimDS)
export(dmtC2SDS)
export(elsplineDS)
export(extractQuantilesDS1)
export(extractQuantilesDS2)
export(fixClassDS)
export(fixColsDS)
export(fixLevelsDS)
export(gamlssDS)
export(getAllLevelsDS)
export(getClassAllColsDS)
export(getWGSRDS)
export(glmDS1)
export(glmDS2)
Expand Down Expand Up @@ -93,6 +100,7 @@ export(minMaxRandDS)
export(namesDS)
export(nsDS)
export(numNaDS)
export(predictDS)
export(qlsplineDS)
export(quantileMeanDS)
export(rBinomDS)
Expand All @@ -112,8 +120,10 @@ export(recodeValuesDS)
export(repDS)
export(replaceNaDS)
export(rmDS)
export(roundDS)
export(rowColCalcDS)
export(sampleDS)
export(scaleDS)
export(scatterPlotDS)
export(seqDS)
export(setSeedDS)
Expand All @@ -139,5 +149,14 @@ import(dplyr)
import(gamlss)
import(gamlss.dist)
import(mice)
importFrom(dplyr,"%>%")
importFrom(dplyr,across)
importFrom(dplyr,mutate)
importFrom(dplyr,select)
importFrom(gamlss.dist,pST3)
importFrom(gamlss.dist,qST3)
importFrom(purrr,map)
importFrom(purrr,set_names)
importFrom(tibble,as_tibble)
importFrom(tidyselect,all_of)
importFrom(tidyselect,peek_vars)
194 changes: 72 additions & 122 deletions R/BooleDS.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,127 +30,77 @@ BooleDS <- function(V1.name=NULL, V2.name=NULL, Boolean.operator.n=NULL, na.assi
# Check Permissive Privacy Control Level.
dsBase::checkPermissivePrivacyControlLevel(c('permissive', 'banana', 'carrot'))

#########################################################################
# DataSHIELD MODULE: CAPTURE THE nfilter SETTINGS #
thr <- dsBase::listDisclosureSettingsDS() #
#nfilter.tab<-as.numeric(thr$nfilter.tab) #
#nfilter.glm<-as.numeric(thr$nfilter.glm) #
#nfilter.subset<-as.numeric(thr$nfilter.subset) #
#nfilter.string<-as.numeric(thr$nfilter.string) #
#nfilter.stringShort<-as.numeric(thr$nfilter.stringShort) #
#nfilter.kNN<-as.numeric(thr$nfilter.kNN) #
#datashield.privacyLevel<-as.numeric(thr$datashield.privacyLevel) #
#########################################################################


#V1: numeric, factor or logical vector or scalar in .GlobalEnv
#V2: numeric, factor or logical vector or scalar in .GlobalEnv or client specified scalar with which to compare V1

#EVAL V1 and V2

##########CHECK NOT LONG SPECIFIED VECTOR##############

V1<-eval(parse(text=V1.name), envir = parent.frame())
V2<-eval(parse(text=V2.name), envir = parent.frame())


if(is.character(V1)){
studysideMessage<-"FAILED: V_i is character, please convert to numeric, factor or logical before running Boole"
stop(studysideMessage, call. = FALSE)
}

if(is.character(V2)){
studysideMessage<-"FAILED: V_ii is character, please convert to numeric, factor or logical before running Boole"
stop(studysideMessage, call. = FALSE)
}

V1.length<-length(V1)
V2.length<-length(V2)

if(!((V1.length == V2.length) | (V2.length==1))){
studysideMessage<-"FAILED: V_ii must either be of length one or of length equal to V_i"
stop(studysideMessage, call. = FALSE)
}

if(!is.numeric(Boolean.operator.n) | Boolean.operator.n==0){
studysideMessage<-"FAILED: Boolean.operator specified incorrectly. Must be: '==', '!=', '<', '<=', '>' or '>='"
stop(studysideMessage, call. = FALSE)
}

Boolean.operator<-" "
if(Boolean.operator.n==1) Boolean.operator<-"=="
if(Boolean.operator.n==2) Boolean.operator<-"!="
if(Boolean.operator.n==3) Boolean.operator<-"<"
if(Boolean.operator.n==4) Boolean.operator<-"<="
if(Boolean.operator.n==5) Boolean.operator<-">"
if(Boolean.operator.n==6) Boolean.operator<-">="


#APPLY BOOLEAN OPERATOR SPECIFIED

Boolean.indicator<-integer(length=V1.length)

#EVALUATE DIFFERENTLY IF V2 IS SAME LENGTH AS V1 OR OF LENGTH 1
if(V2.length==V1.length){
for(j in 1:V1.length){
command.text<-paste0(V1.name,"[",j,"] ",Boolean.operator," ",V2.name,"[",j,"]")
Boolean.indicator[j]<-eval(parse(text=command.text), envir = parent.frame())*1
}
}

if(V2.length==1){
for(j in 1:V1.length){
command.text<-paste0(V1.name,"[",j,"] ",Boolean.operator," ",V2.name)
Boolean.indicator[j]<-eval(parse(text=command.text), envir = parent.frame())*1
}
}


#BY DEFAULT NAs REMAIN AS NAs BUT IF YOU WANT TO YOU CAN FORCE THEM TO 1 OR 0 USING <na.assign.text> ARGUMENT

if(na.assign.text=="1"){
Boolean.indicator[is.na(Boolean.indicator)==1]<-1
}

if(na.assign.text=="0"){
Boolean.indicator[is.na(Boolean.indicator)==1]<-0
}


outobj.b<-as.logical(Boolean.indicator)
outobj<-Boolean.indicator



#COMMENT OUT THIS CODE BLOCK BECAUSE TESTS OF MINIMUM CELL SIZE SHOULD ALL BE
#ENACTED IN AGGREGATE FUNCTIONS. NO VECTOR IS DISCLOSIVE UNTIL IT RETURNS
#SOMETHING TO THE CLIENTSIDE. I AM LEAVING THIS COMMENTED BUT UNDELETED
#IN CASE WE LATER DECIDE TO CHANGE THIS STRATEGY
#CHECK OUTPUT VECTOR VALIDITY
# outobj.invalid<-0
#
# unique.values.outobj<-unique(outobj)
# unique.values.noNA.outobj<-unique.values.outobj[complete.cases(unique.values.outobj)]
#
# #Boolean and can therefore only be binary so check this:
# if(length(unique.values.noNA.outobj)>2) outobj.invalid<-1
#
# tabvar<-table(outobj,useNA="no")[table(outobj,useNA="no")>=1]
# min.category<-min(tabvar)
# if(min.category<nfilter.tab)outobj.invalid<-1
#
#TERMINATE CALCULATION IF outobj.invalid==1
#if(outobj.invalid==1){
# studysideMessage<-"FAILED: outobj has at least one category below table filter limit"
# stop(studysideMessage, call. = FALSE)
#}



if(numeric.output==TRUE){
Boole.obj<-outobj
}else{Boole.obj<-outobj.b}
return(Boole.obj)
V1 <- eval(parse(text=V1.name), envir = parent.frame())
V2 <- eval(parse(text=V2.name), envir = parent.frame())

if(is.character(V1)){
studysideMessage <- "FAILED: V1 is character, please convert to numeric, factor or logical before running Boole"
stop(studysideMessage, call. = FALSE)
}

if(is.character(V2)){
studysideMessage <- "FAILED: V2 is character, please convert to numeric, factor or logical before running Boole"
stop(studysideMessage, call. = FALSE)
}

V1.length <- length(V1)
V2.length <- length(V2)

if(!((V1.length == V2.length) | (V2.length==1))){
studysideMessage <- "FAILED: V2 must either be of length one or of length equal to V1"
stop(studysideMessage, call. = FALSE)
}

if(!(Boolean.operator.n %in% c(1,2,3,4,5,6))){
studysideMessage <- "FAILED: Boolean.operator specified incorrectly. Must be: '==', '!=', '<', '<=', '>' or '>='"
stop(studysideMessage, call. = FALSE)
}

Boolean.operator <- " "
if(Boolean.operator.n==1) Boolean.operator <- "=="
if(Boolean.operator.n==2) Boolean.operator <- "!="
if(Boolean.operator.n==3) Boolean.operator <- "<"
if(Boolean.operator.n==4) Boolean.operator <- "<="
if(Boolean.operator.n==5) Boolean.operator <- ">"
if(Boolean.operator.n==6) Boolean.operator <- ">="

# APPLY BOOLEAN OPERATOR SPECIFIED
Boolean.indicator <- integer(length=V1.length)

# EVALUATE DIFFERENTLY IF V2 IS SAME LENGTH AS V1 OR OF LENGTH 1
if(V2.length==V1.length){
for(j in 1:V1.length){
command.text <- paste0(V1.name,"[",j,"] ",Boolean.operator," ",V2.name,"[",j,"]")
Boolean.indicator[j]<-eval(parse(text=command.text), envir = parent.frame())*1
}
}

if(V2.length==1){
for(j in 1:V1.length){
command.text<-paste0(V1.name,"[",j,"] ",Boolean.operator," ",V2.name)
Boolean.indicator[j]<-eval(parse(text=command.text), envir = parent.frame())*1
}
}

# BY DEFAULT NAs REMAIN AS NAs BUT IF YOU WANT TO YOU CAN FORCE THEM TO 1 OR 0 USING <na.assign.text> ARGUMENT
if(na.assign.text=="1"){
Boolean.indicator[is.na(Boolean.indicator)==1]<-1
}

if(na.assign.text=="0"){
Boolean.indicator[is.na(Boolean.indicator)==1]<-0
}

outobj.b <- as.logical(Boolean.indicator)
outobj <- Boolean.indicator

if(numeric.output==TRUE){
Boole.obj <- outobj
}else{
Boole.obj <- outobj.b
}

return(Boole.obj)
}
#ASSIGN FUNCTION
# ASSIGN FUNCTION
# BooleDS
29 changes: 29 additions & 0 deletions R/asDataFrameDS.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#' @title asDataFrameDS a serverside assign function called by ds.asDataFrame
#' @description Coerces an R object into a matrix maintaining original
#' class for all columns in data.frames.
#' @details This assign function is based on the native R function \code{data.frame}
#' @param x.name the name of the input object to be coerced to class
#' data.frame. Must be specified in inverted commas. But this argument is
#' usually specified directly by <x.name> argument of the clientside function
#' \code{ds.asDataFrame}
#' @return the object specified by the <newobj> argument (or its default name
#' "asdataframe.newobj") which is written to the serverside. For further
#' details see help on the clientside function \code{ds.asDataMatrix}
#' @author Tim Cadman
#' @export
asDataFrameDS <- function (x.name){

if(is.character(x.name)){
x<-eval(parse(text=x.name), envir = parent.frame())

}else{
studysideMessage<-"ERROR: x.name must be specified as a character string"
stop(studysideMessage, call. = FALSE)
}

output <- data.frame(x)

return(output)
}
# ASSIGN FUNCTION
# asDataFrameDS
14 changes: 7 additions & 7 deletions R/asDataMatrixDS.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#' @title asDataMatrixDS a serverside assign function called by ds.asDataMatrix
#' @title asDataFrameDS a serverside assign function called by ds.asDataFrame
#' @description Coerces an R object into a matrix maintaining original
#' class for all columns in data.frames.
#' @details This assign function is based on the native R function \code{data.matrix}
Expand All @@ -8,13 +8,13 @@
#' the data.frame to a matrix but maintains all data columns in their
#' original class
#' @param x.name the name of the input object to be coerced to class
#' data.matrix. Must be specified in inverted commas. But this argument is
#' data.frame. Must be specified in inverted commas. But this argument is
#' usually specified directly by <x.name> argument of the clientside function
#' \code{ds.asDataMatrix}
#' \code{ds.asDataFrame}
#' @return the object specified by the <newobj> argument (or its default name
#' "asdatamatrix.newobj") which is written to the serverside. For further
#' "asdataframe.newobj") which is written to the serverside. For further
#' details see help on the clientside function \code{ds.asDataMatrix}
#' @author Paul Burton for DataSHIELD Development Team
#' @author Tim Cadman
#' @export
asDataMatrixDS <- function(x.name) {
if (is.character(x.name)) {
Expand All @@ -24,9 +24,9 @@ asDataMatrixDS <- function(x.name) {
stop(studysideMessage, call. = FALSE)
}

output <- data.matrix(x)
output <- data.frame(x)

return(output)
}
# ASSIGN FUNCTION
# asDataMatrixDS
# asDataFrameDS
Loading