¿Cómo puedo eliminar un elemento de una lista?

275

Tengo una lista y quiero eliminar un solo elemento de ella. ¿Cómo puedo hacer esto?

He intentado buscar lo que creo que los nombres obvios para esta función estarían en el manual de referencia y no he encontrado nada apropiado.

David Locke
fuente
Depende de si desea eliminarlo por valor, por ejemplo, "el valor 5", o por índice / índices "el elemento en el índice 5" o "en los índices c (5: 6,10)? Si desea eliminar por valor y allí son duplicados, entonces ¿desea eliminar solo los duplicados, la primera o la última aparición, o todos? ¿Se garantiza que la lista contiene su elemento / índice? ¿Necesitamos manejar el caso donde la lista está vacía? ¿Necesitamos se pasa a asegurar NA (/ excluido) es la lista garantiza que sea plana o puede estar anidada ¿Cuántas los laters profunda???
SMCI
2
setdiff (myList, elementToRemove)
JStrahl

Respuestas:

218

No sé R en absoluto, pero un poco de búsqueda creativa en Google me llevó aquí: http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

La cita clave a partir de ahí:

No encuentro documentación explícita para R sobre cómo eliminar elementos de las listas, pero la prueba y el error me dicen

myList [[5]] <- NULL

eliminará el quinto elemento y luego "cerrará" el agujero causado por la eliminación de ese elemento. Eso sufre los valores del índice, así que tengo que tener cuidado al soltar elementos. Debo trabajar desde el final de la lista hasta el frente.

Una respuesta a esa publicación más adelante en el hilo dice:

Para eliminar un elemento de una lista, consulte R Preguntas frecuentes 7.1

Y la sección relevante de las preguntas frecuentes de R dice:

... No establezca x [i] o x [[i]] en NULL, ya que esto eliminará el componente correspondiente de la lista.

Lo que parece decirle (de una manera un tanto al revés) cómo eliminar un elemento.

Espero que ayude, o al menos lo guíe en la dirección correcta.

Abedul Chad
fuente
55
Gracias, mylist [i] <- NULL es exactamente la forma de hacerlo.
David Locke
37
Esto no funcionó para mí. Obtengo:Error in list[length(list)] <- NULL : replacement has length zero
wfbarksdale
3
La publicación de @Aleksandr Levchuck me mostró que en realidad estaba lidiando con un vector y que necesitaba crear un nuevo objeto
wfbarksdale
209

Si no desea modificar la lista en el lugar (por ejemplo, para pasar la lista con un elemento eliminado a una función), puede usar la indexación: los índices negativos significan "no incluir este elemento".

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

x[-2];       # without 2nd element

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

Además, los vectores de índice lógicos son útiles:

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

Esto también funciona con marcos de datos:

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
fuente
55
Su índice lógico solo funciona si tiene ese único elemento "b" en un elemento de la lista. No puede eliminar, por ejemplo, de x$besa manera, ni puede eliminar "b" de un elemento de la lista x[[2]] = c("b","k") .
Carl Witthoft
Con respecto a los elementos individuales versus múltiples: puede usar %in%para probar contra múltiples elementos. No estoy seguro de lo que quieres decir con "no se puede eliminar x $ b". ¿Quieres decir eliminar toda la columna b?
Florian Jenn
30

Así es como se elimina el último elemento de una lista en R:

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

Si x podría ser un vector, entonces necesitaría crear un nuevo objeto:

x <- c("a", "b", "c", "d", "e")
x <- x[-length(x)]
  • Trabaja para listas y vectores
Aleksandr Levchuk
fuente
@krlmlr: por el contrario, esta solución es más general que la respuesta de Florian, ya que es polimórfica en el tipo de colección.
Dan Barowy
@DanBarowy: Me equivoqué: esta parece ser una síntesis de la respuesta de Chad (la aceptada) y la de Florian ... Sin embargo, un buen resumen breve.
krlmlr
19

