Làm thế nào tôi có thể loại bỏ một yếu tố khỏi danh sách?


275

Tôi có một danh sách và tôi muốn xóa một yếu tố khỏi nó. Tôi có thể làm cái này như thế nào?

Tôi đã thử tìm kiếm những gì tôi nghĩ rằng tên rõ ràng cho chức năng này sẽ có trong hướng dẫn tham khảo và tôi không tìm thấy bất cứ điều gì phù hợp.


Bạn muốn loại bỏ nó theo giá trị, ví dụ: "giá trị 5" hoặc theo chỉ mục / chỉ số "phần tử tại chỉ mục 5" hoặc "tại các chỉ số c (5: 6,10)? Nếu bạn muốn xóa theo giá trị và ở đó là trùng lặp, sau đó bạn muốn xóa chỉ các trùng lặp, lần đầu tiên hoặc lần xuất hiện cuối cùng hay tất cả? Có đảm bảo rằng danh sách chứa thành phần / chỉ mục của bạn không? Chúng ta có cần xử lý trường hợp danh sách trống không? đảm bảo NA được thông qua (/ loại trừ)? Danh sách có được đảm bảo bằng phẳng hoặc có thể được lồng không? Có bao nhiêu độ
trễ

2
setdiff (myList, ElementToRemove)
JStrahl

Câu trả lời:


217

Tôi hoàn toàn không biết R, nhưng một chút googling sáng tạo đã dẫn tôi đến đây: http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

Trích dẫn chính từ đó:

Tôi không tìm thấy tài liệu rõ ràng cho R về cách xóa các phần tử khỏi danh sách, nhưng bản dùng thử và lỗi cho tôi biết

myList [[5]] <- NULL

sẽ loại bỏ phần tử thứ 5 và sau đó "đóng" lỗ do xóa phần tử đó. Điều đó đủ cho các giá trị chỉ số, vì vậy tôi phải cẩn thận trong việc loại bỏ các yếu tố. Tôi phải làm việc từ mặt sau của danh sách đến mặt trước.

Một phản hồi cho bài viết đó sau đó trong trạng thái chủ đề :

Để xóa một phần tử của danh sách, xem R FAQ 7.1

Và phần có liên quan của R FAQ nói:

... Không đặt x [i] hoặc x [[i]] thành NULL, vì điều này sẽ xóa thành phần tương ứng khỏi danh sách.

Điều này dường như cho bạn biết (theo cách hơi ngược) làm thế nào để loại bỏ một yếu tố.

Hy vọng rằng sẽ giúp, hoặc ít nhất là dẫn bạn đi đúng hướng.


5
Cảm ơn, danh sách của tôi [i] <- NULL chính xác là cách để làm điều đó.
David Locke

37
Điều này đã không làm việc cho tôi. Tôi nhận được:Error in list[length(list)] <- NULL : replacement has length zero
wfbarksdale

3
Bài đăng của @Aleksandr Levchuck cho tôi thấy rằng tôi thực sự đang xử lý một vectơ và cần thiết để tạo một đối tượng mới
wfbarksdale

209

Nếu bạn không muốn sửa đổi danh sách tại chỗ (ví dụ: để chuyển danh sách có phần tử bị xóa sang hàm), bạn có thể sử dụng lập chỉ mục: chỉ số phủ định có nghĩa là "không bao gồm phần tử này".

x <- list("a", "b", "c", "d", "e"); # example list

x[-2];       # without 2nd element

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

Ngoài ra, vectơ chỉ số logic rất hữu ích:

x[x != "b"]; # without elements that are "b"

Điều này cũng hoạt động với dataframes:

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
Chỉ mục logic của bạn chỉ hoạt động nếu bạn có mục "b" đó trong một phần tử danh sách. Bạn không thể xóa, giả sử x$btheo cách đó và cũng không thể xóa "b" khỏi thành phần danh sách x[[2]] = c("b","k") .
Carl Witthoft

Về đơn so với nhiều mặt hàng: bạn có thể sử dụng %in%để thử nghiệm đối với nhiều mặt hàng. Tôi không chắc ý của bạn là gì bởi không thể xóa x $ b - bạn có nghĩa là xóa toàn bộ cột b?
Florian Jenn

30

Đây là cách loại bỏ phần tử cuối cùng của danh sách trong R:

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

Nếu x có thể là một vectơ thì bạn sẽ cần tạo một đối tượng mới:

x <- c("a", "b", "c", "d", "e")
x <- x[-length(x)]
  • Làm việc cho danh sáchvectơ

@krlmlr: ngược lại, giải pháp này tổng quát hơn câu trả lời của Florian, vì nó là đa hình trong loại bộ sưu tập.
Dan Barowy

