2009-03-16 17 views

Respuesta

157

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

La cita clave de allí:

I do not find explicit documentation for R on how to remove elements from lists, but trial and error tells me

myList[[5]] <- NULL

will remove the 5th element and then "close up" the hole caused by deletion of that element. That suffles the index values, So I have to be careful in dropping elements. I must work from the back of the list to the front.

A response to that post later in the thread estados:

For deleting an element of a list, see R FAQ 7.1

y relevant section of the R FAQ dice:

... Do not set x[i] or x[[i]] to NULL, because this will remove the corresponding component from the list.

Lo que parece decirte (de una manera un tanto hacia atrás) cómo eliminar un elemento.

Espero que ayude, o al menos lo lleve en la dirección correcta.

+2

Gracias, milista [i] <- nula es exactamente la manera de hacerlo. –

+27

Esto no funcionó para mí.Obtengo: 'Error en la lista [longitud (lista)] <- NULO: la sustitución tiene longitud cero ' – wbarksdale

+1

@ La publicación de Aleksandr Levchuck me mostró que en realidad estaba tratando con un vector y necesitaba crear un nuevo objeto – wbarksdale

148

Si no desea modificar la lista in situ (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 funciona con tramas de datos, también:

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

Su índice lógico solo funciona si tiene ese único elemento "b" en un elemento de lista. No se puede eliminar, digamos, 'x $ b' de esa manera, ni se puede eliminar" b "de un elemento de lista' x [[2]] = c ("b", "k") '. –

16

Extracción de elementos nulos de una lista en una sola línea:

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

Saludos

+2

Este código se rompe cuando 'x' es una lista vacía. Use 'compact' de' plyr' para esta tarea. –

+0

Además, si no hay valores nulos en la lista, '- (que (sapply (x, is.null), arr.ind = TRUE))' devuelve 'named entero (0)' que soltará esa fila por completo. – user3055034

24

Así es como el quitar el último elemento de una listaen I:

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

Si x puede ser un vector, entonces sería necesario crear un nuevo objeto:

x <- c("a", "b", "c", "d", "e") 
x <- x[-length(x)] 
  • trabajo para listas y vectores
+0

Un caso especial de la respuesta de Florian ... – krlmlr

+0

@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 la colección. –

+0

@DanBarowy: Estaba equivocado: parece ser una síntesis de la respuesta de Chad (la aceptada) y la de Florian ... Un buen resumen breve, sin embargo. – krlmlr

-2

Puede usar which.

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

Eso no es una 'lista' – GSee

10

Si usted tiene una lista con nombre y desea eliminar un elemento específico que puede probar:

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 con los elementos lsta, b, c. La segunda línea elimina el elemento b después de verificar que existe (para evitar el problema @hjv mencionado).

o mejor:

lst$b <- NULL 

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

6

Ahí está el paquete de RLIST (http://cran.r-project.org/web/packages/rlist/index.html) para hacer frente a diversos tipos de operaciones de lista.

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

Thx por su comentario. Agregué el código relevante. – user2030503

5

No sé si todavía necesita una respuesta a esto, pero he encontrado de mis limitados (3 semanas de auto -teaching R) experiencia con R que, usando la asignación NULL es realmente incorrecta o subóptima, especialmente si estás actualizando dinámicamente una lista en algo así como un for-loop.

Para ser más precisos, utilizando

myList[[5]] <- NULL 

lanzará el error

myList[[5]] <- NULL : replacement has length zero

o

more elements supplied than there are to replace

Lo que he encontrado para trabajar de manera más consistente es

myList <- myList[[-5]] 
+0

¡Buena respuesta! Sin embargo, creo que '[[-5]]' debe ser solo corchetes, de lo contrario está anulando la selección solo de los contenidos de ese elemento de la lista, no del 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]'. –

-1

¿Qué tal esto? Una vez más, utilizando í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 
+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: (longitud (m) - 1)]' – Gregor

0

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

l <- list(a = 1, b = 2, cc = 3) 
l['b'] <- NULL 
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))] 
1

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

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 
Cuestiones relacionadas