R语言 折叠一种特殊的列表结构

e3bfsja2  于 2023-10-13  发布在  其他
关注(0)|答案(2)|浏览(130)

我在R中有一个列表:

List of 4
 $ :List of 4
  ..$ prices  : num [1:5] -3.68 -1.5 1.71 1.75 -0.67
  ..$ lower   : num -2.92
  ..$ midpoint: num 1
  ..$ upper   : num 4.92
 $ :List of 4
  ..$ prices  : num [1:5] 0.15395 0.00512 0.02635 0.0388 0.17721
  ..$ lower   : num 0.00422
  ..$ midpoint: num 0.167
  ..$ upper   : num 0.615
 $ :List of 4
  ..$ prices  : num [1:5, 1:3] 0.841 0.514 1.443 1.096 0.913 ...
  ..$ lower   : num [1:3] -0.96 0.04 1.04
  ..$ midpoint: num [1:3] 1 2 3
  ..$ upper   : num [1:3] 2.96 3.96 4.96
 $ :List of 4
  ..$ prices  : num [1:5] 6.78 -0.28 2.565 0.553 14.275
  ..$ lower   : num -4.84
  ..$ midpoint: num 3
  ..$ upper   : num 10.8

上层列表中的第一项、第二项和第四项是它们应该的,但是第三项应该折叠成三个单独的项。所以最终的结果应该是这样的:

List of 4
 $ :List of 4
  ..$ prices  : num [1:5] -3.68 -1.5 1.71 1.75 -0.67
  ..$ lower   : num -2.92
  ..$ midpoint: num 1
  ..$ upper   : num 4.92
 $ :List of 4
  ..$ prices  : num [1:5] 0.15395 0.00512 0.02635 0.0388 0.17721
  ..$ lower   : num 0.00422
  ..$ midpoint: num 0.167
  ..$ upper   : num 0.615
 $ :List of 4
  ..$ prices  : num [1:5] 1 2 3 ... #This should be the FIRST column in the prices matrix of the third item in the original list, 1 2 3 just for the illustration purposes
  ..$ lower   : num -0.96
  ..$ midpoint: num 1
  ..$ upper   : num 2.96
 $ :List of 4
  ..$ prices  : num [1:5] 1 2 3 ... #This should be the SECOND column in the prices matrix of the third item in the original list, 1 2 3 ... just for the illustration purposes
  ..$ lower   : num -0.04
  ..$ midpoint: num 2
  ..$ upper   : num 3.96
 $ :List of 4
  ..$ prices  : num [1:5] 1 2 3 ... #This should be the THIRD column in the prices matrix of the third item in the original list, 1 2 3 ... just for the illustration purposes
  ..$ lower   : num 1.04
  ..$ midpoint: num 3
  ..$ upper   : num 4.96
 $ :List of 4
  ..$ prices  : num [1:5] 6.78 -0.28 2.565 0.553 14.275
  ..$ lower   : num -4.84
  ..$ midpoint: num 3
  ..$ upper   : num 10.8

有没有比在for循环中填充一个新列表更好的方法,这样:

