Bagaimana saya bisa menghapus elemen dari daftar?


275

Saya punya daftar dan saya ingin menghapus satu elemen dari itu. Bagaimana saya bisa melakukan ini?

Saya sudah mencoba mencari apa yang saya pikir nama yang jelas untuk fungsi ini akan ada di manual referensi dan saya belum menemukan sesuatu yang sesuai.


Tergantung apakah Anda ingin menghapusnya dengan nilai misalnya "nilai 5", atau dengan indeks / indeks "elemen pada indeks 5" atau "pada indeks c (5: 6,10)? Jika Anda ingin menghapus berdasarkan nilai dan ada adalah duplikat, lalu apakah Anda ingin menghapus hanya duplikat, kejadian pertama atau terakhir, atau semua? Apakah dijamin daftar berisi elemen / indeks Anda? Apakah kita perlu menangani kasus di mana daftar kosong? Apakah kita perlu memastikan NA dilewatkan (/ dikecualikan) Apakah daftar dijamin akan datar atau bisa bersarang Berapa banyak laters dalam???
smci

2
setdiff (myList, elementToRemove)
JStrahl

Jawaban:


218

Saya tidak tahu R sama sekali, tetapi sedikit googling kreatif membawa saya ke sini: http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

Kutipan kunci dari sana:

Saya tidak menemukan dokumentasi eksplisit untuk R tentang cara menghapus elemen dari daftar, tetapi coba-coba memberi tahu saya

myList [[5]] <- NULL

akan menghapus elemen ke-5 dan kemudian "menutup" lubang yang disebabkan oleh penghapusan elemen itu. Itu cukup dengan nilai indeks, Jadi saya harus berhati-hati dalam menjatuhkan elemen. Saya harus bekerja dari belakang daftar ke depan.

Sebuah respon yang posting kemudian di thread negara:

Untuk menghapus elemen daftar, lihat R FAQ 7.1

Dan bagian yang relevan dari FAQ R mengatakan:

... Jangan atur x [i] atau x [[i]] ke NULL, karena ini akan menghapus komponen yang sesuai dari daftar.

Yang sepertinya memberi tahu Anda (dengan cara yang agak mundur) cara menghapus elemen.

Harapan yang membantu, atau paling tidak menuntun Anda ke arah yang benar.


5
Terima kasih, mylist [i] <- NULL adalah cara tepat untuk melakukannya.
David Locke

37
Ini tidak berhasil untuk saya. Saya mendapatkan:Error in list[length(list)] <- NULL : replacement has length zero
wfbarksdale

3
@Alexandr posting Levchuck menunjukkan kepada saya bahwa saya benar-benar berurusan dengan vektor dan perlu membuat objek baru
wfbarksdale

209

Jika Anda tidak ingin mengubah daftar di tempat (misalnya untuk meneruskan daftar dengan elemen yang dihapus ke fungsi), Anda dapat menggunakan pengindeksan: indeks negatif berarti "jangan sertakan elemen ini".

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

x[-2];       # without 2nd element

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

Juga, vektor indeks logis berguna:

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

Ini juga berfungsi dengan kerangka data:

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

5
Indeks logis Anda hanya berfungsi jika Anda memiliki item tunggal "b" di elemen daftar. Anda tidak dapat menghapus, katakanlah, dengan x$bcara itu, Anda juga tidak dapat menghapus "b" dari elemen daftar x[[2]] = c("b","k") .
Carl Witthoft

Mengenai item tunggal vs banyak: Anda dapat menggunakan %in%untuk menguji beberapa item. Saya tidak yakin apa yang Anda maksud dengan “tidak dapat menghapus x $ b” - maksud Anda menghapus seluruh kolom b?
Florian Jenn

30

Berikut ini cara menghapus elemen terakhir dari daftar di R:

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

Jika x mungkin menjadi vektor maka Anda perlu membuat objek baru:

x <- c("a", "b", "c", "d", "e")
x <- x[-length(x)]
  • Berfungsi untuk daftar dan vektor

@ krlmlr: sebaliknya, solusi ini lebih umum daripada jawaban Florian, karena polimorfik dalam jenis koleksi.
Dan Barowy

