我希望有人可以帮我解决数据导入问题,我认为这可能是一个简单的解决方法,但还没有找到答案。我有大量包含天线扫描的txt文件,我需要以统一配置导入它们。问题是它们在实际数据开始之前都包含有关天线的不规则数量的诊断数据。我需要一个能够识别实际数据何时开始的函数,然后我可以使用正确的列中的正确数据导入它。基本上,对于每个文件,我需要识别诊断代码的行数,因此当使用read.delim或类似的东西输入文件时,我可以指定skip =“”。
下面是我正在谈论的其中一个文件的示例:
Power OFF @ 12:05:50 02/15/13
Power ON @ 12:06:03 02/15/13
Reader #1 12:06:03 02/15/13
Reader #2 12:06:03 02/15/13
Battery Voltage = 13.35 @ 13:00:00 02/15/13
Battery Voltage = 13.42 @ 14:00:00 02/15/13
Battery Voltage = 13.32 @ 15:00:00 02/15/13
Battery Voltage = 13.55 @ 16:00:00 02/15/13
Reader #2 02:57:40 02/17/13 LA 900 226000012999
Reader #2 02:57:40 02/17/13 LA 900 226000012999
Reader #2 02:57:40 02/17/13 LA 900 226000012999
Reader #2 02:57:40 02/17/13 LA 900 226000012999
答案 0 :(得分:2)
read.table
如果您使用readLines
逐行阅读文本,则可以使用grep
搜索与“电池电压”匹配的最高行号,并将其用于{{1 }}
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
( f ixed w 宽度 f ile)可能更有意义。您需要使用read.fwf
,na.omit
或其他一些消除空行的方法,因为complete.cases
不接受像{{1}这样的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
但这种方法有点不稳定,所以只有在你能够验证它是否正常工作时才应该使用。
答案 1 :(得分:0)
您是否一直在寻找“电池电压”最后一行之后的第一行?如果是这样,试试这个:
the.file <- readLines("C:\\Users\\myfile.txt")
row.to.begin.skip.at <- tail(grep("Battery Voltage", the.file), 1)
然后在您首选的阅读功能中设置skip=row.to.begin.skip.at
。这里的grep()函数在每行搜索短语“Battery Voltage”,然后返回包含该短语的所有行号的列表。 tail(,1)函数返回包含短语的最后一行。
答案 2 :(得分:0)
您可以将文件作为文本块读取,并使用DT[,.(MEDIAN_GRADE = median(GRADE)) , .(GROUP)][
dcast(DT, GROUP ~ ADVANCED, length), on = 'GROUP']
标识要删除的行。在这里,我将您的文本块存储在grep
中。假设您的标题一直到test.txt
部分,您可以先识别包含Battery Voltage
的行号,然后找到它的最后一个实例。这将是要跳过的行数。
Battery
然后你应该读好你的数据。
con = file('test.txt', 'r')
text = readLines(con)
close(con)
lines_to_skip = max(grep('Battery',text))
答案 3 :(得分:0)
略有变化。这将返回以 Reader 开头的每一行,并包含由空格分隔的7个元素。我注意到前两个 Reader 行更短,如果情况总是如此,那么这当然不起作用。
antenna0 <- readLines("antenna.txt")
antenna0 <- antenna0[grep("^Reader", antenna0)]
antenna <- strsplit(antenna0, " ")
data.frame(do.call(rbind, antenna[sapply(antenna, length) == 7]))
# X1 X2 X3 X4 X5 X6 X7
#1 Reader #2 02:57:40 02/17/13 LA 900 226000012999
#2 Reader #2 02:57:40 02/17/13 LA 900 226000012999
#3 Reader #2 02:57:40 02/17/13 LA 900 226000012999
#4 Reader #2 02:57:40 02/17/13 LA 900 226000012999
我想您可以使用更高级的正则表达式直接在grep
中执行此操作,但我没有排版。
编辑:
稍微改善依赖于grep
:
antenna0 <- readLines("antenna.txt")
antenna1 <- antenna0[grep("^Reader.*[\\s{4,}]", antenna0)]
antenna2 <- do.call(rbind, strsplit(antenna1, " "))
data.frame(antenna3)
# X1 X2 X3 X4 X5 X6 X7
#1 Reader #2 02:57:40 02/17/13 LA 900 226000012999
#2 Reader #2 02:57:40 02/17/13 LA 900 226000012999
#3 Reader #2 02:57:40 02/17/13 LA 900 226000012999
#4 Reader #2 02:57:40 02/17/13 LA 900 226000012999
简短的解释者:
[\\s{4,}]
表示将返回包含数字(\\s
)中四个或更多空格({4,}
)的任何字符串。
^Reader
表示将返回以字母序列 Reader 开头的任何字符串。
.*
结合了两种模式,作为AND运算符。