计算嵌套列表中的百分位数并在R中的数据框中输出

时间:2017-11-06 19:05:22

标签: r

我有一个参与者ID及其访问的嵌套列表。对于每次访问的每个参与者,测量10个变量10次,并且数据结构类似于R代码给出的模拟数据。对于参与者[[1]],我们有3次访问对应[[1]] [[1]],[[1]] [[2]]和[[1]] [[3]]。类似地,对于参与者2.我想在每次访问时为每个患者计算第25和第75个分位数,并将其存储在如下的长数据帧中。任何帮助表示赞赏。

set.seed(23)
ll <- lapply(1:2, FUN=function(i) replicate(3, matrix(rnorm(20), ncol=2), simplify=FALSE))


df<-data.frame(id=numeric(0),visit=numeric(0),col1.lower.ptile=numeric(0),col1.upper.ptile=numeric(0),col2.lower.ptile=numeric(0),col2.upper.ptile=numeric(0))

2 个答案:

答案 0 :(得分:2)

这是使用*apply函数的船载的基本R方法。

# use R rapply to get in the nested list and apply pull out the quantiles from  the columns
myRList <- rapply(ll, function(x) apply(x, 2, quantile, probs=c(.25, .75)), how="list")

rapply进入嵌套结构,apply按列拉出每个矩阵的分位数。例如,对于第一位患者,这将返回

myRList[1]
[[1]]
[[1]][[1]]
          [,1]       [,2]
25% 0.08238097 -0.5795292
75% 1.08541924  0.2856748

[[1]][[2]]
          [,1]       [,2]
25% -0.5572163 -0.9983007
75%  0.6329706  0.2190313

[[1]][[3]]
          [,1]       [,2]
25% -0.7966075 -0.4823147
75%  0.8378379  0.9661969

请注意,每个度量都在一列中,这就是R将数据存储在矩阵中的方式。因此,我们可以使用c将数据拉出到所需的格式,以去除矩阵类。要将其放入data.frame,请使用vapplyc从每个矩阵返回一个向量,使用lapply运行每个患者并返回一个向量列表。然后使用带有rbind.data.frame的do.call返回所需的data.frame。

dat <- cbind(id=rep(seq_along(ll), lengths(ll)),
             do.call(rbind.data.frame,
                     lapply(myRList, function(x) t(vapply(x, c, FUN.VALUE=numeric(4))))))

返回

dat
  id          V1         V2         V3        V4
1  1  0.08238097 1.08541924 -0.5795292 0.2856748
2  1 -0.55721633 0.63297057 -0.9983007 0.2190313
3  1 -0.79660754 0.83783794 -0.4823147 0.9661969
4  2 -1.07159858 0.02937252 -0.4670312 0.6528579
5  2 -0.44806361 0.52761202  0.1081107 1.1419628
6  2 -0.72854367 0.55997887 -0.1397759 0.6157683

如果您发现可以信任结果,我们可以将其简化为单个操作,如下所示。

dat <- cbind.data.frame(id=rep(seq_along(ll), lengths(ll)),
                        matrix(rapply(ll, function(x) apply(x, 2, quantile,
                                                            probs=c(.25, .75))), ncol=4))

然后根据需要设置变量名称。

答案 1 :(得分:1)

类似的解决方案,语法稍微简单:

with(new.env(), {

    # compute quantiles
    q <- lapply(ll, lapply, apply, 2, quantile, prob = c(0.25, 0.75))

    # simplify to array
    a <- simplify2array(unlist(q, recursive = FALSE))

    # return dataframe
    data.frame(id = rep(seq_along(ll), lengths(ll)),
               visit = unlist(lapply(lengths(ll), seq)),
               col1.lower.ptile = a[1, 1, ],
               col1.upper.ptile = a[2, 1, ],
               col2.lower.ptile = a[1, 2, ],
               col2.upper.ptile = a[2, 2, ])
}) -> df

df
#  id visit col1.lower.ptile col1.upper.ptile col2.lower.ptile col2.upper.ptile
#1  1     1      -0.18320744       0.42239195       -0.1075228       0.82134959
#2  1     2      -0.30466626       0.72310699       -1.1047154      -0.05519628
#3  1     3      -0.69026613       0.08553756       -0.4338562       0.34916939
#4  2     1       0.08335451       0.59375988       -1.1392453       0.45905958
#5  2     2      -0.81078650       0.23024319       -0.8819546       0.33385295
#6  2     3      -1.15689954       0.82117652       -0.2739212       0.61445726

请注意,我将整个内容放在with中,以便中间结果qa在结尾处自动销毁,但这并非绝对必要。