在R中将列表元素赋值为NULL?

61

我发现这种行为很奇怪,想请更有经验的用户分享他们的想法和解决方法。 在R中运行以下代码示例:

sampleList <- list()
d<- data.frame(x1 = letters[1:10], x2 = 1:10, stringsAsFactors = FALSE)
for(i in 1:nrow(d)) {
        sampleList[[i]] <- d$x1[i]
}

print(sampleList[[1]])
#[1] "a"
print(sampleList[[2]])
#[1] "b"
print(sampleList[[3]])
#[1] "c"
print(length(sampleList))
#[1] 10

sampleList[[2]] <- NULL
print(length(sampleList))
#[1] 9
print(sampleList[[2]])
#[1] "c"
print(sampleList[[3]])
#[1] "d"
列表元素向上移动了。也许这是预期的,但我正在尝试实现一个函数,其中我合并列表的两个元素并删除一个元素。我基本上想失去那个列表索引或将其设为NULL。
是否有任何方法可以将其分配为NULL并且不看到上述行为?
感谢您的建议。

unlist 会对你有帮助吗? - Matt Bannert
1
你使用 R 的方式不正确-- 尝试实现更多的向量化操作,否则你的代码将会保持缓慢、丑陋和难以理解。 - mbq
5个回答

79

好问题。

请查看R-FAQ

在R中,如果x是一个列表,则x[i] <- NULL和x[[i]] <- NULL会从x中删除指定的元素。前者与S不兼容,在S中是无操作的。(请注意,可以使用x[i] <- list(NULL)将元素设置为NULL。)

考虑以下示例:

> t <- list(1,2,3,4)
> t[[3]] <- NULL          # removing 3'd element (with following shifting)
> t[2] <- list(NULL)      # setting 2'd element to NULL.
> t
[[1]]
[2] 1

[[2]]
NULL

[[3]]
[3] 4

更新:

正如R地狱的作者所评论的那样,处理NULL时可能会出现更微妙的情况。考虑代码的一般结构:

# x is some list(), now we want to process it.
> for (i in 1:n) x[[i]] <- some_function(...)

现在要注意的是,如果some_function()返回NULL,那么你可能不会得到想要的结果:某些元素将会消失。相反,你应该使用lapply函数。 看一下这个简单的例子:

> initial <- list(1,2,3,4)
> processed_by_for <- list(0,0,0,0)
> processed_by_lapply <- list(0,0,0,0)
> toy_function <- function(x) {if (x%%2==0) return(x) else return(NULL)}
> for (i in 1:4) processed_by_for[[i]] <- toy_function(initial[[i]])
> processed_by_lapply <- lapply(initial, toy_function)
> processed_by_for
  [[1]]
  [1] 0

  [[2]]
  [1] 2

  [[3]]
  NULL

  [[4]]
  [1] 4

> processed_by_lapply
  [[1]]
  NULL

  [[2]]
  [1] 2

  [[3]]
  NULL

  [[4]]
  [1] 4

18
这是《R地狱》中的8.1.55章节。http://www.burns-stat.com/pages/Tutor/R_inferno.pdf。 8.1.56章节则是它的更微妙版本。 - Patrick Burns
非常感谢您的详细解释。如何阅读手册并不忽略这些微妙之处!!! - harshsinghal

7
您的问题对我来说有些困惑。
将 null 赋值给一个现有对象,本质上是删除该对象(例如,如果您拥有一个数据框并希望删除特定列,则这非常有用)。这就是您所做的。但我无法确定您想要什么。您可以尝试:
sampleList[[2]] <- NA

如果你的意思是想要删除它,那么可以用NULL代替它。这就是为什么会出现“列表元素向上移动”的情况。


6
obj = list(x = "Some Value")
obj = c(obj,list(y=NULL)) #ADDING NEW VALUE
obj['x'] = list(NULL) #SETTING EXISTING VALUE
obj

4

如果你需要创建一个NULL值的列表,以便稍后可以使用值填充(例如数据框架),这里没有抱怨

B <-vector("list", 2) 

a <- iris[sample(nrow(iris), 10), ]
b <- iris[sample(nrow(iris), 10), ]
B[[1]]<-a 
B[[2]]<-b 

以上答案相似,但我认为这值得发布。


0
花了我一些时间才弄清楚这个有关列表的问题。我的解决方法是:
mylist[[i]][j] <- list(double())

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