Оптимизация кода R: для цикла и записи в базу данных - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь оптимизировать простой код R, который я написал для двух аспектов:

1) Для циклов

2) Запись данных в мою базу данных PostgreSQL

Для 1) Я знаю, что для циклов следует избегатьлюбой ценой, и рекомендуется использовать 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)
}

Большое спасибо за ваш вклад!

1 Ответ

1 голос
/ 06 ноября 2019

Прежде всего, это миф, который должен быть полностью разрушен, что 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, 1, 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 в любой графический интерфейс, который имеет прямой доступ к базе данных, используя, например, writeLines(statement, 'clipboard') или запись в текстовый файл (файлявляется более стабильным, если ваши данные содержат много строк). В редких случаях выброса это последнее средство может быть быстрее, если по какой-либо причине DBI или альтернативные R пакеты кажутся слишком медленными, без причины. Поскольку это похоже на личный проект, этого может быть достаточно для вашего использования.

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