如何从列表中删除一个元素?

364

我有一个列表,想从中删除单个元素。如何做到这一点?

我试图在参考手册中查找我认为显而易见的函数名称,但没有找到合适的内容。


你想按值删除它吗,例如“值为5”,还是按索引/索引删除,例如“在索引5处的元素”或“在索引c(5:6,10)处的元素”?如果您想按值删除并且存在重复项,则您想要仅删除重复项、第一次出现、最后一次出现还是全部删除?列表中是否保证包含您的元素/索引?我们需要处理列表为空的情况吗?我们需要确保NA被传递(/排除)吗?列表保证是平面的还是可以嵌套的?有多少层深度? - smci
5
setdiff(myList,elementToRemove) - JStrahl
20个回答

294
如果你不想就地修改列表(例如,将删除元素后的列表传递给函数),你可以使用索引:负索引表示“不包括此元素”。
x <- list("a", "b", "c", "d", "e")  # example list

x[-2]        # without 2nd element

x[-c(2, 3)]  # without 2nd and 3rd

此外,逻辑索引向量也非常有用。
x[x != "b"]  # without elements that are "b"

这也适用于数据框架:
df <- data.frame(number = 1:5, name = letters[1:5])

df[df$name != "b", ]      # rows without "b"

df[df$number %% 2 == 1, ] # rows with odd numbers only

8
你的逻辑索引只在列表元素中有单个项目“b”时才有效。你不能以这种方式删除,比如说,x$b,也不能从列表元素x[[2]] = c("b","k")中删除“b”。 - Carl Witthoft
关于单个与多个项目:您可以使用%in%来测试多个项目。我不确定您所说的“无法删除x $ b”的意思 - 您是指删除整个列b吗? - Florian Jenn

251
我完全不了解R,但通过一些创意性的谷歌搜索,我找到了这里:http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html 其中的关键引用如下:
“我没有找到有关如何从列表中删除元素的R的明确文档,但是尝试和错误告诉我”
“myList[[5]] <- NULL”
“将删除第5个元素,然后“关闭”由删除该元素引起的空洞。这会打乱索引值,因此在删除元素时必须小心。我必须从列表的末尾向前工作。”
该线程稍后的回复表明:
“要删除列表中的元素,请参阅R FAQ 7.1”
R FAQ的相关部分则说明:
“...不要将x[i]或x[[i]]设置为NULL,因为这将从列表中删除相应的组件。”
这似乎(以某种反向的方式)告诉您如何删除元素。

8
谢谢,mylist[i] <- NULL 正是要做的方法。 - David Locke
47
这对我没有用。我得到了一个错误信息:Error in list[length(list)] <- NULL : replacement has length zero - wfbarksdale
5
@Aleksandr Levchuck的帖子让我意识到我实际上正在处理一个向量,并需要创建一个新对象。 - wfbarksdale
这是一个很好的快捷方式,但我认为使用 within 的 @Kim 的答案似乎是删除列表元素的“正确”方法,因为它允许使用字符字符串来标识列表元素,可以同时删除多个元素,并且不需要在原地进行。除了 OP 的问题是关于删除单个元素之外,我还错过了什么吗?谢谢。 - Josh

66

我想补充说明,如果这是一个命名列表,你可以直接使用within

l <- list(a = 1, b = 2)    
> within(l, rm(a))
$b
[1] 2

因此,您可以覆盖原始列表。

l <- within(l, rm(a)) 
从列表l中删除名为a的元素。

7
执行多个 within(l, rm(a, b)) - Vlad
5
要对一个字符向量进行多项操作:x <- c("a","b"); within(l,rm(list=x)) - José

40

以下是如何从 R 中删除一个列表的最后一个元素:

x <- list("a", "b", "c", "d", "e")
x[length(x)] <- NULL

如果x可能是一个向量,那么你需要创建一个新的对象:

x <- c("a", "b", "c", "d", "e")
x <- x[-length(x)]
  • 适用于列表向量

相反,这个解决方案比Florian的回答更通用,因为它在集合类型上是多态的。 - Dan Barowy
@DanBarowy:我错了:这似乎是Chad(被接受的答案)和Florian的综合... 不过是一个很好的简要总结。 - krlmlr

