Comment supprimer un élément d'une liste?

275

J'ai une liste et je veux en supprimer un seul élément. Comment puis-je faire ceci?

J'ai essayé de chercher ce que je pense que les noms évidents pour cette fonction seraient dans le manuel de référence et je n'ai rien trouvé de approprié.

David Locke
la source
Dépend voulez-vous le supprimer par valeur par exemple "la valeur 5", ou par index / indices "l'élément à l'indice 5" ou "aux indices c (5: 6,10)? Si vous voulez supprimer par valeur et là sont des doublons, souhaitez-vous supprimer uniquement les doublons, première ou dernière occurrence, ou tous? Est-il garanti que la liste contient votre élément / index? Avons-nous besoin de gérer le cas où la liste est vide? Avons-nous besoin de assurez-vous que NA est passé (/ exclu)? La liste est-elle garantie d'être plate ou peut-elle être imbriquée? Combien de laters en profondeur?
smci
2
setdiff (myList, elementToRemove)
JStrahl

Réponses:

218

Je ne connais pas du tout R, mais un peu de recherche créative m'a conduit ici: http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

La citation clé de là:

Je ne trouve pas de documentation explicite pour R sur la façon de supprimer des éléments des listes, mais les essais et les erreurs me disent

myList [[5]] <- NULL

supprimera le 5ème élément et "fermera" le trou causé par la suppression de cet élément. Cela souffre les valeurs d'index, donc je dois être prudent lors de la suppression d'éléments. Je dois travailler de l'arrière de la liste vers l'avant.

Une réponse à ce message plus tard dans le fil de discussion déclare:

Pour supprimer un élément d'une liste, voir R FAQ 7.1

Et la section pertinente de la FAQ R dit:

... Ne définissez pas x [i] ou x [[i]] sur NULL, car cela supprimera le composant correspondant de la liste.

