【问题标题】:r data import custom markupr 数据导入自定义标记
【发布时间】:2014-02-11 08:19:59
【问题描述】:

我正在尝试将一系列自定义数据文件导入 R。

文件被组织成块,由类似 XML 的标记标签标记。我知道这些文件不是真正的 XML 文件,它们不包含标记语言的定义。

每个块可以是单行或制表符分隔的矩阵。评论往往用 % 标记

这些文件大约 10K 行长,每个文件我需要大约 2700 行,所以我宁愿避免循环。此外,文件长度和所需行数也会因一些不可预测的因素而有所不同。

我尝试了 XML 包中的一些方法,但总是遇到一堆错误,例如“StartTag:无效元素名称”和“标记 MERGED-PUPIL-DATA 行 5443 中的数据过早结束”。

你有什么想法吗?有没有接受自定义标记标签的方法?

一个典型的文件可能看起来像这样(点表示我剪掉的东西)

<SESSION>
<VERSION>
2
<\VERSION>
<DATE>
2014-01-20 14:29:43
<\DATE>
<SUBJECT-ID>
SUB001
<\SUBJECT-ID>
<NOTE>
red300os
<\NOTE>
<MIN-MAX-PLOT>
0.100000 8707.554688
<\MIN-MAX-PLOT>
<STIMULUS-DEFINED>
redOS300
Default Human Relative Spectral Sensitivity
1   0
1   10.000000   20.000000   60.000000   1   3   2.000000    -100.000000 0.000000    0.000000    1
<\STIMULUS-DEFINED>
.
.
.
.
.
.
<MERGED-PUPIL-DATA>
% time is in sec; diameter is in mm; loci is in pixel; color code -> 100 = unknown, 0 = white, 1 = red, 2 = green, 3 = blue; intensity is in Lux or W/m2
% real time logical time    R. valid    R. diameter R. x loci    R. y loci  L. valid    L. diameter L. x loci    L. y loci  R. led color     R. led intensity   L. led color    L. led intensity
2703
-0.049000   -0.049000   1   5.483765    266.668732  268.837402  1   5.441666    272.687500  272.724976  100 0.000000    100 0.000000
-0.018000   -0.018000   1   5.478448    265.918732  267.837402  1   5.438361    270.687500  273.406219  100 0.000000    100 0.000000
.
.
.
.
89.932000   89.932000   1   5.604879    289.575165  273.574738  1   5.255306    301.056091  303.812744  3   0.000000    3   0.000000
89.964000   89.964000   1   5.650856    289.575165  269.574738  1   5.255306    301.056091  301.812744  3   0.000000    3   0.000000
<\MERGED-PUPIL-DATA>
.
.
.
<\SESSION>

【问题讨论】:

  • 如果 是 s,我认为它更像是有效的 XML
  • 如果可以接受外部工具并且你有一个 unix 工具集,我会使用 awk 来匹配你想要的部分并将它们剪切成 R 可以读取的新文件。
  • 你能发布一个完整数据集的链接吗?我认为您的问题之一是color code -&gt; 100=unknown,。 XML 包不喜欢元素文本中的&lt;&gt;

标签: xml r markup data-import


【解决方案1】:

除非您首先进行搜索和替换,否则错误方向的斜杠会阻止任何使用 XML 处理的尝试。另一种方法是将文件按行读取并搜索标签。

读取数据文件:

txt = readLines("dummy.txt")

这是一个在匹配标签之间返回文本的函数,作为一个列表,以防有多个部分:

getSection <- function(txt, tag){
    start=paste0("^<",tag,">$")
    end = paste0("^<\\\\",tag,">$") 
    startLines = grep(start,txt)
    endLines = grep(end,txt)
    lapply(1:length(startLines),function(i){
        txt[(startLines[i]+1):(endLines[i]-1)]
    })
}

例如,测试文件包含:

<DATE>
2014-01-20 14:29:43
<\DATE>
<DATE>
Never!
<\DATE>

我明白了:

> getSection(txt,"DATE")
[[1]]
[1] "2014-01-20 14:29:43"

[[2]]
[1] "Never!"

建议您为要解析的各个部分编写包装此函数的函数,例如,我稍微编辑了您的文件以使该部分更具规律性:

<STIMULUS-DEFINED>
redOS300
Default Human Relative Spectral Sensitivity
1   10.000000   20.000000   60.000000   1   
3   2.000000    -100.000000 0.000000    0.000000 
<\STIMULUS-DEFINED>

然后写:

getStimulusDefined <- function(lines){
    section = getSection(lines,"STIMULUS-DEFINED")[[1]] # only one of these
    data = read.table(textConnection(section),skip=1,head=TRUE)
    data
}

所以我可以这样做:

> getStimulusDefined(txt)
  Default Human Relative Spectral Sensitivity
1       1    10       20       60           1
2       3     2     -100        0           0

然后我得到一个数据框(您需要根据您对该部分的理解重写它)。

如果标签是嵌套的,它会做一些奇怪的事情,但我怀疑这种文件格式会有这种情况。

它是否足够快/足够高效?在您对自己的数据进行尝试之前,我们不会知道,但这至少是一个解决方案。

【讨论】:

  • 感谢您的回答。你的方法被证明是非常有效的。我曾假设(错误地!)任何涉及 readLines 的方法都会太慢。尽管您的函数在定义中使用了参数“lines”和“tag”,但在语句中使用了“txt”和“tag”,但函数中存在轻微错误。我假设“行”在这两个地方都应该是“txt”。
  • 是的,当然,当我开发这个时,我已经将文本读入 txt 并且在函数内部匹配而不是名称 lines 参数。已编辑。好地方。
【解决方案2】:

对不起,我在这里搞得一团糟,但我是 Stackoverflow 的新手。我想对 Spacedman 的出色答案进行一些扩展,但无法在评论中获得我的代码。

我已经修改了 Spacedman 的函数,使其具有更通用的函数来读取数据帧。

startSkip 和 endSkip 参数可用于忽略每个块的开头和结尾处的行。

至少我的文件工作似乎相当快。

getSection <- function(file, tag,startSkip=0,endSkip=0){
  txt<-readLines(file)
  start=paste0("^<",tag,">$")
  end = paste0("^<\\\\",tag,">$") 
  startLines = grep(start,txt)
  endLines = grep(end,txt)
  noLines=endLines-startLines-startSkip-endSkip-1
  read.table(file,skip=startLines+startSkip,nrows=noLines)  
}

【讨论】:

  • 我将文件的读取与部分的提取分开,因为这样您就不需要每次都读取整个文件来提取每个标记的部分。
  • 这很好。尽管即使我每次都读取文件,它似乎也运行得很快,但最好避免这种情况。我只是不太清楚如何在不使用 read.table() 和整个文件的情况下读取数据框
  • 对不起,我看到你已经有了解决方案。我想我应该更好地阅读您的答案!
猜你喜欢
  • 2018-05-04
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
相关资源
最近更新 更多