使用 append() 合并后,来自 rentrez 的摘要列表停止工作

Lists of summaries from rentrez stop working after being merged using append()

tl;dr:rentrez 生成的摘要列表有何不同,为什么这些列表在使用 append() 合并后停止与其他 rentrez 函数一起使用?

我正在使用 rentrez 访问 Pubmed。我可以毫无问题地搜索出版物和下载摘要。但是,一定有一些我不理解的摘要列表的特殊之处,因为当我使用 append() 尝试合并列表时,事情就分崩离析了。通过阅读文档,我无法弄清楚这种区别是什么。这是允许我毫无问题地搜索 Pubmed 和下载记录的代码:

# set search term and retmax
term_set <- '"Transcription, Genetic"[Mesh] AND "Regulatory Sequences, Nucleic Acid"[Mesh] AND 2017:2018[PDAT]'
retmax_set <- 500
# search pubmed using web history
search.l <- entrez_search(db = "pubmed", term = term_set, use_history = T)
# get summaries of search hits using web history 
for (seq_start in seq(0, search.l$count, retmax_set)) {
    if (seq_start == 0) {summary.l <- list()} 
    summary.l[[length(summary.l)+1]] <- entrez_summary(
        db = "pubmed", 
        web_history = search.l$web_history, 
        retmax = retmax_set, 
        retstart = seq_start
    )
}

但是,使用 summary.l <- list(),然后使用 summary.l[[length(summary.l)+1]] <- entrez_summary(... 会得到一个摘要列表列表(在此搜索中有 3 个子列表)。这会在数据提取的后续步骤(如下)中导致多个 for 循环,并且是一个不合适的数据结构。

# extract desired information from esummary, convert to dataframe
for (i in 1:length(summary.l)) {
    if (i == 1) {faut.laut.l <- list()}
    faut.laut <- summary.l[[i]] %>% 
        extract_from_esummary(
            c("uid", "sortfirstauthor", "lastauthor"), 
            simplify = F
        )
    faut.laut.l <- c(faut.laut.l, faut.laut)
}
faut.laut.df <- rbindlist(faut.laut.l)

在下面的代码中使用 append() 给出了所有 1334 个摘要的单个列表,避免了子列表。

# get summaries of search hits using web history 
for (seq_start in seq(0, search.l$count, retmax_set)) {
    if (seq_start == 0) {
        summary.append.l <- entrez_summary(
            db = "pubmed", 
            web_history = search.l$web_history, 
            retmax = retmax_set, 
            retstart = seq_start
        )
    } 
    summary.append.l <- append(
        summary.append.l,
        entrez_summary(
            db = "pubmed", 
            web_history = search.l$web_history, 
            retmax = retmax_set, 
            retstart = seq_start
        )
    )
}

然而,在后续步骤中 extract_from_esummary() 会抛出一个错误,即使文档说参数 esummaries 应该是一个摘要对象列表。

# extract desired information from esummary, convert to dataframe
faut.laut.append.l <- extract_from_esummary(
    esummaries = summary.append.l,
    elements = c("uid", "sortfirstauthor", "lastauthor"), 
    simplify = F
)
Error in UseMethod("extract_from_esummary", esummaries) : 
no applicable method for 'extract_from_esummary' applied to an object of class "list"

faut.laut.append.df <- rbindlist(faut.laut.append.l)
Error in rbindlist(faut.laut.append.l) : 
object 'faut.laut.append.l' not found

可以在 entrez_summary() 的单个调用中完成生成少于 500 条记录的搜索,并且不需要串联列表。因此,下面的代码有效。

# set search term and retmax
term_set_small <- 'kadonaga[AUTH]'
retmax_set <- 500
# search pubmed using web history
search_small <- entrez_search(db = "pubmed", term = term_set_small, use_history = T)
# get summaries from search with <500 hits
summary_small <- entrez_summary(
    db = "pubmed", 
    web_history = search_small$web_history, 
    retmax = retmax_set
)
# extract desired information from esummary, convert to dataframe
faut.laut_small <- extract_from_esummary(
    esummaries = summary_small,
    elements = c("uid", "sortfirstauthor", "lastauthor"), 
    simplify = F
)
faut.laut_small.df <- rbindlist(faut.laut_small)

为什么 append() 会破坏摘要,这可以避免吗?谢谢。

extract_from_esummary 的文档对此有点混乱。它真正需要的是 esummary 对象或 esummary_list。因为 esummary 对象本身继承自一个列表,所以我不认为我们可以轻易地让 extract_from_esummary 处理任何抛给它的列表。我会修复文档,也许会考虑更好的对象设计。

为了解决这个特殊问题,有一些修复方法。第一,您可以重新class 摘要列表

class(summary.append.l) <- c("list", "esummary_list")
extract_from_esummary(summary.append.l, "sortfirstauthor")

应该可以解决问题。另一种选择是在进行任何追加之前提取相关数据。这与您的示例类似,多 lapplyfor

all_the_summs <- lapply(seq(0,50,5),  function(s) {
    entrez_summary(db="pubmed", 
                   web_history=search.l$web_history, 
                   retmax=5,  retstart=s)
})
desired_fields <- lapply(all_the_summs, extract_from_esummary, c("uid", "sortfirstauthor", "lastauthor"), simplify=FALSE)  
res <- do.call(cbind.data.frame, desired_fields)

希望提供一条前进的道路。