Ce qui semble vous dire (d'une manière un peu en arrière) comment supprimer un élément.

J'espère que cela vous aide, ou du moins vous mène dans la bonne direction.

Chad Birch
la source
5
Merci, mylist [i] <- NULL est exactement la façon de le faire.
David Locke
37
Cela n'a pas fonctionné pour moi. Je reçois:Error in list[length(list)] <- NULL : replacement has length zero
wfbarksdale
3
Le message de @Aleksandr Levchuck m'a montré que j'avais en fait affaire avec un vecteur et que je devais créer un nouvel objet
wfbarksdale
209

Si vous ne voulez pas modifier la liste sur place (par exemple pour passer la liste avec un élément supprimé à une fonction), vous pouvez utiliser l'indexation: les indices négatifs signifient "ne pas inclure cet élément".

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

x[-2];       # without 2nd element

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

De plus, les vecteurs d'index logique sont utiles:

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

Cela fonctionne également avec les cadres de données:

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
Florian Jenn
la source
5
Votre index logique ne fonctionne que si vous avez cet élément unique "b" dans un élément de liste. Vous ne pouvez pas supprimer, par exemple, de x$bcette façon, ni supprimer "b" d'un élément de liste x[[2]] = c("b","k") .
Carl Witthoft
En ce qui concerne les éléments uniques vs multiples: vous pouvez utiliser %in%pour tester contre plusieurs éléments. Je ne suis pas sûr de ce que vous entendez par «ne peut pas supprimer x $ b» - voulez-vous dire supprimer toute la colonne b?
Florian Jenn
30

Voici comment supprimer le dernier élément d'une liste dans R:

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

Si x peut être un vecteur, vous devrez créer un nouvel objet:

x <- c("a", "b", "c", "d", "e")
x <- x[-length(x)]
  • Travailler pour des listes et des vecteurs
Aleksandr Levchuk
la source
@krlmlr: au contraire, cette solution est plus générale que la réponse de Florian, car polymorphe dans le type de la collection.
Dan Barowy
@DanBarowy: J'avais tort: ​​cela semble être une synthèse de la réponse de Chad (la réponse acceptée) et de Florian ... Un bon bref résumé, cependant.
krlmlr
19

Suppression d'éléments Null d'une liste sur une seule ligne:

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

À votre santé

Sukhi
la source
2
Ce code se casse quand xest une liste vide. Utilisez compactde plyrcette tâche à la place.
Richie Cotton
De plus, s'il n'y a pas de valeurs nulles dans la liste, -(which(sapply(x,is.null),arr.ind=TRUE))renvoie named integer(0)ce qui supprimera entièrement cette ligne.
user3055034
18

Je voudrais ajouter que s'il s'agit d'une liste nommée, vous pouvez simplement l'utiliser within.

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

Vous pouvez donc écraser la liste d'origine

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

pour supprimer l'élément nommé ade la liste l.

Kim
la source
1
Faire plusieurswithin(l, rm(a, b))
Vlad
16

Si vous avez une liste nommée et que vous souhaitez supprimer un élément spécifique, vous pouvez essayer:

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

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

Cela fera une liste lstavec des éléments a, b, c. La deuxième ligne supprime l'élément baprès avoir vérifié qu'il existe (pour éviter le problème @hjv mentionné).

ou mieux:

lst$b <- NULL

De cette façon, ce n'est pas un problème d'essayer de supprimer un élément inexistant (par exemple lst$g <- NULL)

alko989
la source
10

Il y a le paquetage rlist ( http://cran.r-project.org/web/packages/rlist/index.html ) pour gérer différents types d'opérations de liste.

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

Résulte en:

# $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
user2030503
la source
comment supprimer les éléments python ou lang dans cet exemple?
Arthur Yip
9

Je ne sais pas si vous avez encore besoin d'une réponse à cette question, mais d'après mon expérience limitée (3 semaines en R autodidacte) avec R, l'utilisation du NULLdevoir est en fait incorrecte ou sous-optimale, surtout si vous mettez à jour dynamiquement une liste dans quelque chose comme une boucle for.

Pour être plus précis, en utilisant

myList[[5]] <- NULL

jettera l'erreur

myList [[5]] <- NULL: le remplacement a une longueur nulle

ou

plus d'éléments fournis qu'il n'y en a à remplacer

Ce que j'ai trouvé pour travailler de manière plus cohérente, c'est

myList <- myList[[-5]]
user2035799
la source
1
Bonne réponse! Cependant, je pense que les [[-5]]crochets devraient être simples, sinon vous ne désélectionnez que le contenu de cet élément de liste, pas l'élément lui-même. Eh bien, au moins l'utilisation de crochets doubles me donne cette erreur: "essayez de sélectionner plus d'un élément". Ce qui fonctionne pour moi était alors: myList <- myList[-5].
n1k31t4
4

Je voulais juste ajouter rapidement (car je ne l'ai vu dans aucune des réponses) que, pour une liste nommée, vous pouvez également le faire l["name"] <- NULL. Par exemple:

l <- list(a = 1, b = 2, cc = 3)
l['b'] <- NULL
Alexey Shiklomanov
la source
4

Utilisez -(signe négatif) avec la position de l'élément, par exemple si le 3e élément doit être retiré, utilisez-le commeyour_list[-3]

Contribution

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

Supprimer un seul élément de la liste

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

 # $b
 # [1] 3

 # $d
 # [1] "Hello"

 # $e
 [1] NA

Supprimer plusieurs éléments de la liste

 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
Sowmya S. Manian
la source
2

Dans le cas des listes nommées, je trouve ces fonctions d'aide utiles

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
DJJ
la source
0

Utilisation de lapply et 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))]
Ferroao
la source
-1

Que dis-tu de ça? Encore une fois, en utilisant des indices

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

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

ou

> m[-(length(m))]
[1] 1 2 3 4
RocketRon
la source
1
m est un vecteur, pas une liste
C8H10N4O2
1
La méthode fonctionne pour les listes, mais OP a de la chance et veut probablement plus de parenthèses:m[1:(length(m) - 1)]
Gregor Thomas
-1

si vous souhaitez éviter les index numériques, vous pouvez utiliser

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

pour supprimer des noms namea...namende a. cela fonctionne pour les listes

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

ainsi que pour les vecteurs

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

Vous pouvez utiliser which.

x<-c(1:5)
x
#[1] 1 2 3 4 5
x<-x[-which(x==4)]
x
#[1] 1 2 3 5
Pavidus
la source
20
Ce n'est pas unlist
GSee