2010-05-20 16 views
5

Mam ładne liście, który wygląda tak:Jak uzyskać dostęp do elementów na złożonej liście?

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) 

która produkuje:

> 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" 

Teraz chcę przeszukać elementów każdego resultitem. Chcę poznać numer dbname dla każdej bazy danych, która ma mniej niż 10 count (przykład). W tym przypadku jest to bardzo proste, ponieważ lista ta zawiera tylko 3 elementy, ale prawdziwa lista jest nieco dłuższa.

Można to zrobić po prostu za pomocą pętli for. Ale czy istnieje sposób, aby to zrobić z inną funkcją R (jak rapply)? Mój problem z tymi stosowanymi funkcjami polega na tym, że patrzą tylko na jeden element.

Jeśli zrobię grep, aby uzyskać wszystkie elementy dbname, nie mogę uzyskać liczby poszczególnych elementów.

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

Czy ktoś ma lepszy pomysł niż pętla for?

+6

Przepraszam, ale dlaczego używasz tych niezręcznych struktur list, a nie ramki danych? –

Odpowiedz

2

Jeśli jesteś absolutnie natarczywy, że trzeba to zrobić w wykazie znajdą pracować w tej sprawie.

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

Ogólniej, jeśli chcesz faktycznie korzysta poszarpane list w ten sposób można użyć tego samego kodu, ale sprawdzić na obecność elementu pierwszego

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

To będzie pracować dla przypadków gdzie listy nie mają tej samej długości, jak i niniejszej sprawy. (Nadal uważam, że powinieneś używać ramek danych do szybkiego i rozsądnego przedstawiania danych).

+0

Problem z moimi danymi polega na tym, że pochodzi on z usługi sieciowej. I nie jest pewne, że kolumna istnieje. Jeśli usługa sieciowa zmieni pakiet R nie będzie już działać. Nawet jeśli zapytanie zmieni się, kolumny mogą nie być takie same jak wcześniej. Postanowiłem więc użyć list jako reprezentacji wyników. A teraz szukam sposobów radzenia sobie z tymi listami. Bardzo mi pomogłeś, dziękuję. – Martin

+0

Myślę, że mówisz, że nie możesz być pewien, że komórka istnieje w danym zapytaniu. W porządku, po prostu NA to komórka. Jeśli kolumna w ogóle nie istnieje, to jest to tylko inna ramka danych, a mimo to trzeba będzie zmienić kod. Nie próbuję utrudniać twojego życia. Wszyscy tu jesteśmy, próbując ci ułatwić. Nic, co powiedziałeś, nie wyklucza ramki danych. Oprócz tego wszystkiego, biorąc pod uwagę, że chcesz trzymać się list, powinieneś oznaczyć moją jako poprawną odpowiedź. :) – John

5

R ogólnie chce obsługiwać te rzeczy jako data.frames, więc myślę, że najlepiej jest zamienić listę w jedną (lub nawet utworzyć zamiast tego listę danych zamiast listy, chyba że jest to potrzebne być w formie listy).

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 

a następnie, aby uzyskać odpowiedź na to pytanie (s) można użyć zwykłych operacji data.frame podzbiorów:

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

Ta data.frame nie jest poprawna data.frame. Każda kolumna jest listą. Będzie dobrze, jeśli zrobisz 'x <-do.call (rbind, lapply (tmp, unlist)), a następnie' dat <-data.frame (x, stringiAsFactors = FALSE, row.names = NULL) '. – Marek

+0

Zauważyłem problem z nazwami rzędów i kolumnami, ale nie byłem od razu przekonany, co z nimi zrobić. Dobra poprawka. – Fojtasek

+0

To działa idealnie na mój przykład, thanx. Ale problem z ramkami danych polega na tym, że nie obsługują kolumn o różnych długościach. Mam też inne listy, w których tak się stanie. Więc jestem zobowiązany do list. – Martin

0

Wygląda na to, że twoja lista pochodzi ze struktury XML. Łatwiej jest nawigować do tego, co chcesz z XPath i używać struktury i funkcji NodeSet getNodeSet w pakiecie XML

Powiązane problemy