วิธีแยกวิเคราะห์ XML เป็น R data frame


104

ฉันพยายามแยกวิเคราะห์ XML เป็น R data frame ลิงก์นี้ช่วยฉันได้มาก:

วิธีสร้างเฟรมข้อมูล 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()ช่วยเหลือใด ๆ จะได้รับการชื่นชมมากขอบคุณ

คำตอบ:


104

ข้อมูลในรูปแบบ 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

96

ใช้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

13
นี่น่าจะเป็นคำตอบที่ได้รับการยอมรับจริงๆ มันกระชับกว่าและ xpath มีประสิทธิภาพที่ดีกว่าการทำซ้ำในรายการ
SchaunW

คำตอบที่ดี โปรดทราบว่าบทช่วยสอนW3schoolsอาจเป็นสถานที่ที่ดีกว่าในการเรียนรู้ xpath มากกว่าหน้า xpath อย่างเป็นทางการ
Laurent Bergé

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
คำตอบที่เป็นประโยชน์ หากมีใครสะดุดข้ามนี่คือลิงก์ไปยังบทช่วยสอนโดย Hadley เกี่ยวกับการใช้ xml2: 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.