将复杂列表转换为数据框

问题描述 投票:1回答:2

对不起,如果这个问题之前已经制定,但我完全是新的,我尝试了其他帖子中的建议,但没有结果。例如我试过:

do.call("rbind", lapply(MET1, as.data.frame))

但它说:

as.data.frame.default(X [[i]],...)出错:无法将类“”mixEM“”强制转换为data.frame

我有这个列表(MET1)与7个元素(如下所示),我想将其转换为简化的数据框。数据框的每一行都需要是其中一个元素,我只需要lambdamusigma的信息。所以基本上是这样的:

           LAMBDA1    LAMBDA2    MU1    MU2    SIGMA1    SIGMA2
0102-A451    0.822      0.178   1711  10850       249     14986
0102-A453    0.813      0.187   1491   4031       108      6877
...

我的清单列表是:

str(MET1)
List of 7
$ 0102-A451:List of 9
..$ x         : num [1:178] 2088 1579 1638 1507 1862 ...
..$ lambda    : num [1:2] 0.822 0.178
..$ mu        : num [1:2] 1711 10850
..$ sigma     : num [1:2] 249 14986
..$ loglik    : num -1440
..$ posterior : num [1:178, 1:2] 0.991 0.997 0.997 0.996 0.996 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : NULL
.. .. ..$ : chr [1:2] "comp.1" "comp.2"
..$ all.loglik: num [1:16] -1703 -1518 -1472 -1450 -1442 ...
..$ restarts  : num 0
..$ ft        : chr "normalmixEM"
..- attr(*, "class")= chr "mixEM"
$ 0102-A453:List of 9
..$ x         : num [1:663] 1414 1506 1399 1423 1421 ...
..$ lambda    : num [1:2] 0.813 0.187
..$ mu        : num [1:2] 1491 4031
..$ sigma     : num [1:2] 108 6877
..$ loglik    : num -4847
..$ posterior : num [1:663, 1:2] 0.996 0.997 0.995 0.996 0.996 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : NULL
.. .. ..$ : chr [1:2] "comp.1" "comp.2"
..$ all.loglik: num [1:29] -5760 -4983 -4883 -4861 -4853 ...
..$ restarts  : num 0
..$ ft        : chr "normalmixEM"
..- attr(*, "class")= chr "mixEM"

...

r
2个回答
1
投票

这是一个tidyverse解决方案,首先我们提取列表的相关子集并将它们转换为tibble(还添加行号)。然后我们绑定tibbles并做标准的tidyr体操:

MET1 %>%
  map_dfr(~as_tibble(.x[c("lambda","mu","sigma")]) %>% rownames_to_column,
          .id="id") %>%
  gather(,,-rowname,-id) %>%
  unite(key,key,rowname) %>%
  spread(key,value)

# # A tibble: 2 x 7
#       id lambda_1 lambda_2  mu_1  mu_2 sigma_1 sigma_2
#  * <chr>    <dbl>    <dbl> <dbl> <dbl>   <dbl>   <dbl>
#  1     1    0.822    0.178  1711 10850     249   14986
#  2     2    0.813    0.187  1491  4031     108    6877

数据:

MET1 <- list(
  list(lambda = c(0.822, 0.178),
       mu     = c(1711, 10850),
       sigma  = c(249, 14986),
       something_else="whatever"),

  list(lambda = c(0.813, 0.187),
       mu     = c(1491, 4031),
       sigma  = c(108, 6877),
       something_else="whatever")
)

0
投票

Overview

使用lapply()MET1中的每个列表转换为wide data frame。然后,在rbind()中使用do.call()MET1中的所有列表折叠成一个数据框。感谢@Moody_Mudskipper创建可重现的数据。

# load data
MET1 <- 
    list(
        `0102-A451` = list(
            lambda = c(0.822, 0.178),
             mu     = c(1711, 10850),
             sigma  = c(249, 14986),
             something_else = "whatever"
            )
        , `0102-A453` = list(
            lambda = c(0.813, 0.187),
             mu     = c(1491, 4031),
             sigma  = c(108, 6877),
             something_else = "whatever"
            )
    )

# Transfrom MET1 
# so that each list is a wide data frame
MET1 <-
    lapply(
        X = MET1
        , FUN = function( i )
            data.frame(
                LAMBDA_1   = i[["lambda"]][1]
                , LAMBDA_2 = i[["lambda"]][2]
                , MU_1     = i[["mu"]][1]
                , MU_2     = i[["mu"]][2]
                , SIGMA_1  = i[["sigma"]][1]
                , SIGMA_2  = i[["sigma"]][2]
            )
    )

# now transfrom MET1
# into one data frame
# one row for each data frame within MET1
MET1 <-
    do.call(
        what = "rbind"
        , args = MET1
    )

# view results
MET1
#           LAMBDA_1 LAMBDA_2 MU_1  MU_2 SIGMA_1
# 0102-A451    0.822    0.178 1711 10850     249
# 0102-A453    0.813    0.187 1491  4031     108
#           SIGMA_2
# 0102-A451   14986
# 0102-A453    6877

# end of script #
© www.soinside.com 2019 - 2024. All rights reserved.