2017-04-14 35 views
8

我有一个列表的列表,我希望子列表都具有相同的长度均衡列表中所有列表的长度?

即如果需要填充他们NA s所以他们都达到最长列表的长度。

模拟例如

list1 <- list(1, 2, 3) 
list2 <- list(1, 2, 3, 4, 5) 
list3 <- list(1, 2, 3, 4, 5, 6) 

list_lists <- list(list1, list2, list3) 

我最好的尝试尚未

max_length <- max(unlist(lapply (list_lists, FUN = length))) 
    # returns the length of the longest list 

list_lists <- lapply (list_lists, function (x) length (x) <- max_length) 

问题,那就是更换所有我的子列表到一个整数= MAX_LENGTH ...

list_lists [[1]] 
> [1] 6 

可以一些一个帮助?

回答

3

这里是你的代码修复。 该功能应返回x,而不是length(x)。 此外,我使用矢量,而不是清单清单。

list1 <- c(1, 2, 3) 
list2 <- c(1, 2, 3, 4, 5) 
list3 <- c(1, 2, 3, 4, 5, 6) 

list_lists <- list(list1, list2, list3) 

max_length <- max(unlist(lapply (list_lists, FUN = length))) 

list_lists <- lapply (list_lists, function (x) {length (x) <- max_length;x}) 

# [[1]] 
# [1] 1 2 3 NA NA NA 
# 
# [[2]] 
# [1] 1 2 3 4 5 NA 
# 
# [[3]] 
# [1] 1 2 3 4 5 6 

对于原有名单的结果是:

# [[1]] 
# [[1]][[1]] 
# [1] 1 
# 
# [[1]][[2]] 
# [1] 2 
# 
# [[1]][[3]] 
# [1] 3 
# 
# [[1]][[4]] 
# NULL 
# 
# [[1]][[5]] 
# NULL 
# 
# [[1]][[6]] 
# NULL 
# 
# 
# [[2]] 
# [[2]][[1]] 
# [1] 1 
# 
# [[2]][[2]] 
# [1] 2 
# 
# [[2]][[3]] 
# [1] 3 
# 
# [[2]][[4]] 
# [1] 4 
# 
# [[2]][[5]] 
# [1] 5 
# 
# [[2]][[6]] 
# NULL 
# 
# 
# [[3]] 
# [[3]][[1]] 
# [1] 1 
# 
# [[3]][[2]] 
# [1] 2 
# 
# [[3]][[3]] 
# [1] 3 
# 
# [[3]][[4]] 
# [1] 4 
# 
# [[3]][[5]] 
# [1] 5 
# 
# [[3]][[6]] 
# [1] 6 
+0

>为了清晰起见,我使用了矢量而不是列表。 –

+1

解决方案适用于列表和数值向量。 –

+1

正如@ 989所指出的那样,这个填充符用'NULL'而不是'NA' –

2

试试这个:

funJoeOld <- function(ls) { 
    list_length <- sapply(ls, length) 
    max_length <- max(list_length) 

    lapply(seq_along(ls), function(x) { 
     if (list_length[x] < max_length) { 
      c(ls[[x]], lapply(1:(max_length - list_length[x]), function(y) NA)) 
     } else { 
      ls[[x]] 
     } 
    }) 
} 

funJoeOld(list_lists)[[1]] 
[[1]] 
[1] 1 

[[2]] 
[1] 2 

[[3]] 
[1] 3 

[[4]] 
[1] NA 

[[5]] 
[1] NA 

[[6]] 
[1] NA 


编辑

只是想照亮R使用正确的工具如何让一个巨大的差异。虽然我的解决方案给出了正确的结果,但效率很低。通过用lengths以及lapply(1:z, function(y) NA)替换sapply(ls, length)as.list(rep(NA, z)),我们获得几乎15倍的加速。注意:

funJoeNew <- function(ls) { 
    list_length <- lengths(ls) 
    max_length <- max(list_length) 

    lapply(seq_along(ls), function(x) { 
     if (list_length[x] < max_length) { 
      c(ls[[x]], as.list(rep(NA, max_length - list_length[x]))) 
     } else { 
      ls[[x]] 
     } 
    }) 
} 

funAlistaire <- function(ls) { 
    Map(function(x, y){c(x, rep(NA, y))}, 
     ls, 
     max(lengths(ls)) - lengths(ls)) 
} 

fun989 <- function(ls) { 
    lapply(lapply(sapply(ls, unlist), "length<-", max(lengths(ls))), as.list) 
} 

比较平等

set.seed(123) 
samp_list <- lapply(sample(1000, replace = TRUE), function(x) {lapply(1:x, identity)}) 

## have to unlist as the NAs in 989 are of the integer 
## variety and the NAs in Joe/Alistaire are logical 
identical(sapply(fun989(samp_list), unlist), sapply(funJoeNew(samp_list), unlist)) 
[1] TRUE 

