read.table
如果您使用readLines 逐行读取文本,则可以使用grep 搜索与“电池电压”匹配的最高行号并将其用于skip。
read.table(file.txt,
skip = max(grep('Battery Voltage', readLines(file.txt))),
# set comment delimiting character to anything besides "#"
comment.char = '')
## V1 V2 V3 V4 V5 V6 V7
## 1 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
## 2 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
## 3 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
## 4 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
请注意,需要进一步清理(合并列、格式化日期)。
read.fwf
如果列宽一致,使用read.fwf (fixed width file) 可能更有意义。您需要使用na.omit、complete.cases 或其他一些方法来消除空白行,因为read.fwf 不接受blank.lines.skip 参数,如read.table 及其变体:
na.omit(read.fwf(file.txt,
widths = c(9, -1, 17, -1, 2, -1, 3, -1, 12),
skip = max(grep('Battery Voltage', readLines(file.txt))),
comment.char = ''))
## V1 V2 V3 V4 V5
## 2 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
## 4 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
## 6 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
## 8 Reader #2 02:57:40 02/17/13 LA 900 2.26e+11
但是,通过计数字符来计算列宽是一件很痛苦的事情(而且容易出错)。
readr::read_fwf
readr 包使处理固定宽度文件的烦恼稍微减轻了一些,并在事情没有得到理想解析时给出有用的警告。它还提供参数以在您读取数据时解析日期和日期时间,这很方便:
library(readr)
df <- read_fwf(file.txt,
fwf_widths(c(9, 18, 3, 4, NA)),
col_types = list('c', col_datetime('%H:%M:%S %m/%d/%y'),'c', 'i', 'd'),
skip = max(grep('Battery Voltage', readLines(file.txt))))
df <- df[complete.cases(df), ]
# or df <- na.omit(df)
# or if some NAs are possible, more robust:
# df <- df[colSums(!apply(df, 1, is.na)) > 0, ]
df
## # A tibble: 4 x 5
## X1 X2 X3 X4 X5
## <chr> <time> <chr> <int> <dbl>
## 1 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
## 2 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
## 3 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
## 4 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
注意解析得很好的日期时间和稍微简单的列宽输入方法(你可以用fwf_empty 让它猜测,如果你有列名,这很好用)。
如果您的宽度和列类型正确,任何不正确的都将输入为NA,因此如果您使用na.omit,则可以完全避免使用skip 参数:
na.omit(read_fwf(file.txt,
fwf_widths(c(9, 18, 3, 4, 13)),
col_types = list('c', col_datetime('%H:%M:%S %m/%d/%y'),'c', 'i', 'd')))
## # A tibble: 4 x 5
## X1 X2 X3 X4 X5
## <chr> <time> <chr> <int> <dbl>
## 1 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
## 2 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
## 3 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
## 4 Reader #2 2013-02-17 02:57:40 LA 900 2.26e+11
不过,这种方法有些不稳定,因此只有在您能够验证其工作正常时才应使用。