也许不是最好的主意,但这应该可行:
content <- scan('filepath','character',sep='~') # Warning choose a sep not appearing in datas to get the whole file.
# Split content in lines:
lines <- regmatches(content,gregexpr('.{60}',content))[[1]]
x <- tempfile()
write(lines,x)
data <- read.fwf(x, widths = c(8,4,7,41))
unlink(x)
这个想法是读取整个文件,将每次出现的 60 个字符放入一个条目中,将其写入临时文件,并在删除临时文件之前从该临时文件中读取数据。
另一种方法是使用正则表达式和包stringr
(仍然包含上面扫描得到的内容):
library(stringr)
d <- data.frame( str_match_all( content, "(.{8})(.{4})(.{7})(.{41})")[[1]][,2:5], stringsAsFactors=FALSE)
这使:
V1 V2 V3 V4
1 20141101 77h 3.210 0 3
2 20141102 76h 3.090 0 3
str_match_all
返回一个列表,这里有 1 个元素,因为只有一行作为输入,所以我们将其删除[[1]]
.
现在返回的是 5 列,第一列是完全匹配,其他列是捕获组,因此我们在第 2 列到第 5 列上对矩阵进行子集化,以仅获取我们需要的 4 列并将其包装在其中as.data.frame
最后得到一个 data.frame 。
然后你可以用以下方式命名列colnames(d) <- c('date','time','data_point','rest')
如果您想清理空格,可以将 str_extract_all 结果包装在trimws
(感谢@jaap提醒这个功能)像这样:
td <- data.frame( trimws( str_match_all( content, "(.{8})(.{4})(.{7})(.{41})")[[1]][,2:5] ), stringsAsFactors=FALSE)
Output:
X1 X2 X3 X4
1 20141101 77h 3.210 0 3
2 20141102 76h 3.090 0 3