将列表元素复制到填充NA列表元素

3
以下是我现在的代码。
set.seed(20)
test_list <- list("1" = matrix(rnorm(100), 10, 10), 
                  "2" = NA, 
                  "3" = NA, 
                  "4" = NA, 
                  "5" = NA, 
                  "6" = matrix(rnorm(100), 10, 10), 
                  "7" = NA, 
                  "8" = NA)

我希望找到一种方法,将不包含NA的列表元素内容复制到前一个元素中,以便填充每个列表元素。元素1-5将包含元素1中的矩阵,而6-8将包含元素6中的矩阵。如果使用NULL或类似内容作为应该被复制的元素(如果这有助于解决方案),则可以设置此问题。谢谢您提前的建议。
2个回答

5

is.na 可以以恰当的方式处理 "list",在这里需要返回 单个 NA 的情况下返回 TRUE:

is.na(test_list)
#    1     2     3     4     5     6     7     8 
#FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE

这种 is.na 的行为还可以有效地测试“list”,因为它避免了检查任何长度不等于1的元素。
基于此构建一个 NA locf 功能:
cummax((!is.na(test_list)) * seq_along(test_list))
#1 2 3 4 5 6 7 8 
#1 1 1 1 1 6 6 6 

我们对test_list进行了子集处理:

test_list[cummax((!is.na(test_list)) * seq_along(test_list))]

这非常令人愉快。可能需要重新设置名称。 - Rich Scriven
@RichScriven:..我不会想到一个功能会返回c(TRUE, FALSE)作为is.na(list(NA, c(NA, NA)))的用例.. :-). 你说的关于“names”的问题是对的,我把它保留原样是为了在可能有用的情况下打印输出哪个元素被传递。 - alexis_laz

3

您可以使用 Reduce 函数并选择 accumulate 模式(在处理非常大的数据时可能不起作用):

str(test_list)
#List of 8
# $ 1: num [1:10, 1:10] 1.163 -0.586 1.785 -1.333 -0.447 ...
# $ 2: logi NA
# $ 3: logi NA
# $ 4: logi NA
# $ 5: logi NA
# $ 6: num [1:10, 1:10] 0.548 -0.226 1.217 0.701 0.912 ...
# $ 7: logi NA
# $ 8: logi NA


fill_list <- Reduce(function(x, y) if(all(is.na(y))) x else y, test_list, acc = TRUE)

str(fill_list)
#List of 8
# $ : num [1:10, 1:10] 1.163 -0.586 1.785 -1.333 -0.447 ...
# $ : num [1:10, 1:10] 1.163 -0.586 1.785 -1.333 -0.447 ...
# $ : num [1:10, 1:10] 1.163 -0.586 1.785 -1.333 -0.447 ...
# $ : num [1:10, 1:10] 1.163 -0.586 1.785 -1.333 -0.447 ...
# $ : num [1:10, 1:10] 1.163 -0.586 1.785 -1.333 -0.447 ...
# $ : num [1:10, 1:10] 0.548 -0.226 1.217 0.701 0.912 ...
# $ : num [1:10, 1:10] 0.548 -0.226 1.217 0.701 0.912 ...
# $ : num [1:10, 1:10] 0.548 -0.226 1.217 0.701 0.912 ...

那是一个非常优雅的解决方案,谢谢。它至少可以在几千个元素上快速运行。 - Trevor Nederlof

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接