如何解决为“加载”和“保存”进程创建一个循环
我有一个包含 url 链接列表的 data.frame
(dim: 100 x 1),每个 url 看起来像这样:https:blah-blah-blah.com/item/123/index.do
.
列表(列表是一个名为 my_list
的数据框,有 100 行和一个名为 col
的单列,采用字符格式 $ col: chr
)一起看起来像这样:>
1 "https:blah-blah-blah.com/item/123/index.do"
2" https:blah-blah-blah.com/item/124/index.do"
3 "https:blah-blah-blah.com/item/125/index.do"
etc.
我正在尝试将这些 url 中的每一个导入 R 并将对象共同保存为与文本挖掘程序兼容的对象。
我知道如何手动成功转换这些网址(在列表中):
library(pdftools)
library(tidytext)
library(textrank)
library(dplyr)
library(tm)
#1st document
url <- "https:blah-blah-blah.com/item/123/index.do"
article <- pdf_text(url)
str(article)
chr [1:13]
看起来像这样:
[1] "abc ....."
[2] "def ..."
etc etc
[15] "ghi ...:
从这里,我可以成功地将其保存为 RDS 文件:
saveRDS(article,file = "article_1.rds")
有没有办法同时对所有 100 篇文章执行此操作?也许有一个循环?
类似:
for (i in 1:100) {
url_i <- my_list[i,1]
article_i <- pdf_text(url_i)
saveRDS(article_i,file = "article_i.rds")
}
如果写得正确,它会将每篇文章保存为 RDS 文件(例如 article_1.rds、article_2.rds、... article_100.rds)。
解决方法
请注意,list
不是一个对象的好名字,因为这会
暂时覆盖 。我认为这通常很好
根据变量的内容命名变量。也许 list()
函数url_df
会是
好名字。
library(pdftools)
#> Using poppler version 20.09.0
library(tidyverse)
url_df <-
data.frame(
url = c(
"https://www.nimh.nih.gov/health/publications/autism-spectrum-disorder/19-mh-8084-autismspecdisordr_152236.pdf","https://www.nimh.nih.gov/health/publications/my-mental-health-do-i-need-help/20-mh-8134-mymentalhealth-508_161032.pdf"
)
)
由于网址已经在 data.frame
中,我们可以将文本数据存储在
一个额外的专栏。这样数据就可以很容易地供以后使用
步骤。
text_df <-
url_df %>%
mutate(text = map(url,pdf_text))
我们现在可以存储所有数据,而不是将每个文本保存在单独的文件中 在单个文件中:
saveRDS(text_df,"text_df.rds")
由于历史原因,for
循环在 R 社区中并不是很流行。
base R
具有 *apply()
函数族,它提供了一个函数式
迭代的方法。 tidyverse 有 purrr
包和 map*()
改进 *apply()
函数的函数。
我建议看一看 https://purrr.tidyverse.org/ 了解详情。
,假设您有一个名为 data.frame
的 my_df
,其中有一列包含您的 pdf 位置的 URL。根据您的评论,似乎某些 URL 会导致 PDF 损坏。在这些情况下,您可以使用 tryCatch
报告哪些链接已损坏并手动检查这些链接有什么问题。
您可以像这样在 for
循环中执行此操作:
my_df <- data.frame(url = c(
"https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",# working pdf
"https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pfd" # broken pdf
))
# make some useful new columns
my_df$id <- seq_along(my_df$url)
my_df$status <- NA
for (i in my_df$id) {
my_df$status[i] <- tryCatch({
message("downloading ",i) # put a status message on screen
article_i <- suppressMessages(pdftools::pdf_text(my_df$url[i]))
saveRDS(article_i,file = paste0("article_",i,".rds"))
"OK"
},error = function(e) {return("FAILED")}) # return the string FAILED if something goes wrong
}
my_df$status
#> [1] "OK" "FAILED"
我特意在示例数据中加入了一个断开的链接,以展示它的外观。
或者,您可以使用 apply 系列中的循环。不同之处在于,*apply 不是遍历向量并应用相同的代码直到向量结束,而是采用一个函数,将其应用于列表的每个元素(或可以转换为列表的对象)并返回结果从一次迭代开始。许多人一开始发现 *apply 函数很混乱,因为通常人们在一行中定义和应用函数。让我们让函数更明确:
s_download_pdf <- function(link,id) {
tryCatch({
message("downloading ",id) # put a status message on screen
article_i <- suppressMessages(pdftools::pdf_text(link))
saveRDS(article_i,id,error = function(e) {return("FAILED")})
}
既然我们有了这个功能,让我们用它来下载所有文件。我正在使用 mapply
,它一次遍历两个向量,在本例中为 id
和 url
列:
my_df$status <- mapply(s_download_pdf,link = my_df$url,id = my_df$id)
my_df$status
#> [1] "OK" "FAILED"
我认为您选择哪种方法没有太大区别,因为速度将受到您的互联网连接而不是 R
的瓶颈。只是想你可能会喜欢这种比较。
您的数据中似乎有某些 url 不是有效的 pdf 文件。您可以将其包装在 tryCatch
中以处理错误。如果您的数据框名为 df
,其中包含 url
列,您可以执行以下操作:
library(pdftools)
lapply(seq_along(df$url),function(x) {
tryCatch({
saveRDS(pdf_text(df$url[x]),file = sprintf('article_%d.rds',x)),},error = function(e) {})
})
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。