Чтение многочисленных html-таблиц в R

#r #web-scraping #xml-parsing

#r #очистка веб-страниц #синтаксический анализ xml

Вопрос:

Я пытаюсь объединить HTML-таблицы данных в единый фрейм данных и ищу элегантное решение. Существует 255 таблиц, а URL-адреса различаются двумя переменными: годом и округом Олдермена. Я знаю, что должен быть способ использовать циклы for или что-то в этом роде, но я в тупике.

Я успешно импортировал данные, прочитав каждую таблицу с помощью отдельной строки кода, но в результате для каждой таблицы получается строка, и снова получается 255 таблиц.

 library(XML)
data <- bind_rows(readHTMLTable("http://assessments.milwaukee.gov/SalesData/2018_RVS_Dist14.htm", skip.rows=1),
                   readHTMLTable("http://assessments.milwaukee.gov/SalesData/2017_RVS_Dist14.htm", skip.rows=1),
                   readHTMLTable("http://assessments.milwaukee.gov/SalesData/2016_RVS_Dist14.htm", skip.rows=1),
                   readHTMLTable("http://assessments.milwaukee.gov/SalesData/2015_RVS_Dist14.htm", skip.rows=1),
  

В идеале я мог бы использовать for цикл или что-то в этом роде, чтобы мне не приходилось вручную кодировать readHTMLTable функцию для каждой таблицы.

Ответ №1:

Вы могли бы попробовать создать вектор, содержащий все URL, которые вы хотите очистить, а затем выполнить итерацию по этим входным данным, используя for цикл:

 url1 <- "http://assessments.milwaukee.gov/SalesData/"
url2 <- "_RVS_Dist"
years <- c(2015:2018)
dist <- c(1:15)
urls <- apply(expand.grid(paste0(url1, years), paste0(url2, dist)), 1, paste, collapse="")
data <- NULL
for (url in urls) {
    df <- readHTMLTable(url)
    data <- rbind(data, df)
}
  

Комментарии:

1. Спасибо за ваш ответ. Проблема в том, что мне все еще приходится записывать все URL-адреса — я ищу решение, которое автоматизирует итерацию URL-адресов.

2. @Pecners Я дал вам возможность генерировать URL-адреса для всех лет и районов.

Ответ №2:

Мы можем использовать map_dfr из purrr пакета (части tidyverse ) пакета, чтобы применить readHTMLTable функцию к URL. Ключ в том, чтобы определить часть, которая отличается от каждого URL. В этом случае 2015:2018 изменено единственное, поэтому мы можем сконструировать URL с помощью paste0 . map_dfr автоматически объединило бы все фреймы данных, чтобы вернуть один объединенный фрейм данных. dat является конечным результатом.

 library(tidyverse)
library(XML)

dat <- map_dfr(2015:2018,
               ~readHTMLTable(paste0("http://assessments.milwaukee.gov/SalesData/",
                                     .x,
                                     "_RVS_Dist14.htm"), skip.rows = 1)[[1]])
  

Обновить

Вот способ расширить комбинацию между годом и числами, а затем загрузить данные с помощью map2_dfr .

 url <- expand.grid(Year = 2002:2018, Number = 1:15)

dat <- map2_dfr(url$Year, url$Number,
               ~readHTMLTable(paste0("http://assessments.milwaukee.gov/SalesData/",
                                     .x,
                                     "_RVS_Dist",
                                     .y,
                                     ".htm"), skip.rows = 1)[[1]]) 
  

Комментарии:

1. Спасибо за ваш ответ. Это работает годами, но район также варьируется, начиная с 1: 15 («14» в URL). Могу ли я использовать этот метод в течение 2002: 2018 годов для районов в диапазоне 1: 15?

2. Передайте районы в качестве второго аргумента с помощью map2_dfr(arg1, arg2, fun) . Обратитесь к нему, используя, .y где это уместно, внутри paste выше, и все готово