作者:moTzxx | 来源:互联网 | 2023-09-13 15:27
我正在尝试优化我在两个方面编写的简单R代码:
1) 用于循环
2) 将数据写入我的PostgreSQL数据库
对于 1) 我知道应该不惜一切代价避免for循环,建议使用lapply,但是我不清楚如何在下面使用lapply转换我的代码
对于 2) ,我下面的工作是否有效,但是我不确定这是最有效的方法(例如,将这种方式与将所有数据重新绑定到R中一样)数据框,然后将整个数据框加载到我的PostgreSQL数据库中。)
编辑:我用下面的可复制示例更新了代码。
for (i in 1:100){
search <- paste0("https://github.com/search?o=desc&p=",i,&q=R&type=Repositories)
download.file(search,destfile ='scrape.html',quiet = TRUE)
url <- read_html('scrape.html')
github_title <- url%>%html_nodes(xpath="//div[@class=mt-n1]")%>%html_text()
github_link <- url%>%html_nodes(xpath="//div[@class=mt-n1]//@href")%>%html_text()
df <- data.frame(github_title,github_link )
colnames(df) <- c("title","link")
dbWritetable(con,"my_database",df,append = TRUE,row.names = FALSE)
cat(i)
}
非常感谢您的所有投入!
首先,完全荒谬的是,lapply
比使用for loop
的等效代码要快得多。多年来,此问题已得到解决,for loops
在每种情况下都应比等效的lapply
更快。
随着您似乎觉得更直观,我将使用for loop
进行可视化。但是请注意,我主要在T-sql中工作,可能需要进行一些转换。
n <- 1e5
outputDat <- vector('list',n)
for (i in 1:10000){
id <- element_a[i]
location <- element_b[i]
language <- element_c[i]
date_creation <- element_d[i]
df <- data.frame(id,location,language,date_creation)
colnames(df) <- c("id","location","language","date_creation")
outputDat[[i]] <- df
}
## Combine data.frames
outputDat <- do.call('rbind',outputDat)
#Write the combined data.frame into the database.
##dbBegin(con) #<= might speed up might not.
dbWriteTable(con,"my_database",df,append = TRUE,row.names = FALSE)
##dbCommit(con) #<= might speed up might not.
使用Transact-SQL,您可以选择将整个字符串组合为单个insert into
语句。在这里,我将偏离并使用apply
对行进行迭代,因为在这种情况下它更易读。如果正确完成,则for循环再次变得一样快。
#Create the statements. here
statement <- paste0("('",apply(outputDat,1,paste0,collapse = "','"),"')",collapse = ",\n") #\n can be removed,but makes printing nicer.
##Optional: Print a bit of the statement
# cat(substr(statement,2000))
##dbBegin(con) #<= might speed up might not.
dbExecute(con,statement <- paste0(
'
/*
SET NOCOCUNT ON seems to be necessary in the DBI API.
It seems to react to 'n rows affected' messages.
Note only affects this method,not the one using dbWriteTable
*/
--SET NOCOUNT ON
INSERT INTO [my table] values ',statement))
##dbCommit(con) #<= might speed up might not.
请注意,正如我所评论的那样,这可能会导致无法正确上载表,因为DBI
包有时会导致这种交易失败,如果它导致有关n rows affected
的一条或多条消息。
最后但并非最不重要的一点是,可以将语句从R
复制并粘贴到任何直接访问数据库的GUI中,例如使用writeLines(statement,'clipboard')
或写入文本文件(如果您的数据包含很多行,则文件更稳定)。在极少数的异常情况下,如果出于某种原因DBI
或替代R
程序包似乎无故运行太慢,则最后一招可能会更快。由于这似乎是一个个人项目,因此可能足以供您使用。