identical(funJoeNew(samp_list), funAlistaire(samp_list)) 
[1] TRUE 

基准

microbenchmark(funJoeOld(samp_list), funJoeNew(samp_list), fun989(samp_list), 
          funAlistaire(samp_list), times = 30, unit = "relative") 
Unit: relative 
       expr  min  lq  mean median  uq  max neval cld 
funJoeOld(samp_list) 21.825878 23.269846 17.434447 20.803035 18.851403 4.8056784 30 c 
funJoeNew(samp_list) 1.827741 1.841071 2.253294 1.667047 1.780324 2.4659653 30 ab 
    fun989(samp_list) 3.108230 3.563780 3.170320 3.790048 3.888632 0.9890681 30 b 
    funAli(samp_list) 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 30 a 

有两种拿走的题位置:

  1. apply功能家族有很好的理解,使得 简明高效的代码(可以在@ alistaire和@ 989的解决方案中看到)。
  2. 了解base R的细微差别,一般可以有相当大的后果
1

不知道你是你寻找这一点,你可以使用lengths功能列表:

list_lists <- list(unlist(list1), unlist(list2), unlist(list3)) 
list_lists1 <- lapply(list_lists, `length<-`, max(lengths(list_lists))) 
list_lists1 

    > list_lists1 
[[1]] 
[1] 1 2 3 NA NA NA 

[[2]] 
[1] 1 2 3 4 5 NA 

[[3]] 
[1] 1 2 3 4 5 6 

或为名单清单,你可以更进一步:

list_lists2 <- lapply(list_lists1,as.list) 


> list_lists2 
[[1]] 
[[1]][[1]] 
[1] 1 

[[1]][[2]] 
[1] 2 

[[1]][[3]] 
[1] 3 

[[1]][[4]] 
[1] NA 

[[1]][[5]] 
[1] NA 

[[1]][[6]] 
[1] NA 


[[2]] 
[[2]][[1]] 
[1] 1 

[[2]][[2]] 
[1] 2 

[[2]][[3]] 
[1] 3 

[[2]][[4]] 
[1] 4 

[[2]][[5]] 
[1] 5 

[[2]][[6]] 
[1] NA 


[[3]] 
[[3]][[1]] 
[1] 1 

[[3]][[2]] 
[1] 2 

[[3]][[3]] 
[1] 3 

[[3]][[4]] 
[1] 4 

[[3]][[5]] 
[1] 5 

[[3]][[6]] 
[1] 6 


> 
5

试试这个(其中ls是你的列表):

lapply(lapply(sapply(ls, unlist), "length<-", max(lengths(ls))), as.list) 
3

在列表中,NULL似乎比NA更合适,可加入vector

list_lists <- list(list(1, 2, 3), 
        list(1, 2, 3, 4, 5), 
        list(1, 2, 3, 4, 5, 6)) 


list_lists2 <- Map(function(x, y){c(x, vector('list', length = y))}, 
        list_lists, 
        max(lengths(list_lists)) - lengths(list_lists)) 

str(list_lists2) 
#> List of 3 
#> $ :List of 6 
#> ..$ : num 1 
#> ..$ : num 2 
#> ..$ : num 3 
#> ..$ : NULL 
#> ..$ : NULL 
#> ..$ : NULL 
#> $ :List of 6 
#> ..$ : num 1 
#> ..$ : num 2 
#> ..$ : num 3 
#> ..$ : num 4 
#> ..$ : num 5 
#> ..$ : NULL 
#> $ :List of 6 
#> ..$ : num 1 
#> ..$ : num 2 
#> ..$ : num 3 
#> ..$ : num 4 
#> ..$ : num 5 
#> ..$ : num 6 

如果你真的想NA S,只是改变vectorrep

list_lists3 <- Map(function(x, y){c(x, rep(NA, y))}, 
        list_lists, 
        max(lengths(list_lists)) - lengths(list_lists)) 

str(list_lists3) 
#> List of 3 
#> $ :List of 6 
#> ..$ : num 1 
#> ..$ : num 2 
#> ..$ : num 3 
#> ..$ : logi NA 
#> ..$ : logi NA 
#> ..$ : logi NA 
#> $ :List of 6 
#> ..$ : num 1 
#> ..$ : num 2 
#> ..$ : num 3 
#> ..$ : num 4 
#> ..$ : num 5 
#> ..$ : logi NA 
#> $ :List of 6 
#> ..$ : num 1 
#> ..$ : num 2 
#> ..$ : num 3 
#> ..$ : num 4 
#> ..$ : num 5 
#> ..$ : num 6 

注意,在后者的类型不匹配,除非你指定NA_real_或强迫NA匹配的x类型。

相关问题