@DanBarowy: Saya salah: Ini tampaknya merupakan sintesis dari jawaban Chad (yang diterima) dan Florian ... Namun, ringkasan singkat yang bagus.
krlmlr

19

Menghapus elemen Null dari daftar dalam satu baris:

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

Bersulang


2
Kode ini rusak ketika xdaftar kosong. Gunakan compactdari plyruntuk tugas ini sebagai gantinya.
Richie Cotton

Juga jika tidak ada null dalam daftar, -(which(sapply(x,is.null),arr.ind=TRUE))mengembalikan named integer(0)yang akan menjatuhkan baris itu seluruhnya.
user3055034

18

Saya ingin menambahkan bahwa jika itu adalah daftar nama yang dapat Anda gunakan within.

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

Jadi, Anda dapat menimpa daftar asli

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

untuk menghapus elemen bernama adari daftar l.


1
Untuk melakukan banyakwithin(l, rm(a, b))
Vlad

16

Jika Anda memiliki daftar bernama dan ingin menghapus elemen tertentu, Anda dapat mencoba:

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

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

Ini akan membuat daftar lstdengan unsur-unsur a, b, c. Baris kedua menghapus elemenb setelah memeriksa apakah ada (untuk menghindari masalah @hjv yang disebutkan).

atau lebih baik:

lst$b <- NULL

Dengan cara ini, bukan masalah untuk mencoba menghapus elemen yang tidak ada (mis. lst$g <- NULL)


10

Ada paket rlist ( http://cran.r-project.org/web/packages/rlist/index.html ) untuk menangani berbagai jenis operasi daftar.

Contoh ( 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"))

Hasil dalam:

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

bagaimana kita bisa menghapus item python atau lang dalam contoh ini?
Arthur Yip

9

Tidak tahu apakah Anda masih membutuhkan jawaban untuk ini, tetapi saya menemukan dari pengalaman R-mengajar 3 minggu saya yang terbatas dengan R itu, menggunakan NULL tugas sebenarnya salah atau kurang optimal terutama jika Anda memperbarui secara dinamis daftar dalam sesuatu seperti for-loop.

Untuk lebih tepatnya, gunakan

myList[[5]] <- NULL

akan melempar kesalahan

myList [[5]] <- NULL: penggantian memiliki panjang nol

atau

lebih banyak elemen yang disediakan daripada yang harus diganti

Apa yang saya temukan untuk bekerja lebih konsisten adalah

myList <- myList[[-5]]

1
Jawaban yang bagus! Namun, saya pikir [[-5]]harus kurung kotak tunggal, jika tidak, Anda hanya membatalkan pilihan elemen daftar itu, bukan elemen itu sendiri. Yah, setidaknya menggunakan tanda kurung ganda memberi saya kesalahan ini: "upaya untuk memilih lebih dari satu elemen". Karya apa yang bagi saya adalah maka: myList <- myList[-5].
n1k31t4

4

Hanya ingin menambahkan dengan cepat (karena saya tidak melihatnya di salah satu jawaban) yang, untuk daftar nama, Anda juga dapat melakukannya l["name"] <- NULL. Sebagai contoh:

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

4

Gunakan -(tanda Negatif) bersama dengan posisi elemen, misalnya jika elemen ke-3 harus dihapus gunakan sebagaiyour_list[-3]

Memasukkan

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

Hapus satu elemen dari daftar

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

 # $b
 # [1] 3

 # $d
 # [1] "Hello"

 # $e
 [1] NA

Hapus beberapa elemen dari daftar

 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

Dalam kasus daftar bernama saya menemukan fungsi pembantu itu berguna

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

Menggunakan lapply dan 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

Bagaimana dengan ini? Sekali lagi, menggunakan indeks

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

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

atau

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

1
m adalah vektor, bukan daftar
C8H10N4O2

1
Metode ini berfungsi untuk daftar, tetapi OP beruntung dan mungkin menginginkan beberapa tanda kurung lagi:m[1:(length(m) - 1)]
Gregor Thomas

-1

jika Anda ingin menghindari indeks numerik, Anda dapat menggunakan

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

untuk menghapus nama namea...namendari a. ini berfungsi untuk daftar

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

serta untuk vektor

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

-2

Anda bisa menggunakannya which.

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

20
Itu bukanlist
GSee
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.