Извлечение деталей из файла Google Earth KML в R - PullRequest
0 голосов
/ 01 марта 2020

Я пытаюсь взять подробности из ряда местоположений в файле Google Earth kml.

Получение идентификаторов и координат работает, но для имени местоположения (которое находится в первой ячейке таблицы ( тд) из описания), когда я делаю это для ВСЕХ локаций, он возвращает одинаковое значение для всех них (Stratford Road - название первой локации).

library(sf)
library(tidyverse)
library(rvest)

removeHtmlTags <- function(htmlString) {
  return(gsub("<.*?>", "", htmlString))
}
getHtmlTableCells<- function(htmlString) {
  # Convert html to html doc
  htmldoc <- read_html(htmlString)
  # get html for each cell (i.e. within <td></td>)
  table_cells_with_tags <- html_nodes(htmldoc, "td")
  # remove the html tags (<td></td>)
  return(removeHtmlTags(table_cells_with_tags))[1]
}

download.file("https://www.dropbox.com/s/ohipb477kqrqtlz/AQMS_2019.kml?dl=1","aqms.kml")
locations <- st_read("aqms.kml", stringsAsFactors = FALSE) %>%
  rename(id = Name) %>%
  mutate(latitude = st_coordinates(geometry)[,1],
         longitiude = st_coordinates(geometry)[,2],
         name = getHtmlTableCells(Description)[1]) %>%
  st_drop_geometry()

Теперь, если я используйте функцию в определенном месте и получите первую ячейку таблицы (td), затем она работает, возвращая Stratford Road и Selly Oak для первого, как показано ниже.

getHtmlTableCells(locations$Description[1])[1]
getHtmlTableCells(locations$Description[2])[1]

Что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 02 марта 2020

Ваша getHtmlTableCells функция не векторизована. Если вы передадите ей одну html строку, она будет работать нормально, но если вы передадите ей несколько строк, она обработает только первую. Кроме того, вы поставили [1] после оператора return, который ничего не делает. Это должно быть в скобках. Как только вы это сделаете, вы легко векторизуете функцию, используя sapply.

Так что внесите небольшое изменение в вашу функцию ...

getHtmlTableCells <- function(htmlString) {
  # Convert html to html doc
  htmldoc <- read_html(htmlString)
  # get html for each cell (i.e. within <td></td>)
  table_cells_with_tags <- html_nodes(htmldoc, "td")
  # remove the html tags (<td></td>)
  return(removeHtmlTags(table_cells_with_tags)[1])
}

и векторизуйте ее следующим образом:

download.file("https://www.dropbox.com/s/ohipb477kqrqtlz/AQMS_2019.kml?dl=1","aqms.kml")

locations <- st_read("aqms.kml", stringsAsFactors = FALSE) %>%
  rename(id = Name) %>%
  mutate(latitude = st_coordinates(geometry)[,1],
         longitiude = st_coordinates(geometry)[,2],
         name = sapply(as.list(Description), getHtmlTableCells)) %>%
  st_drop_geometry()

Что дает правильный результат:

locations$name
#>  [1] "Stratford Road"            "Selly Oak (Bristol Road)" 
#>  [3] "Acocks Green"              "Colmore Row"              
#>  [5] "St Chads Queensway"        "Moor Street Queensway"    
#>  [7] "Birmingham Ladywood"       "Lower Severn Street"      
#>  [9] "New Hall"                  "Birmingham A4540 Roadside"
2 голосов
/ 01 марта 2020

read_html не векторизовано - он не принимает вектор для анализа html. Мы можем apply вашу функцию для каждого элемента вектора:

locations <- st_read("aqms.kml", stringsAsFactors = FALSE) 

locations %>%
  rename(id = Name) %>%
  mutate(latitude = st_coordinates(geometry)[,1],
         longitiude = st_coordinates(geometry)[,2],
         name = sapply(Description, function(x) getHtmlTableCells(x)[1])) %>%
  st_drop_geometry()

#>     latitude longitiude                      name
#> 1  -1.871622   52.45920            Stratford Road
#> 2  -1.934559   52.44513  Selly Oak (Bristol Road)
#> 3  -1.830070   52.43771              Acocks Green
#> 4  -1.898731   52.48180               Colmore Row
#> 5  -1.896764   52.48607        St Chads Queensway
#> 6  -1.891955   52.47990     Moor Street Queensway
#> 7  -1.918173   52.48138       Birmingham Ladywood
#> 8  -1.902121   52.47675       Lower Severn Street
#> 9  -1.786413   52.56815                  New Hall
#> 10 -1.874989   52.47609 Birmingham A4540 Roadside

В качестве альтернативы, поскольку вы в любом случае используете regex в своей функции, вы можете использовать stringr::str_extract для извлечения вашего текста (который уже векторизован).

library(sf)
library(tidyverse)

locations <- st_read("aqms.kml", stringsAsFactors = FALSE) %>%
  rename(id = Name) %>%
  mutate(latitude = st_coordinates(geometry)[,1],
         longitiude = st_coordinates(geometry)[,2],
         name = str_extract(Description, '(?<=Location</td> <td>)[^<]+')) %>%
  st_drop_geometry()

Где (?<=Location</td> <td>) - это указатель на тег Location td, предшествующий нашему name и [^<]+ соответствует чему-либо до следующего тега, следующего за name .

...