XML에서 R 데이터 프레임으로 구문 분석하는 방법


103

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(), 어떤 도움이라도 대단히 감사하겠습니다, 감사합니다.

답변:


103

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

온도 데이터는 조금 더 복잡합니다. 먼저 온도 목록이 포함 된 노드로 이동해야합니다. 그런 다음 두 목록을 모두 추출하고 각 목록을 살펴본 다음 값 중 하나로 "시간별"이있는 목록을 선택해야합니다. 그런 다음 해당 목록 만 선택하고 "값"레이블이있는 값만 유지해야합니다.

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

94

성능과 명확성을 위해 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

12
이것은 정말로 받아 들여지는 대답이어야합니다. 더 간결하고 xpath는 목록을 반복하는 것보다 훨씬 더 나은 성능을 제공합니다.
SchaunW

40

다음은 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()

8
유용한 답변입니다. 다른 사람이 우연히 발견 한 경우 xml2 사용에 대한 Hadley의 자습서 링크 : blog.rstudio.com/2015/04/21/xml2
Richard Erickson

9

아래 코드를 시도해 볼 수 있습니다.

# 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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.