@DanBarowy: Tôi đã sai: Dường như đây là tổng hợp câu trả lời của Chad (câu trả lời được chấp nhận) và ... Tuy nhiên, một bản tóm tắt ngắn gọn.
krlmlr

19

Xóa các phần tử Null khỏi danh sách trong một dòng:

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

Chúc mừng


2
Mã này phá vỡ khi xlà một danh sách trống. Sử dụng compacttừ plyrcho nhiệm vụ này thay thế.
Richie Cotton

Ngoài ra nếu không có null trong danh sách, -(which(sapply(x,is.null),arr.ind=TRUE))trả về named integer(0)sẽ bỏ hoàn toàn hàng đó.
dùng3055034

17

Tôi muốn thêm rằng nếu đó là một danh sách có tên, bạn có thể chỉ cần sử dụng within.

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

Vì vậy, bạn có thể ghi đè lên danh sách ban đầu

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

để loại bỏ phần tử có tên atrong danh sách l.


1
Để làm nhiềuwithin(l, rm(a, b))
Vlad

16

Nếu bạn có một danh sách được đặt tên và muốn xóa một yếu tố cụ thể, bạn có thể thử:

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

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

Điều này sẽ tạo ra một danh sách lstvới các yếu tố a, b, c. Dòng thứ hai loại bỏ phần tử bsau khi nó kiểm tra xem nó có tồn tại không (để tránh sự cố @hjv đã đề cập).

hoặc tốt hơn:

lst$b <- NULL

Bằng cách này, không có vấn đề gì khi cố gắng xóa phần tử không tồn tại (ví dụ lst$g <- NULL)


10

Có gói danh sách ( http://cran.r-project.org/web/packages/rlist/index.html ) để đối phó với các loại hoạt động danh sách khác nhau.

Ví dụ ( 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"))

Kết quả trong:

# $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

Làm thế nào người ta có thể loại bỏ các mục python hoặc lang trong ví dụ này?
Arthur Yip

9

Không biết bạn vẫn cần câu trả lời cho vấn đề này hay không nhưng tôi đã tìm thấy từ kinh nghiệm tự học R (có giá trị 3 tuần) của tôi với R rằng, sử dụng NULLbài tập thực sự sai hoặc không tối ưu, đặc biệt nếu bạn đang cập nhật động một danh sách trong một cái gì đó như một vòng lặp for.

Nói chính xác hơn, sử dụng

myList[[5]] <- NULL

sẽ ném lỗi

myList [[5]] <- NULL: thay thế có độ dài bằng không

hoặc là

nhiều yếu tố được cung cấp hơn là để thay thế

Những gì tôi tìm thấy để làm việc ổn định hơn là

myList <- myList[[-5]]

1
Câu trả lời tốt! Tuy nhiên, tôi nghĩ rằng [[-5]]nên là dấu ngoặc đơn, nếu không, bạn chỉ bỏ chọn nội dung của phần tử danh sách đó, không phải phần tử. Chà, ít nhất sử dụng dấu ngoặc vuông đôi cho tôi lỗi này: "cố gắng chọn nhiều hơn một phần tử". Những gì làm việc cho tôi là : myList <- myList[-5].
n1k31t4

4

Chỉ muốn nhanh chóng thêm (vì tôi không thấy nó trong bất kỳ câu trả lời nào) mà đối với một danh sách có tên, bạn cũng có thể làm l["name"] <- NULL. Ví dụ:

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

4

Sử dụng -(dấu âm) cùng với vị trí của phần tử, ví dụ nếu phần tử thứ 3 được loại bỏ, hãy sử dụng nó nhưyour_list[-3]

Đầu vào

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

Xóa phần tử đơn khỏi danh sách

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

 # $b
 # [1] 3

 # $d
 # [1] "Hello"

 # $e
 [1] NA

Xóa nhiều yếu tố khỏi danh sách

 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

Trong trường hợp danh sách được đặt tên, tôi thấy các hàm trợ giúp này hữu ích

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

Sử dụng lapply và 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

Còn cái này thì sao? Một lần nữa, sử dụng các chỉ số

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

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

hoặc là

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

1
m là một vectơ, không phải là một danh sách
C8H10N4O2

1
Phương pháp này hoạt động cho các danh sách, nhưng OP may mắn và có thể muốn có thêm dấu ngoặc đơn:m[1:(length(m) - 1)]
Gregor Thomas

-1

nếu bạn muốn tránh các chỉ số số, bạn có thể sử dụng

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

để xóa tên namea...namenkhỏi a. cái này hoạt động cho danh sách

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

cũng như cho các vectơ

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

-2

Bạn có thể sử dụng which.

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

20
Đó không phải làlist
GSee
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.