newlist <- list()
newlist_i <- 1 #This index increases faster than i, whenever we encounter a "compressed" list item.
for(i in 1:length(origlist)) {
    if(!is.null(dim(origlist[[i]]$prices)) { #dim(vector) returns NULL
        for(j in 1:ncol(prices)) {
            newlist[[newlist_i+j-1]]$prices <- origlist[[i]]$prices[,j]
            newlist[[newlist_i+j-1]]$lower <- origlist[[i]]$lower[j]
            newlist[[newlist_i+j-1]]$midpoint <- origlist[[i]]$midpoint[j]
            newlist[[newlist_i+j-1]]$upper <- origlist[[i]]$upper[j]
        }
        newlist_i = newlist_i + dim(origlist[[i]]$prices) - 1
    } else {
        newlist[[i]] <- origlist[[i]]
        newlist_i = newlist_i + 1
    }
}

但是for循环看起来太丑陋和复杂了。有没有更好的方法来做到这一点?

cyvaqqii

cyvaqqii1#

您可以使用ModifyList + asplit + lapply使用来自@asd-tm的数据(到期时给予给予学分)

origlist <- md
lapply(origlist, \(x)
  if(length(dim(x$prices))) 
    do.call(Map, c(list,modifyList(x, list(prices = asplit(x$prices,2)))))
  else list(x)
)|>unlist(FALSE)

List of 6
 $ :List of 4
  ..$ prices  : num [1:5] 1.097 0.435 -0.326 1.149 0.994
  ..$ lower   : num 0.548
  ..$ midpoint: num 0.239
  ..$ upper   : num -0.628
 $ :List of 4
  ..$ prices  : num [1:5] 1.361 -0.6 2.187 1.533 -0.236
  ..$ lower   : num -1.03
  ..$ midpoint: num -0.71
  ..$ upper   : num 0.257
 $ :List of 4
  ..$ prices  : num [1:5(1d)] -0.247 -0.348 -0.952 -0.045 -0.785
  ..$ lower   : num -0.641
  ..$ midpoint: num 0.118
  ..$ upper   : num -0.256
 $ :List of 4
  ..$ prices  : num [1:5(1d)] -1.668 -0.38 0.919 -0.575 0.608
  ..$ lower   : num -0.85
  ..$ midpoint: num -0.947
  ..$ upper   : num 1.84
 $ :List of 4
  ..$ prices  : num [1:5(1d)] -1.6179 -0.0556 0.5194 0.3012 0.1057
  ..$ lower   : num -1.02
  ..$ midpoint: num -0.491
  ..$ upper   : num -0.652
 $ :List of 4
  ..$ prices  : num [1:5] 0.2354 0.078 -0.9619 -0.0713 1.4446
  ..$ lower   : num 0.452
  ..$ midpoint: num 0.0412
  ..$ upper   : num -0.422
uz75evzq

uz75evzq2#

我提供了以下基本的R解决方案:

do.call(rbind, 
        lapply(my_d, \(x){
          rbind(x$prices |> matrix(5), x$lower, x$midpoint, x$upper) |> t()
        }) 
) |> apply(MARGIN = 1, \(x) {
  list(
  prices = x[1:5],
  lower = x[6],
  midpoint = x[7],
  upper = x[8]
  )
})

或者如果prices的长度未知:

do.call(rbind, 
        lapply(my_d, \(x){
          cbind(x$prices |> matrix(length(x$lower), byrow = T), x$lower, x$midpoint, x$upper) 
        }) 
) |> apply(MARGIN = 1, \(x) {
  list(
    prices = x[1:(length(x) - 3)],
    lower = x[length(x) - 2],
    midpoint = x[length(x) - 1],
    upper = x[length(x)]
  )
})

两个脚本返回相同的输出:

[[1]]
[[1]]$prices
[1]  1.9196255  0.1770681  2.3306149 -0.8893725  0.7117880

[[1]]$lower
[1] 1.317551

[[1]]$midpoint
[1] 0.4215168

[[1]]$upper
[1] -0.8721538

[[2]]
[[2]]$prices
[1] -1.0674630  0.2179483 -2.2493795  0.2747926 -1.3451170

[[2]]$lower
[1] 1.444299

[[2]]$midpoint
[1] 1.212617

[[2]]$upper
[1] 0.1006223

[[3]]
[[3]]$prices
[1] -0.3124539  0.8772849  0.4090815  0.4909305 -0.9445474

[[3]]$lower
[1] -1.182347

[[3]]$midpoint
[1] -1.285585

[[3]]$upper
[1] -1.537147

[[4]]
[[4]]$prices
[1] -0.6609199  0.2626416 -0.2137965 -0.2261824 -0.8723562

[[4]]$lower
[1] -1.693114

[[4]]$midpoint
[1] -1.607736

[[4]]$upper
[1] -0.05325191

[[5]]
[[5]]$prices
[1] -0.8811282 -0.8030718  2.4720077 -0.1622402  0.9657835

[[5]]$lower
[1] -0.4743322

[[5]]$midpoint
[1] -0.9583107

[[5]]$upper
[1] 0.264364

[[6]]
[[6]]$prices
[1] -0.1863864  0.2615337 -0.3725853 -0.1614547  0.4465152

[[6]]$lower
[1] 0.03844349

[[6]]$midpoint
[1] -0.5716921

[[6]]$upper
[1] -1.85495

使用的数据:

my_d <- list(
  list(prices = rnorm(5),
       lower = rnorm(1),
       midpoint = rnorm(1),
       upper = rnorm(1)),
  list(prices = rnorm(5),
       lower = rnorm(1),
       midpoint = rnorm(1),
       upper = rnorm(1)),
  list(prices = matrix(rnorm(5*3), 5),
       lower = rnorm(3),
       midpoint = rnorm(3),
       upper = rnorm(3)),
  list(prices = rnorm(5),
       lower = rnorm(1),
       midpoint = rnorm(1),
       upper = rnorm(1))
)

相关问题