【问题标题】:Parse XML File with R Get into data frame使用 R 解析 XML 文件进入数据框
【发布时间】:2016-07-28 20:39:37
【问题描述】:

XML 数据

<HealthData locale="en_US">
 <ExportDate value="2016-06-02 14:05:23 -0400"/>
 <Me HKCharacteristicTypeIdentifierDateOfBirth="" HKCharacteristicTypeIdentifierBiologicalSex="HKBiologicalSexNotSet" HKCharacteristicTypeIdentifierBloodType="HKBloodTypeNotSet" HKCharacteristicTypeIdentifierFitzpatrickSkinType="HKFitzpatrickSkinTypeNotSet"/>
 <Record type="HKQuantityTypeIdentifierStepCount" sourceName="Ryan Praskievicz iPhone" unit="count" creationDate="2014-10-02 08:30:17 -0400" startDate="2014-09-24 15:07:06 -0400" endDate="2014-09-24 15:07:11 -0400" value="7"/>
 <Record type="HKQuantityTypeIdentifierStepCount" sourceName="Ryan Praskievicz iPhone" unit="count" creationDate="2014-10-02 08:30:17 -0400" startDate="2014-09-24 15:12:13 -0400" endDate="2014-09-24 15:12:18 -0400" value="15"/>
 <Record type="HKQuantityTypeIdentifierStepCount" sourceName="Ryan Praskievicz iPhone" unit="count" creationDate="2014-10-02 08:30:17 -0400" startDate="2014-09-24 15:17:16 -0400" endDate="2014-09-24 15:17:21 -0400" value="20"/>
</HealthData>

R 代码

> library(XML)
> doc="\\pathtoXMLfile"
> list <-xpathApply(doc, "//HealthData/Record", xmlAttrs)
> df <- do.call(rbind.data.frame, list)
> str(df)

我正在尝试获取上面显示的 XML 数据样本并将其加载到 R 中的数据框中,其中每个记录的名称即类型、源名称、单位、结束日期、值作为列标题和每个记录值,即计数, 2014-09-24 15:07:11 -0400, 7 作为数据框中每一行的值。

df &lt;- do.call(rbind.data.frame, list) 关闭时,它看起来也绑定了列标题的所有值。如果你 View(df)str(df) 你会明白我的意思。如何使用记录变量名称作为列标题名称?

谢谢, 瑞恩

【问题讨论】:

    标签: r xml xml-parsing rbind


    【解决方案1】:

    考虑xpathSApply() 检索属性,然后将结果列表与t() 转置到数据帧中:

    library(XML)
    
    xmlstr <- '<?xml version="1.0" encoding="UTF-8"?>
                <HealthData locale="en_US">
                  <ExportDate value="2016-06-02 14:05:23 -0400"/>
                  <Me HKCharacteristicTypeIdentifierDateOfBirth="" HKCharacteristicTypeIdentifierBiologicalSex="HKBiologicalSexNotSet" HKCharacteristicTypeIdentifierBloodType="HKBloodTypeNotSet" HKCharacteristicTypeIdentifierFitzpatrickSkinType="HKFitzpatrickSkinTypeNotSet"/>
                  <Record type="HKQuantityTypeIdentifierStepCount" sourceName="Ryan Praskievicz iPhone" unit="count" creationDate="2014-10-02 08:30:17 -0400" startDate="2014-09-24 15:07:06 -0400" endDate="2014-09-24 15:07:11 -0400" value="7"/>
                  <Record type="HKQuantityTypeIdentifierStepCount" sourceName="Ryan Praskievicz iPhone" unit="count" creationDate="2014-10-02 08:30:17 -0400" startDate="2014-09-24 15:12:13 -0400" endDate="2014-09-24 15:12:18 -0400" value="15"/>
                  <Record type="HKQuantityTypeIdentifierStepCount" sourceName="Ryan Praskievicz iPhone" unit="count" creationDate="2014-10-02 08:30:17 -0400" startDate="2014-09-24 15:17:16 -0400" endDate="2014-09-24 15:17:21 -0400" value="20"/>
                </HealthData>'
    
    xml <- xmlParse(xmlstr)
    
    recordAttribs <- xpathSApply(doc=xml, path="//HealthData/Record",  xmlAttrs)
    df <- data.frame(t(recordAttribs))
    df
    
    #                                type              sourceName  unit
    # 1 HKQuantityTypeIdentifierStepCount Ryan Praskievicz iPhone count
    # 2 HKQuantityTypeIdentifierStepCount Ryan Praskievicz iPhone count
    # 3 HKQuantityTypeIdentifierStepCount Ryan Praskievicz iPhone count
    #                creationDate                 startDate                   endDate
    # 1 2014-10-02 08:30:17 -0400 2014-09-24 15:07:06 -0400 2014-09-24 15:07:11 -0400
    # 2 2014-10-02 08:30:17 -0400 2014-09-24 15:12:13 -0400 2014-09-24 15:12:18 -0400
    # 3 2014-10-02 08:30:17 -0400 2014-09-24 15:17:16 -0400 2014-09-24 15:17:21 -0400
    #   value
    # 1     7
    # 2    15
    # 3    20
    

    如果属性出现在某些而不是其他中,请考虑与预先确定的名称列表进行匹配,并反复填写NAs。以下是使用 sapply()for 循环和第二个列表参数的两个版本:

    recordnames <- c("type", "unit", "sourceName", "device", "sourceVersion", 
                     "creationDate", "startDate", "endDate", "value")
    
    # FOR LOOP VERSION
    recordAttribs <- sapply(recordAttribs, function(i) {
      for (r in recordnames){
        i[r] <- ifelse(is.null(i[r]), NA, i[r])
      }
      i <- i[recordnames]  # REORDER INNER VECTORS
      return(i)
    })
    
    # TWO LIST ARGUMENT SAPPLY
    recordAttribs <- sapply(recordAttribs, function(i,r) {  
        if (is.null(i[r])) i[r] <- NA
            else i[r] <- i[r]         
        i <- i[recordnames]  # REORDER INNER VECTORS
        return(i)
    }, recordnames)
    
    
    df <- data.frame(t(recordAttribs))
    

    【讨论】:

    • 感谢它对我提供的测试数据非常有效。当我回去尝试将其应用于完整数据集时,我意识到有些记录有 9 列而不是 7 列,即 &lt;Record type="HKQuantityTypeIdentifierFlightsClimbed" sourceName="Ryan Praskievicz iPhone" sourceVersion="9.3.2" device="&amp;lt;&amp;lt;HKDevice: 0x15a4af3f0&amp;gt;, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone8,1, software:9.3.2&amp;gt;" unit="count" creationDate="2016-06-02 12:27:46 -0400" startDate="2016-06-02 12:09:29 -0400" endDate="2016-06-02 12:09:29 -0400" value="1"/&gt; 它不起作用。有什么想法吗?
    • 您知道要保留通用属性还是全部?你事先知道要保留哪些属性吗?
    • 是的,我想保留向量中的所有 9 行,并且只为具有 7 行的向量设置 NA。
    • 查看更新,调整 9 中可能存在或不存在的任何属性。
    【解决方案2】:

    另一个选项是xmlAttrsToDataFrame,它应该处理缺失的属性。您还可以获取具有特定属性的标签,例如设备

    XML:::xmlAttrsToDataFrame(xml["//Record"])
    XML:::xmlAttrsToDataFrame(xml["//Record[@device]"])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-16
      • 1970-01-01
      • 2014-05-05
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多