Jason Stout, M.D.
2014-May-24 13:58 UTC
[R] Conditional assignment of values to vector using ifelse
Hi R-users, I'm trying to simulate the outcome of several diagnostic tests with binary outcomes (positive/negative) and different performance characteristics. What I would like to generate is a dataframe with the first column representing the result of a "perfect" test, and different columns to the right simulating tests with different combinations of sensitivity and specificity. Here's the code I used to attempt this: x3<-rmvbin(10000,margprob=0.2) # results of perfect test, disease prevalence 20% sens1<-0.7 # sensitivity of test 1 spec1<-0.8 # specificity of test 1 sens2<-0.8 # sensitivity of test 2 spec2<-0.7 # specificity of test 2 funcsensspec<-function(x,sens,spec) { result<-ifelse(x==1,ifelse(runif(1,0,1)<=sens,1,0), ifelse(runif(1,0,1)<=spec,0,1)) return(result) } x4<-funcsensspec(x3,sens1,spec1) x5<-funcsensspec(x3,sens2,spec2) xx<-cbind(x3,x4,x5) The problem is that this is not behaving as I expected. Ideally I wanted R to randomly reassign values for each row with probability based on test characteristics, but what I think it is doing is generating one random value and using that to reassign the entire vector. Here is sample output:> head(xx,30)[,1] [,2] [,3] [1,] 0 1 0 [2,] 0 1 0 [3,] 0 1 0 [4,] 0 1 0 [5,] 0 1 0 [6,] 0 1 0 [7,] 1 1 1 [8,] 0 1 0 [9,] 1 1 1 [10,] 0 1 0 [11,] 1 1 1 [12,] 0 1 0 [13,] 0 1 0 [14,] 1 1 1 [15,] 0 1 0 [16,] 1 1 1 [17,] 0 1 0 [18,] 0 1 0 [19,] 0 1 0 [20,] 0 1 0 [21,] 0 1 0 [22,] 0 1 0 [23,] 0 1 0 [24,] 1 1 1 [25,] 0 1 0 [26,] 0 1 0 [27,] 0 1 0 [28,] 0 1 0 [29,] 0 1 0 [30,] 0 1 0 I know I could do this task by creating two actual vectors of random numbers and using them to assign probabilities, but am wondering if there is a simpler and more elegant way to accomplish the task (and this would provide some insight into how ifelse is working within this function). Thanks for any assistance. Jason Stout, MD, MHS Box 102359-DUMC Durham, NC 27710 FAX 919-681-7494 [[alternative HTML version deleted]]
David Winsemius
2014-May-24 15:35 UTC
[R] Conditional assignment of values to vector using ifelse
On May 24, 2014, at 6:58 AM, Jason Stout, M.D. wrote:> Hi R-users, > > I'm trying to simulate the outcome of several diagnostic tests with binary outcomes (positive/negative) and different performance characteristics. What I would like to generate is a dataframe with the first column representing the result of a "perfect" test, and different columns to the right simulating tests with different combinations of sensitivity and specificity. Here's the code I used to attempt this: > > x3<-rmvbin(10000,margprob=0.2) # results of perfect test, disease prevalence 20% > sens1<-0.7 # sensitivity of test 1 > spec1<-0.8 # specificity of test 1 > sens2<-0.8 # sensitivity of test 2 > spec2<-0.7 # specificity of test 2 > funcsensspec<-function(x,sens,spec) { > result<-ifelse(x==1,ifelse(runif(1,0,1)<=sens,1,0), > ifelse(runif(1,0,1)<=spec,0,1)) > return(result) > } > x4<-funcsensspec(x3,sens1,spec1) > x5<-funcsensspec(x3,sens2,spec2) > xx<-cbind(x3,x4,x5) > > The problem is that this is not behaving as I expected. Ideally I wanted R to randomly reassign values for each row with probability based on test characteristics, but what I think it is doing is generating one random value and using that to reassign the entire vector. Here is sample output:I think you need to re-examine your understanding of sensitivity and specificity. They are mappings from data to a continuous variable in [0,1] for varying choice of a continuously variable threshold, rather than a sampling parameter. The typical display of ROC curves is if no help to physicians because it obscures this relationship by failing to include annotations with the threshold values. -- David Winsemius, MD> > >> head(xx,30) > [,1] [,2] [,3] > [1,] 0 1 0 > [2,] 0 1 0 > [3,] 0 1 0 > [4,] 0 1 0 > [5,] 0 1 0 > [6,] 0 1 0 > [7,] 1 1 1 > [8,] 0 1 0 > [9,] 1 1 1 > [10,] 0 1 0 > [11,] 1 1 1 > [12,] 0 1 0 > [13,] 0 1 0 > [14,] 1 1 1 > [15,] 0 1 0 > [16,] 1 1 1 > [17,] 0 1 0 > [18,] 0 1 0 > [19,] 0 1 0 > [20,] 0 1 0 > [21,] 0 1 0 > [22,] 0 1 0 > [23,] 0 1 0 > [24,] 1 1 1 > [25,] 0 1 0 > [26,] 0 1 0 > [27,] 0 1 0 > [28,] 0 1 0 > [29,] 0 1 0 > [30,] 0 1 0 > > I know I could do this task by creating two actual vectors of random numbers and using them to assign probabilities, but am wondering if there is a simpler and more elegant way to accomplish the task (and this would provide some insight into how ifelse is working within this function). > > Thanks for any assistance. > > > Jason Stout, MD, MHS > Box 102359-DUMC > Durham, NC 27710 > FAX 919-681-7494 > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.David Winsemius Alameda, CA, USA