如何按时间顺序搜索文本中的某些元素以创建简化的数据框

时间:2019-07-11 09:40:43

标签: r string function loops apply

数据简介

我有一个文本文件文档或csv,其中包含网站的编码,而我无法将数据导出到Excel工作表。这意味着数据本身就是一堆代码,其中的元素由某些文本位来区分。

了解数据

Fx。每个变量以<a:FN>开头。变量x中的每个元素都有一个以<a:DT>...开头的代码 y的代码以<a:KY>...开头,其中该元素的值以<a:VL>开头。 每个变量的编码以及与此变量相关的基础代码均以<a:PLI>开头。

数据结构

So the structure of the file is as following: 


   `<a:PLI>`
      <a:DT>...
       `<a:FN>...` 
          `<a:KY>...`
           <a:VL>...
    `<a:PLI>`
      <a:DT>...
       `<a:FN>...` 
           `<a:KY>...`
            <a:VL>...

当导入到R中时,数据框仅具有1列,总计大约为1。 35.000行。每段代码都有自己的行。

我想做的事和预期的结果

我想做的就是将这个复杂的文本文件转换成一个新的数据框,其中包含我感兴趣的所有元素。

例如,对于每个组/变量(a<:FN),我想找到X (<a:DT>),然后在其中找到组织机构键的Y (<a:KY>org-key</a:KY>)和Z (<a:VL) 。 我想对所有组/变量中的所有X都执行此操作,从而得到一个输出,其中每个X都按照其尊重的Y和Z值进行分组。

我不确定如何解决我的问题。我以为可能是for循环,或者使用诸如sapply之类的应用族中的方法。坦白说,我不确定从哪里开始,这就是为什么我要伸出援手。

我打算做的是设置一个描述我要做什么的函数:

bespoke <- function (x) {

find x in df      ## X could be one of the varaibles I am looking for
find y after x    ## Find y for x in df
find z after x    ## find z for x in df
return all elements to a df  ## I wnat to repeat this function for all variables in df. 
}

df2 <- adply(keys, bespoke) 

我不习惯使用函数,所以我甚至都不知道该如何开始,这还因为我有很多底层函数要跟踪。

我希望有人能帮助我前进。

数据部分:

    <a:PLI>
       <a:DT>False</a:DT>
       <a:DTR>False</a:DTR>
       <a:Desc>text text text</a:Desc>
       <a:FN>Type</a:FN>
       <a:PSPS>
          <a:PSP>
             <a:KY>org-group</a:KY>
             <a:VL>40100</a:VL>
          </a:PSP>
          <a:PSP>
             <a:KY>org-key</a:KY>
             <a:VL>60205</a:VL>
          </a:PSP>
          <a:PSP>
             <a:KY>org-systemkey</a:KY>
             <a:VL>1005</a:VL>
          </a:PSP>
          <a:PSP>
             <a:KY>org-report-type</a:KY>
             <a:VL>text text text</a:VL>
          </a:PSP>
       </a:PSPS>
       <a:TI>80200</a:TI>
    </a:PLI>
    <a:PLI>
       <a:DT>Room</a:DT>
       <a:DTR>Room</a:DTR>
       <a:Desc/>
       <a:FN>StartRoom</a:FN>
       <a:PSPS>
          <a:PSP>
             <a:KY>org-group</a:KY>
             <a:VL>13020</a:VL>
          </a:PSP>
          <a:PSP>
             <a:KY>org-key</a:KY>
             <a:VL>13130</a:VL>
          </a:PSP>
       </a:PSPS>
       <a:TI>12500</a:TI>
    </a:PLI>
    <a:PLI>
       <a:DT>Other room</a:DT>
       <a:DTR>Other room</a:DTR>
       <a:Desc/>
       <a:FN>StartRoom</a:FN>
       <a:PSPS>
          <a:PSP>
             <a:KY>org-group</a:KY>
             <a:VL>11160</a:VL>
          </a:PSP>
          <a:PSP>
             <a:KY>org-key</a:KY>
             <a:VL>15152</a:VL>
          </a:PSP>
       </a:PSPS>
       <a:TI>15552</a:TI>
    </a:PLI>

2 个答案:

答案 0 :(得分:1)

(很抱歉以前的错误答案,我错过了您问题的重要部分)

这是我要这样做的方式:

  1. 将文本包装在一对标签中,以便它是有效的xml(即添加根节点)
  2. 删除所有的“ a:”(命名空间前缀)

然后,在R中:

library(xml2)
foo <- read_xml("tmp.xml")

# convert to a nodeset
allplis <- xml_find_all(foo, "//PLI")

xtractpli <- function(x) {
  dt <- xml_text(xml_find_first(x, "DT"))
  fn <- xml_text(xml_find_first(x, "FN"))
  orgkey <- xml_find_first(x, "PSPS/PSP[KY='org-key']")
  orgkey <- xml_text(xml_find_first(orgkey, "VL"))
  return(c(fn, dt, orgkey))
}

t(sapply(allplis, xtractpli))

结果:

     [,1]        [,2]         [,3]   
[1,] "Type"      "False"      "60205"
[2,] "StartRoom" "Room"       "13130"
[3,] "StartRoom" "Other room" "15152"

这是您想要的吗?

答案 1 :(得分:1)

您实际上正在处理一种XML,其中a之前的:被称为其“命名空间”。假设其余数据与您提供的示例相似,则可以使用以下代码提取数据,其中s是您提供的数据(您需要替换s和您的文件名):

library(rvest)
library(purrr)
library(dplyr)

vars <- c("dt", "dtr", "desc", "fn", "ti", "ky", "vl")

read_html(s) %>% 
    html_nodes("pli") %>% 
    unclass() %>% 
    map_df(~ map2(list(.), vars, ~ html_text(html_nodes(.x, .y))) %>% 
               set_names(vars) %>% 
               as_tibble,
           .id = "pli"
           )

我使用read_html而不是read_xml,因为在这种情况下,它可以很好地解析XML,而且我不喜欢在名称空间周围闲逛。我不能保证这将一直有效。在示例数据中似乎只有一个命名空间,所以也许您会没事的。

此后,我使用pli拉出三个html_nodes节点,然后使用unclass将XML节点集转换为列表。在map_df中,我遍历三个列表元素(三个pli节点)中的每一个,并应用map2,在其中使用vars中的值拉出所有相关节点并将输出存储在小标题中。结果应如下所示:

# A tibble: 8 x 8
  pli   dt         dtr        desc           fn        ti    ky              vl            
  <chr> <chr>      <chr>      <chr>          <chr>     <chr> <chr>           <chr>         
1 1     False      False      text text text Type      80200 org-group       40100         
2 1     False      False      text text text Type      80200 org-key         60205         
3 1     False      False      text text text Type      80200 org-systemkey   1005          
4 1     False      False      text text text Type      80200 org-report-type text text text
5 2     Room       Room       ""             StartRoom 12500 org-group       13020         
6 2     Room       Room       ""             StartRoom 12500 org-key         13130         
7 3     Other room Other room ""             StartRoom 15552 org-group       11160         
8 3     Other room Other room ""             StartRoom 15552 org-key         15152