2010-05-20 13 views
5

Tengo una lista agradable, que se ve así:¿Cómo acceder a los elementos en una lista compleja?

tmp = NULL 
t = NULL 
tmp$resultitem$count = "1057230" 
tmp$resultitem$status = "Ok" 
tmp$resultitem$menu = "PubMed" 
tmp$resultitem$dbname = "pubmed" 
t$resultitem$count = "305215" 
t$resultitem$status = "Ok" 
t$resultitem$menu = "PMC" 
t$resultitem$dbname = "pmc" 
tmp = c(tmp, t) 
t = NULL 
t$resultitem$count = "1" 
t$resultitem$status = "Ok" 
t$resultitem$menu = "Journals" 
t$resultitem$dbname = "journals" 
tmp = c(tmp, t) 

que produce:

> str(tmp) 
List of 3 
$ resultitem:List of 4 
    ..$ count : chr "1057230" 
    ..$ status: chr "Ok" 
    ..$ menu : chr "PubMed" 
    ..$ dbname: chr "pubmed" 
$ resultitem:List of 4 
    ..$ count : chr "305215" 
    ..$ status: chr "Ok" 
    ..$ menu : chr "PMC" 
    ..$ dbname: chr "pmc" 
$ resultitem:List of 4 
    ..$ count : chr "1" 
    ..$ status: chr "Ok" 
    ..$ menu : chr "Journals" 
    ..$ dbname: chr "journals" 

Ahora quiero buscar a través de los elementos de cada resultitem. Quiero saber el dbname para cada base de datos, que tiene menos de 10 count (ejemplo). En este caso es muy fácil, ya que esta lista solo tiene 3 elementos, pero la lista real es un poco más larga.

Esto podría hacerse simplemente con un bucle for. Pero, ¿hay alguna manera de hacer esto con alguna otra función de R (como Rapply)? Mi problema con esas funciones de aplicación es que solo miran un elemento.

Si hago un grep para obtener todos los elementos dbname, no puedo obtener el recuento de cada elemento.

rapply(tmp, function(x) paste("Content: ", x))[grep("dbname", names(rapply(tmp, c)))]

¿Alguien tiene una idea mejor que un ciclo for?

+6

Perdóneme, pero ¿por qué está utilizando estas torpes estructuras de listas en lugar de un marco de datos? –

Respuesta

2

Si está completamente insiste en que debe hacerlo en una lista los siguientes voluntad trabajo para el presente caso.

x <- tmp[sapply(tmp, function(x){x$count>10})] 
str(x) 
(the list items you wanted) 

De manera más general, si desea utilizar realmente listas irregulares de esta manera se puede utilizar el mismo código, pero comprobar la presencia del elemento de primera

testForCount <- function(x) {if ('count' %in% names(x)) x$count>10 else FALSE} 
tmp[sapply (tmp, count)] 

Esto funcionará para los casos donde las listas no tienen la misma longitud que el presente caso. (Todavía creo que debería usar marcos de datos para la velocidad y la representación sensata de los datos).

+0

El problema con mis datos es que proviene de un servicio web. Y no es seguro que exista una columna. Si el servicio web cambia, el paquete R ya no funcionará. Incluso si la consulta cambia, las columnas pueden no ser las mismas que antes. Entonces decidí usar listas como representación de los resultados. Y ahora estoy buscando algunas maneras de manejar estas listas. Me ayudaste mucho, gracias. – Martin

+0

Creo que está diciendo que no puede estar seguro de que la celda exista en la consulta en particular. Está bien, solo NA esa célula. Si la columna no existe, entonces ese es solo un marco de datos diferente y, de todos modos, tendrías que ajustar tu código. No estoy tratando de hacer tu vida difícil. Estamos todos aquí intentando que sea más fácil para ti. Nada de lo que ha dicho excluye un marco de datos. Además de todo eso, dado que le gusta atenerse a las listas, debe marcar la mía como la respuesta correcta. :) – John

5

R generalmente quiere manejar estas cosas como data.frames, así que creo que su mejor opción es convertir su lista en una (o incluso hacer un data.frame en lugar de una lista para empezar, a menos que lo necesite). estar en forma de lista).

x <- do.call(rbind,tmp) 
dat <- data.frame(x) 
dat$count <- as.numeric(dat$count) 

> dat 
    count status  menu dbname 
1 1057230  Ok PubMed pubmed 
2 305215  Ok  PMC  pmc 
3  1  Ok Journals journals 

y después de obtener su respuesta (s) se puede usar operaciones normales hoja.de.datos subconjuntos:

> dat$dbname[dat$count<10] 
$resultitem 
[1] "journals" 
+2

Este data.frame no es un data.frame apropiado. Cada columna es una lista. Estará bien si haces 'x <-do.call (rbind, lapply (tmp, unlist))' y luego 'dat <-data.frame (x, stringsAsFactors = FALSE, row.names = NULL)'. – Marek

+0

Noté que el problema con los nombres de las filas y las columnas eran listas, pero no estaba seguro de qué hacer al respecto. Buen arreglo. – Fojtasek

+0

Esto funciona perfectamente para mi ejemplo, gracias. Pero el problema con los dataframes es que no admiten columnas con longitudes diferentes. Y tengo algunas otras listas, donde este será el caso. Así que estoy obligado a las listas. – Martin

0

Parece que su lista proviene de una estructura XML. Es más fácil navegar a lo que desea con XPath y usar la estructura y función NodeSet getNodeSet en el paquete XML

Cuestiones relacionadas