如何从列表中删除元素?


275

我有一个列表,我想从中删除一个元素。我怎样才能做到这一点?

我已经尝试在参考手册中查找我认为该功能的明显名称,但没有找到合适的名称。


取决于您要按值(例如“值5”)还是按索引/索引“索引5处的元素”或“索引c(5:6,10)处”将其删除?是重复项,那么您是否要仅删除重复项,第一次出现或最后一次出现或全部删除?是否保证列表包含您的元素/索引?我们是否需要处理列表为空的情况?确保NA被通过(/排除)?列表是否保证是平坦的或可以嵌套?后来的深度是多少?
smci

2
setdiff(myList,elementToRemove)
JStrahl

Answers:


218

我一点也不了解R,但是一些创意性的搜索使我在这里: http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

从那里的关键报价:

我没有找到有关如何从列表中删除元素的R的明确文档,但是反复试验告诉我

myList [[5]] <-空

将删除第5个元素,然后“关闭”由删除该元素引起的孔。这样会降低索引值,因此在删除元素时必须小心。我必须从列表的背面到正面进行工作。

稍后在线程状态中对该帖子响应

有关删除列表元素的信息,请参见R FAQ 7.1

R FAQ相关部分说:

...请勿将x [i]或x [[i]]设置为NULL,因为这将从列表中删除相应的组件。

这似乎在告诉您(以某种倒退的方式)如何删除元素。

希望对您有所帮助,或至少会引导您朝正确的方向发展。


5
谢谢,mylist [i] <-NULL正是这样做的方法。
David Locke

37
这对我不起作用。我得到:Error in list[length(list)] <- NULL : replacement has length zero
wfbarksdale 2011年

3
@Aleksandr Levchuck的帖子告诉我,我实际上是在处理向量,需要创建一个新对象
wfbarksdale

209

如果您不想就地修改列表(例如,通过将元素删除的列表传递给函数),则可以使用索引:负索引表示“不包括该元素”。

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

4
仅当列表元素中具有单个项目“ b”时,逻辑索引才有效。不能这样说, x$b也不能从列表元素中删除“ b” x[[2]] = c("b","k")
卡尔·威索夫特'18

关于单个项目还是多个项目:您可以%in%用于针对多个项目进行测试。我不确定“无法删除x $ b”是什么意思–您是要删除整个列b吗?
弗洛里安·詹

30

这是删除R中列表的最后一个元素的方法:

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

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

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

@krlmlr:相反,此解决方案比Florian的回答更笼统,因为它在集合类型上是多态的。
Dan Barowy 2014年

@DanBarowy:我错了:这似乎是乍得的答案(公认的答案)和弗洛里安的答案的综合……虽然很好。
krlmlr 2014年

19

从单行列表中删除Null元素:

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

干杯


2
x为空列表时,此代码中断。请改用compactfrom来自plyr此任务。
Richie Cotton

同样,如果列表中没有空值,则-(which(sapply(x,is.null),arr.ind=TRUE))返回named integer(0),它将完全删除该行。
user3055034

17

我想补充一点,如果它是一个命名列表,则可以简单地使用within

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

这样您可以覆盖原始列表

l <- within(l, rm(a)) 

a从list中删除命名的元素l


1
做多个within(l, rm(a, b))
Vlad19's

16

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

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)就没有问题了


10

有一个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项目?
亚瑟·叶

9

不知道您是否仍然需要答案,但是从我有限的(3周的自我教学R)经验中我发现,使用NULL分配实际上是错误的或次优的,尤其是当您动态更新时一个类似for循环的列表。

更确切地说,使用

myList[[5]] <- NULL

会抛出错误

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

要么

提供的元素多于要替换的元素

我发现更一致地工作是

myList <- myList[[-5]]

1
好答案!但是,我认为[[-5]]应该是单个方括号,否则您将仅取消选择该列表元素的内容,而不是元素本身。好吧,至少使用双方括号会给我这个错误:“试图选择多个元素”。那么对我有用的是:myList <- myList[-5]
n1k31t4


4

-与元素的位置一起使用(负号),例如,如果要删除第三个元素,则将其用作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

2

对于命名列表,我发现那些辅助函数很有用

member <- function(list,names){
    ## return the elements of the list with the input names
    member..names <- names(list)
    index <- which(member..names %in% names)
    list[index]    
}


exclude <- function(list,names){
     ## return the elements of the list not belonging to names
     member..names <- names(list)
     index <- which(!(member..names %in% names))
    list[index]    
}  
aa <- structure(list(a = 1:10, b = 4:5, fruits = c("apple", "orange"
)), .Names = c("a", "b", "fruits"))

> aa
## $a
##  [1]  1  2  3  4  5  6  7  8  9 10

## $b
## [1] 4 5

## $fruits
## [1] "apple"  "orange"


> member(aa,"fruits")
## $fruits
## [1] "apple"  "orange"


> exclude(aa,"fruits")
## $a
##  [1]  1  2  3  4  5  6  7  8  9 10

## $b
## [1] 4 5

0

使用lapply和grep:

lst <- list(a = 1:4, b = 4:8, c = 8:10)
# say you want to remove a and c
toremove<-c("a","c")
lstnew<-lst[-unlist(lapply(toremove, function(x) grep(x, names(lst)) ) ) ]
#or
pattern<-"a|c"
lstnew<-lst[-grep(pattern, names(lst))]

-1

这个怎么样?同样,使用索引

> m <- c(1:5)
> m
[1] 1 2 3 4 5

> m[1:length(m)-1]
[1] 1 2 3 4

要么

> m[-(length(m))]
[1] 1 2 3 4

1
m是向量,而不是列表
C8H10N4O2

1
该方法确实适用于列表,但是OP很幸运,可能还需要更多括号:m[1:(length(m) - 1)]
Gregor Thomas

-1

如果您想避免使用数字索引,可以使用

a <- setdiff(names(a),c("name1", ..., "namen"))

删除名字namea...namen从。这适用于列表

> l <- list(a=1,b=2)
> l[setdiff(names(l),"a")]
$b
[1] 2

以及向量

> v <- c(a=1,b=2)
> v[setdiff(names(v),"a")]
b 
2

-2

您可以使用which

x<-c(1:5)
x
#[1] 1 2 3 4 5
x<-x[-which(x==4)]
x
#[1] 1 2 3 5

20
那不是list
GSee
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.