问题
Suppose I have a list of objects called bb
. I want to pick each unique pair of elements in bb
and use them in some kind of function (called convolve
) as shown below:
## Below `bb` elements: `bma1` & `bma2` are used in the function:
con <- convolve(dens1= bb$bma1$dposterior,
dens2= function(x){bb$bma2$dposterior(-x)},
cdf1= bb$bma1$pposterior,
cdf2= function(x){1 - bb$bma2$pposterior(-x)})
con$quantile(c(0.025, 0.975))
Question:
bb
can have any number of elements butconvolve()
accepts only two elements at a time, I wonder how to loop over the elements of thebb
list such that all unique pairs inbb
(in this example:bma1
&bma2
;bma1
&bma3
;bma2 & bma3
) are entered intoconvolve()
?
Here is a reproducible code:
library("metafor")
library("bayesmeta")
dat <- escalc(measure="OR", ai=lh.le, bi=lh.re, ci=rh.le,
di=rh.re, data=dat.bourassa1996, add=1/2, to="all")
bma1 <- bayesmeta(dat[dat$sex=="combined",])
bma2 <- bayesmeta(dat[dat$sex=="male",])
bma3 <- bayesmeta(dat[dat$sex=="female",])
bb <- list(bma1 = bma1, bma2 = bma2, bma3 = bma3)
# The function (`source` if needed for full reproducibility)
source('https://raw.githubusercontent.com/rnorouzian/m/master/co.r')
con <- convolve(dens1= bb$bma1$dposterior,
dens2= function(x){bb$bma2$dposterior(-x)},
cdf1= bb$bma1$pposterior,
cdf2= function(x){1 - bb$bma2$pposterior(-x)})
con$quantile(c(0.025, 0.975))
回答1:
if bb
represents the data frames that must be combined in pairs, we can use gtools::combinations()
to generate a matrix of pairs and use it to drive calls to convolve()
.
library("metafor")
library("bayesmeta")
dat <- escalc(measure="OR", ai=lh.le, bi=lh.re, ci=rh.le,
di=rh.re, data=dat.bourassa1996, add=1/2, to="all")
bma1 <- bayesmeta(dat[dat$sex=="combined",])
bma2 <- bayesmeta(dat[dat$sex=="male",])
bma3 <- bayesmeta(dat[dat$sex=="female",])
bb <- list(bma1 = bma1, bma2 = bma2, bma3 = bma3)
library(gtools)
comboMatrix <- combinations(length(bb),2) # unique pairs of elements in bb
comboMatrix
At this point, comboMatrix
looks like:
> comboMatrix
[,1] [,2]
[1,] 1 2
[2,] 1 3
[3,] 2 3
We continue with code provided in the original post, wrapping the convolve()
function in lapply()
. We drive lapply()
with a vector representing the row dimension of comboMatrix
, which we will use to index into columns 1 and 2 for the pairs of elements from the list bb
for a comparison between two groups.
We use the [[
form of the extract operator instead of the $
form because we need to use variable substitution (i.e. the result of comboMatrix[a,1]
or comboMatrix[a,2]
) to extract the appropriate elements from the list bb
.
# The function (source if needed for full reproducibility)
source('https://raw.githubusercontent.com/rnorouzian/m/master/co.r')
conList <- lapply(1:nrow(comboMatrix),function(a){
con <- convolve(dens1 = bb[[comboMatrix[a,1]]]$dposterior,
dens2 = function(x){bb[[comboMatrix[a,2]]]$dposterior(-x)},
cdf1 = bb[[comboMatrix[a,1]]]$pposterior,
cdf2 = function(x){1 - bb[[comboMatrix[a,2]]]$pposterior(-x)})
con$quantile(c(0.025, 0.975))
})
At this point the conList
object contains the confidence intervals for each pair of data frames compared with convolve()
.
# name the output items
names(conList) <- unlist(lapply(1:nrow(comboMatrix),function(x){
paste("group",comboMatrix[x,1],"vs",comboMatrix[x,2])
}))
conList
When we print the object we see three sets of confidence intervals:
> conList
$`group 1 vs 2`
[1] -0.3564418 0.3685752
$`group 1 vs 3`
[1] -0.6560065 0.3069931
$`group 2 vs 3`
[1] -0.7298583 0.3589061
When we verify the results by running the code for the first comparison that was included with the original post, we see that the confidence intervals match.
con <- convolve(dens1= bb$bma1$dposterior,
dens2= function(x){bb$bma2$dposterior(-x)},
cdf1= bb$bma1$pposterior,
cdf2= function(x){1 - bb$bma2$pposterior(-x)})
con$quantile(c(0.025, 0.975))
...and the output:
> con$quantile(c(0.025, 0.975))
[1] -0.3564418 0.3685752
The second and third runs generate confidence intervals that match the results from the lapply()
version as well.
# group 1 vs. 3
con <- convolve(dens1= bb$bma1$dposterior,
dens2= function(x){bb$bma3$dposterior(-x)},
cdf1= bb$bma1$pposterior,
cdf2= function(x){1 - bb$bma3$pposterior(-x)})
con$quantile(c(0.025, 0.975))
# group 2 vs. 3
con <- convolve(dens1= bb$bma2$dposterior,
dens2= function(x){bb$bma3$dposterior(-x)},
cdf1= bb$bma2$pposterior,
cdf2= function(x){1 - bb$bma3$pposterior(-x)})
con$quantile(c(0.025, 0.975))
...and the output:
> # group 1 vs. 3
> con <- convolve(dens1= bb$bma1$dposterior,
+ dens2= function(x){bb$bma3$dposterior(-x)},
+ cdf1= bb$bma1$pposterior,
+ cdf2= function(x){1 - bb$bma3$pposterior(-x)})
>
> con$quantile(c(0.025, 0.975))
[1] -0.6560065 0.3069931
> # group 2 vs. 3
> con <- convolve(dens1= bb$bma2$dposterior,
+ dens2= function(x){bb$bma3$dposterior(-x)},
+ cdf1= bb$bma2$pposterior,
+ cdf2= function(x){1 - bb$bma3$pposterior(-x)})
>
> con$quantile(c(0.025, 0.975))
[1] -0.7298583 0.3589061
来源:https://stackoverflow.com/questions/65486367/looping-over-unique-pairs-of-elements-in-a-list-in-r