Eliminar elementos nulos de una lista en una sola línea:

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

Salud

Sukhi
fuente
2
Este código se rompe cuando xes una lista vacía. Utilice compactfrom plyrpara esta tarea en su lugar.
Richie Cotton
Además, si no hay valores nulos en la lista, -(which(sapply(x,is.null),arr.ind=TRUE))retornos named integer(0)que eliminarán esa fila por completo.
user3055034
18

Me gustaría agregar que si se trata de una lista con nombre , simplemente puede usar within.

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

Para que pueda sobrescribir la lista original

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

para eliminar el elemento nombrado ade la lista l.

Kim
fuente
1
Para hacer múltipleswithin(l, rm(a, b))
Vlad
16

Si tiene una lista con nombre y desea eliminar un elemento específico, puede intentar:

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

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

Esto hará una lista lstcon los elementos a, b, c. La segunda línea elimina el elemento bdespués de comprobar que existe (para evitar el problema mencionado por @hjv).

o mejor:

lst$b <- NULL

De esta manera, no es un problema intentar eliminar un elemento inexistente (por ejemplo lst$g <- NULL)

alko989
fuente
10

Existe el paquete rlist ( http://cran.r-project.org/web/packages/rlist/index.html ) para tratar varios tipos de operaciones de listas.

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

Resultados 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
usuario2030503
fuente
¿Cómo se pueden eliminar los elementos de Python o Lang en este ejemplo?
Arthur Yip
9

No sé si aún necesita una respuesta a esto, pero descubrí por mi experiencia limitada (3 semanas de autoaprendizaje R) con R que, el uso de la NULLtarea es realmente incorrecto o subóptimo, especialmente si está actualizando dinámicamente una lista en algo así como un bucle for.

Para ser más precisos, usando

myList[[5]] <- NULL

arrojará el error

myList [[5]] <- NULL: el reemplazo tiene longitud cero

o

más elementos suministrados de los que hay que reemplazar

Lo que encontré para trabajar más consistentemente es

myList <- myList[[-5]]
usuario2035799
fuente
1
¡Buena respuesta! Sin embargo, creo que [[-5]]deberían estar entre corchetes, de lo contrario, estará deseleccionando solo el contenido de ese elemento de la lista, no el elemento en sí. Bueno, al menos usar corchetes dobles me da este error: "intento de seleccionar más de un elemento". Lo que funciona para mí fue entonces: myList <- myList[-5].
n1k31t4
4

Solo quería agregar rápidamente (porque no lo vi en ninguna de las respuestas) que, para una lista con nombre, también puede hacer l["name"] <- NULL. Por ejemplo:

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

Use -(signo negativo) junto con la posición del elemento, por ejemplo, si se va a eliminar el tercer elemento, úselo comoyour_list[-3]

Entrada

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

Eliminar un solo elemento de la lista

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

 # $b
 # [1] 3

 # $d
 # [1] "Hello"

 # $e
 [1] NA

Eliminar múltiples elementos de la lista

 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
fuente
2

En el caso de las listas con nombre, encuentro útiles esas funciones auxiliares

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
fuente
0

Usando lapply y 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
fuente
-1

¿Qué tal esto? Nuevamente, usando índices

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

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

o

> m[-(length(m))]
[1] 1 2 3 4
RocketRon
fuente
1
m es un vector, no una lista
C8H10N4O2
1
El método funciona para las listas, pero OP tiene suerte y probablemente quiera más paréntesis:m[1:(length(m) - 1)]
Gregor Thomas
-1

si desea evitar índices numéricos, puede usar

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

para eliminar nombres namea...namende a. esto funciona para listas

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

así como para vectores

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

Puedes usar which.

x<-c(1:5)
x
#[1] 1 2 3 4 5
x<-x[-which(x==4)]
x
#[1] 1 2 3 5
Pavidus
fuente
20
Eso no es unlist
GSee