23

一行代码删除列表中的Null元素:

x = x[-(which(sapply(x, is.null), arr.ind=TRUE))]

干杯!


3
x 是一个空列表时,这段代码会出错。建议改用 plyr 包中的 compact 函数来完成这个任务。 - Richie Cotton
如果列表中没有空值,则 -(which(sapply(x,is.null),arr.ind=TRUE)) 返回 named integer(0),这将完全删除该行。 - user3055034

19

如果您有一个命名列表并想要删除特定元素,则可以尝试以下方法:

lst <- list(a = 1:4, b = 4:8, c = 8:10)

if("b" %in% names(lst)) lst <- lst[ - which(names(lst) == "b")]

这将创建一个名为lst的列表,其中包含abc元素。第二行在检查b存在的情况下删除它(以避免@hjv提到的问题)。

或者更好:

lst$b <- NULL

这样尝试删除不存在的元素就不是问题了 (例如,lst$g <- NULL)。


16

使用-(负号)以及元素的位置,例如如果要删除第3个元素,请将其用作your_list[-3]

输入

my_list <- list(a = 3, b = 3, c = 4, d = "Hello", e = NA)
my_list
# $`a`
# [1] 3

# $b
# [1] 3

# $c
# [1] 4

# $d
# [1] "Hello"

# $e
# [1] NA

从列表中删除单个元素

 my_list[-3]
 # $`a`
 # [1] 3

 # $b
 # [1] 3

 # $d
 # [1] "Hello"

 # $e
 [1] NA

从列表中删除多个元素

 my_list[c(-1,-3,-2)]
 # $`d`
 # [1] "Hello"

 # $e
 # [1] NA

 my_list[c(-3:-5)]
 # $`a`
 # [1] 3

 # $b
 # [1] 3

 my_list[-seq(1:2)]
 # $`c`
 # [1] 4

 # $d
 # [1] "Hello"

 # $e
 # [1] NA

11

有一个rlist包(http://cran.r-project.org/web/packages/rlist/index.html)可用于处理各种列表操作。

示例(http://cran.r-project.org/web/packages/rlist/vignettes/Filtering.html):

library(rlist)
devs <- 
  list(
    p1=list(name="Ken",age=24,
      interest=c("reading","music","movies"),
      lang=list(r=2,csharp=4,python=3)),
    p2=list(name="James",age=25,
      interest=c("sports","music"),
      lang=list(r=3,java=2,cpp=5)),
    p3=list(name="Penny",age=24,
      interest=c("movies","reading"),
      lang=list(r=1,cpp=4,python=2)))

list.remove(devs, c("p1","p2"))

结果为:

# $p3
# $p3$name
# [1] "Penny"
# 
# $p3$age
# [1] 24
# 
# $p3$interest
# [1] "movies"  "reading"
# 
# $p3$lang
# $p3$lang$r
# [1] 1
# 
# $p3$lang$cpp
# [1] 4
# 
# $p3$lang$python
# [1] 2

在这个例子中,如何删除Python或Lang项目? - Arthur Yip

9

我不知道你是否还需要对此问题的答案,但是从我有限的(3周的自学R)R经验中发现,在像for循环这样动态更新列表的情况下,使用NULL赋值实际上是错误或次优的。

更准确地说,使用

myList[[5]] <- NULL

将会抛出错误

myList[[5]] <- NULL:替换长度为零

或者

提供的元素数量超过要替换的元素数量

我发现更加稳定的做法是

myList <- myList[[-5]]

2
很好的回答!不过,我认为[[-5]]应该改成单方括号,否则你只是取消选择该列表元素的内容,而不是元素本身。至少使用双方括号会给我这个错误:“尝试选择多个元素”。对我有效的是:myList <- myList[-5] - n1k31t4

7

我想快速补充一下(因为我没有在任何答案中看到这个),对于命名列表,你也可以使用l["name"] <- NULL。例如:

l <- list(a = 1, b = 2, cc = 3)
l['b'] <- NULL

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