我正在尝试将一系列自定义数据文件导入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>
答案 0 :(得分:0)
除非您先进行搜索和替换,否则错误的斜杠会阻碍任何使用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
然后我得到一个数据框(你需要根据你对该部分的理解来重写这个)。
如果标签是嵌套的,它会做奇怪的事情,但我怀疑这种文件格式是否会有。
足够快/足够有效吗?在您对数据进行尝试之前我们不会知道,但它至少是一种解决方案。
答案 1 :(得分:0)
抱歉,我在这里弄得一团糟,但我是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)
}