Как получить доступ к элементам в сложном списке? - PullRequest
5 голосов
/ 20 мая 2010

У меня есть хороший список, который выглядит так:

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)

Который производит:

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

Теперь я хочу поискать элементы каждого resultitem. Я хочу знать dbname для каждой базы данных, которая имеет менее 10 count (пример). В этом случае это очень просто, так как в этом списке всего 3 элемента, но реальный список немного длиннее.

Это можно сделать просто с помощью цикла for. Но есть ли способ сделать это с какой-то другой функцией R (например, rapply)? Моя проблема с этими применимыми функциями заключается в том, что они смотрят только на один элемент.

Если я сделаю grep, чтобы получить все элементы dbname, я не смогу получить счетчик каждого элемента.

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

У кого-нибудь есть идея получше, чем цикл for?

Ответы [ 3 ]

5 голосов
/ 20 мая 2010

R обычно хочет обрабатывать эти вещи как data.frames, поэтому я думаю, что вам лучше всего превратить ваш список в один (или даже создать data.frame вместо списка для начала, если только вам это не нужно) в виде списка).

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

и затем, чтобы получить ответ (ы), вы можете использовать обычные операции подмножества data.frame:

> dat$dbname[dat$count<10]
$resultitem
[1] "journals"
2 голосов
/ 20 мая 2010

Если вы абсолютно настаиваете на том, что вы должны сделать это в списке, в данном случае будет работать следующее.

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

В более общем смысле, если вы хотите использовать рваные списки таким образом, вы можете использовать тот же код, но сначала проверьте наличие элемента

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

Это будет работать для ваших случаев, когда списки имеют разную длину, а не для настоящего случая. (Я все еще думаю, что вы должны использовать фреймы данных как для скорости, так и для разумного представления данных).

0 голосов
/ 27 января 2012

Похоже, ваш список происходит из структуры XML. Проще перейти к тому, что вы хотите с XPath и используя структуру и функцию NodeSet getNodeSet в пакете XML

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...