对read_html使用sapply / vapply

时间:2019-09-22 15:05:33

标签: r rvest

library(rvest)

urls <- c("https://www.r-bloggers.com", "https://www.stackoverflow.com")

docsFor <- list()
for(url in urls){
  docsFor[[url]] <- read_html(url)
}
docsFor[[1]]

问题:我该如何用sapply / vapply做同样的事情?

使用sapply(urls, read_html)不起作用,因此我选择了vapply。如果我是正确的,我会需要externalptr(0)之类的东西,但我不确定是否存在。

无法工作,因为没有externalptr()?:

docs <- vapply(urls, read_html, FUN.VALUE = list(externalptr(0), externalptr(0)))
docs[[1]]

2 个答案:

答案 0 :(得分:3)

简而言之,如果您要返回的是列表(这是您的情况),请使用lapply而不是sapply,后者是lapply的包装,它返回一个{{ 1}},vectormatrix

array相同的论点,因为正如注释中适当提到的,应仅将其用于简化对象。

因此,这种情况下最好的整洁解决方案是:

vapply

答案 1 :(得分:1)

本质上,应用族的每个成员默认情况下都会返回:

  • 简化的对象(向量,矩阵,数组),其中所有元素都是相同的原子类型,例如逻辑,整数,双精度,复数,原始;
  • 非简化对象(数据框,列表),其中每个元素不一定是相同的类型,并且可以包含复杂的类对象。

要充分将for循环转换为apply-family函数,您必须首先询问什么是输入类型和所需的输出类型?由于read_html返回XML类型的特殊类对象,因此它不能完全适合原子向量或矩阵。因此,lapply将是最好的for循环翻译。但是,它的同级可以处理对默认值或输入的各种更改:

施加

lapply(urls, read_html)

应用 (至少需要二维输入,例如矩阵或数组)

apply(matrix(urls), 1, read_html)

应用 (包装到lapply,但需要simplify参数)

sapply(urls, read_html, simplify=FALSE)

通过 tapply的面向对象包装)

by(urls, urls, function(x) read_html(as.character(x)))

mapply (需要SIMPLIFY参数,该参数等效于包装器Map

mapply(read_html, urls, SIMPLIFY = FALSE)

Map(read_html, urls)

强行应用 (需要嵌套列表转换以及列表输出)

urls_list <- list(u1 = urls[1], u2 = urls[2])

rapply(urls_list, read_html, how="list")

以下功能由于默认值仅限于简化类型而无法使用,其中?引用外部指针。

应用 (默认设置)

sapply(urls, read_html)

#      https://www.r-bloggers.com https://www.stackoverflow.com
# node ?                          ?                            
# doc  ?                          ?         

vapply (通常只返回简化的对象)

vapply(urls, read_html, vector(mode="list", length=2))

#      https://www.r-bloggers.com https://www.stackoverflow.com
# node ?                          ?                            
# doc  ?                          ?         

应用 (默认设置)

mapply(read_html, urls)
#      https://www.r-bloggers.com https://www.stackoverflow.com
# node ?                          ?                            
# doc  ?                          ?         

应用

rapply(urls_list, read_html)

# $u1.node
# <pointer: 0x8638eb0>

# $u1.doc
# <pointer: 0x6f79b30>

# $u2.node
# <pointer: 0x9c98930>

# $u2.doc
# <pointer: 0x9cb19a0>

有关进一步的阅读,请参见下面的SO帖子:

Grouping functions (tapply, by, aggregate) and the *apply family