Looping over unique pairs of elements in a list in R

大憨熊 提交于 2020-12-30 04:44:31

问题


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 but convolve() accepts only two elements at a time, I wonder how to loop over the elements of the bb list such that all unique pairs in bb (in this example: bma1 & bma2; bma1 & bma3; bma2 & bma3) are entered into convolve()?

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!