Как разобрать XML на R фрейм данных
Я попытался разобрать XML на R фрейм данных, эта ссылка мне очень помогла:
как создать фрейм данных R из xml-файла
но все равно я не смог разобраться в своей проблеме:
вот мой код:
data <- xmlParse("http://forecast.weather.gov/MapClick.php?lat=29.803&lon=-82.411&FcstType=digitalDWML")
xmlToDataFrame(nodes=getNodeSet(data1,"//data"))[c("location","time-layout")]
step1 <- xmlToDataFrame(nodes=getNodeSet(data1,"//location/point"))[c("latitude","longitude")]
step2 <- xmlToDataFrame(nodes=getNodeSet(data1,"//time-layout/start-valid-time"))
step3 <- xmlToDataFrame(nodes=getNodeSet(data1,"//parameters/temperature"))[c("type="hourly"")]
фрейм данных, который я хочу иметь, выглядит так:
latitude longitude start-valid-time hourly_temperature
29.803 -82.411 2013-06-19T15:00:00-04:00 91
29.803 -82.411 2013-06-19T16:00:00-04:00 90
Я застрял в xmlToDataFrame()
, любая помощь будет очень ценится, спасибо.
4 ответа:
данные в формате XML редко организованы таким образом, что бы позволить
xmlToDataFrame
функция для работы. Вам лучше извлечь все в списках, а затем связать списки вместе в фрейме данных:require(XML) data <- xmlParse("http://forecast.weather.gov/MapClick.php?lat=29.803&lon=-82.411&FcstType=digitalDWML") xml_data <- xmlToList(data)
в случае вашего примера данных, получение местоположения и времени начала довольно просто:
location <- as.list(xml_data[["data"]][["location"]][["point"]]) start_time <- unlist(xml_data[["data"]][["time-layout"]][ names(xml_data[["data"]][["time-layout"]]) == "start-valid-time"])
данные о температуре немного сложнее. Сначала нужно добраться до узла, который содержит списки температуры. Тогда вам нужно извлечь оба списки, посмотрите в каждом из них, и выбрать тот, который имеет "ежечасно" в качестве одного из его значений. Затем вам нужно выбрать только этот список, но только сохранить значения, которые имеют метку "value":
temps <- xml_data[["data"]][["parameters"]] temps <- temps[names(temps) == "temperature"] temps <- temps[sapply(temps, function(x) any(unlist(x) == "hourly"))] temps <- unlist(temps[[1]][sapply(temps, names) == "value"]) out <- data.frame( as.list(location), "start_valid_time" = start_time, "hourly_temperature" = temps) head(out) latitude longitude start_valid_time hourly_temperature 1 29.81 -82.42 2013-06-19T16:00:00-04:00 91 2 29.81 -82.42 2013-06-19T17:00:00-04:00 90 3 29.81 -82.42 2013-06-19T18:00:00-04:00 89 4 29.81 -82.42 2013-06-19T19:00:00-04:00 85 5 29.81 -82.42 2013-06-19T20:00:00-04:00 83 6 29.81 -82.42 2013-06-19T21:00:00-04:00 80
использовать xpath более непосредственно для производительности и ясности.
time_path <- "//start-valid-time" temp_path <- "//temperature[@type='hourly']/value" df <- data.frame( latitude=data[["number(//point/@latitude)"]], longitude=data[["number(//point/@longitude)"]], start_valid_time=sapply(data[time_path], xmlValue), hourly_temperature=as.integer(sapply(data[temp_path], as, "integer"))
, ведущей к
> head(df, 2) latitude longitude start_valid_time hourly_temperature 1 29.81 -82.42 2014-02-14T18:00:00-05:00 60 2 29.81 -82.42 2014-02-14T19:00:00-05:00 55
вот частичное решение с использованием xml2. Разбивая решение на более мелкие кусочки, как правило, облегчает обеспечение того, чтобы все было выстроено:
library(xml2) data <- read_xml("http://forecast.weather.gov/MapClick.php?lat=29.803&lon=-82.411&FcstType=digitalDWML") # Point locations point <- data %>% xml_find_all("//point") point %>% xml_attr("latitude") %>% as.numeric() point %>% xml_attr("longitude") %>% as.numeric() # Start time data %>% xml_find_all("//start-valid-time") %>% xml_text() # Temperature data %>% xml_find_all("//temperature[@type='hourly']/value") %>% xml_text() %>% as.integer()