【问题标题】:R: Replace values in nested listR:替换嵌套列表中的值
【发布时间】:2015-04-03 07:18:30
【问题描述】:

假设我们有一个嵌套列表:

test <- list(
  list(a = 1, b = 2, c = NULL),
  list(a = NULL, b = 2, c = 3))

如何将所有 NULL 值替换为 NA 以保留数据结构?这样当我尝试将数据框从列表中删除时,我最终不会丢失值/结构。如:

data.frame(matrix(unlist(test), nrow = 2, byrow = T))

  X1 X2
1  1  2
2  2  3

所需的输出类似于:

   X1 X2 X3
1  1  2  NA
2  NA 2  3

有建议这样做:

rbind.fill(lapply(test, function(f) {
  as.data.frame(Filter(Negate(is.null), f))
}))

这并不像我想要的那样矢量化。显然,尺寸和性能是一个问题。想到的一种解决方法是替换所有 NULL 值,因为它可以一次为整个数据帧完成。然后是unlist() 和matrix() 列表。

我不确定性能的提升(如果有的话)。也许好老的lapply() 并没有那么糟糕。

【问题讨论】:

  • 要替换整个列表中的 NULL 值,我们必须访问其中的元素。使用data.table 1.9.5,您可以在更新的代码中使用rbindlist(lapply(....), fill=TRUE)。
  • ..这需要 lapply 并且基本上以与原始答案相同的性能结束?
  • 我没有检查基准,但我认为 rbindlist 会更快。

标签: r


【解决方案1】:

我们可以使用stri_list2matrix

library(stringi)
m1 <- matrix(as.numeric(t(sapply(test, stri_list2matrix))), ncol=3)
m1
#    [,1] [,2] [,3]
#[1,]    1    2   NA
#[2,]   NA    2    3

这可以转换为data.frame

as.data.frame(m1)

【讨论】:

  • 只是好奇 - 是否有替换值的选项,而不是应用类似循环的函数?在data.table 包中还有其他选项,例如rbind.all... 它确实达到了结果,但路线并不完全符合我的预期。
  • 经过对不同案例的一些测试,这似乎是最通用的方法。
  • @A.Val。您是否使用此方法和rbindlist 尝试过一些基准测试
  • 如果我的嵌套列表有混合向量类型,这仍然有效吗? (我的列表中有双打、字符和列表...)
  • @MagO 不知道结构,很难说。你能发布一个新问题吗
【解决方案2】:

在here 找到以下答案,这是进入base R 的(有点扭曲)方法:

data.frame(matrix(as.numeric(as.character(unlist(test, recursive=F))), nrow=length(test), byrow=T))

#  X1 X2 X3
#1  1  2 NA
#2 NA  2  3

【讨论】:

  • @ColonelBeauvel,谢谢,尽管我在这里唯一的功劳是找到了正确的 SO 页面 ;-)
【解决方案3】:

如果您知道它只是一个两级列表,您可以使用两个循环测试 is.null 来循环遍历每个元素。

test <- list(
  list(a = 1, b = 2, c = NULL),
  list(a = NULL, b = 2, c = 3)
)

# get structure fyi
str(test)
# tells you the highest level list length
length(test)

for(i in 1:length(test))
    for(j in 1:length(test[[i]])) # second level
        if(is.null(test[[i]][[j]])) test[[i]][[j]]<-NA

编辑:那么当然做你之前在做的事情。

【讨论】:

  • 循环是一个明显的答案,我想不惜一切代价避免,也许我应该扩大我的问题有点澄清。
【解决方案4】:

通过dput 和dget 以及剪贴板的不同方法。

test <- list(
  list(a = 1, b = 2, c = NULL),
  list(a = NULL, b = 2, c = 3))

dput(test,file="clipboard-1024")
tmp=dget(textConnection(gsub("NULL","NA",readChar(con="clipboard-1024",file.info("clipboard-1024")$size))))
data.frame(matrix(unlist(tmp), nrow = 2, byrow = T))

#  X1 X2 X3
#1  1  2 NA
#2 NA  2  3

我不知道这有多快或多慢。

【讨论】:

    猜你喜欢
    • 2018-08-16
    • 2021-10-11
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多