【问题标题】:How to parse XML to R data frame如何将 XML 解析为 R 数据框
【发布时间】:2013-06-16 10:12:44
【问题描述】:

我尝试将 XML 解析为 R 数据框,这个链接对我帮助很大:

how to create an R data frame from a xml file

但我仍然无法弄清楚我的问题:

这是我的代码:

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(),非常感谢任何帮助,谢谢。

【问题讨论】:

    标签: xml r


    【解决方案1】:

    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
    

    【讨论】:

      【解决方案2】:

      更直接地使用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
      

      【讨论】:

      • 这确实应该是公认的答案。它更简洁,并且 xpath 比迭代列表具有更好的性能。
      • 很好的答案。请注意,W3schools 教程可能比官方 xpath 页面更适合学习 xpath。
      【解决方案3】:

      这是使用 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()
      

      【讨论】:

      【解决方案4】:

      你可以试试下面的代码:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-15
        • 2015-10-07
        • 2019-03-05
        • 2016-01-27
        相关资源
        最近更新 更多