如何将 XML 文件解析为 R 数据框架?

我试着把一个 XML 文件解析成一个 R 数据框架,这个链接帮了我很大的忙:

如何从 xml 文件创建一个 R 数据框架?

但是我仍然不能解决我的问题,这是我的代码:

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()公司了,如果你能帮忙,我将不胜感激。

206872 次浏览

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"))

leading to

> 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()

你可以试试下面的代码:

# Load the packages required to read XML files.
library("XML")
library("methods")


# Convert the input xml file to a data frame.
xmldataframe <- xmlToDataFrame("input.xml")
print(xmldataframe)