我有数百个文本文件,每个文件中包含以下信息:
*****Auto-Corelation Results******
1 .09 -.19 .18 non-Significant
*****STATISTICS FOR MANN-KENDELL TEST******
S= 609
VAR(S)= 162409.70
Z= 1.51
Random : No trend at 95%
*****SENs STATISTICS ******
SEN SLOPE = .24
现在,我想阅读所有这些文件,并从每个文件(例如.24
)“收集” Sen的统计信息,并将其与相应的文件名一起编译成一个文件。我必须在R中完成。
我使用过CSV文件但不知道如何使用文本文件。
这是我现在使用的代码:
require(gtools)
GG <- grep("*.txt", list.files(), value = TRUE)
GG<-mixedsort(GG)
S <- sapply(seq(GG), function(i){
X <- readLines(GG[i])
grep("SEN SLOPE", X, value = TRUE)
})
spl <- unlist(strsplit(S, ".*[^.0-9]"))
SenStat <- as.numeric(spl[nzchar(spl)])
SenStat<-data.frame( SenStat,file = GG)
write.table(SenStat, "sen.csv",sep = ", ",row.names = FALSE)
当前代码无法正确读取所有值并出现此错误:
Warning message:
NAs introduced by coercion
另外,我没有将文件名作为Output的另一列。请帮忙!
代码也在读取=符号。这是print(spl)的输出
[1] "" "5.55" "" "-.18" "" "3.08" "" "3.05" "" "1.19" "" "-.32"
[13] "" ".22" "" "-.22" "" ".65" "" "1.64" "" "2.68" "" ".10"
[25] "" ".42" "" "-.44" "" ".49" "" "1.44" "" "=-1.07" "" ".38"
[37] "" ".14" "" "=-2.33" "" "4.76" "" ".45" "" ".02" "" "-.11"
[49] "" "=-2.64" "" "-.63" "" "=-3.44" "" "2.77" "" "2.35" "" "6.29"
[61] "" "1.20" "" "=-1.80" "" "-.63" "" "5.83" "" "6.33" "" "5.42"
[73] "" ".72" "" "-.57" "" "3.52" "" "=-2.44" "" "3.92" "" "1.99"
[85] "" ".77" "" "3.01"
我发现了问题。负号有点棘手。在某些文件中它是
SEN SLOPE =-1.07
SEN SLOPE = -.11
由于=之后的差距,我正在为第一个获得NAs,但代码正在读取第二个。如何修改正则表达式来解决这个问题?谢谢!
答案 0 :(得分:10)
假设"text.txt"
是您的一个文本文件。使用readLines
读入R,您可以使用grep
查找包含SEN SLOPE
的行。如果没有其他参数,grep
将返回找到正则表达式的元素的索引号。在这里,我们发现它是第11行。添加value = TRUE
参数以获取读取的行。
x <- readLines("text.txt")
grep("SEN SLOPE", x)
## [1] 11
( gg <- grep("SEN SLOPE", x, value = TRUE) )
## [1] "SEN SLOPE = .24"
要查找工作目录中的所有.txt
个文件,我们可以将list.files
与正则表达式一起使用。
list.files(pattern = "*.txt")
## [1] "text.txt"
循环播放多个文件
我创建了第二个文本文件text2.txt
,其中包含不同的SEN SLOPE
值,以说明如何将此方法应用于多个文件。我们可以使用sapply
,然后使用strsplit
来获取所需的spl
值。
GG <- list.files(pattern = "*.txt")
S <- sapply(seq_along(GG), function(i){
X <- readLines(GG[i])
ifelse(length(X) > 0, grep("SEN SLOPE", X, value = TRUE), NA)
## added 04/23/14 to account for empty files (as per comment)
})
spl <- unlist(strsplit(S, split = ".*((=|(\\s=))|(=\\s|\\s=\\s))"))
## above regex changed to capture up to and including "=" and
## surrounding space, if any - 04/23/14 (as per comment)
SenStat <- as.numeric(spl[nzchar(spl)])
然后我们可以将结果放入数据框并将其发送到write.table
( SenStatDf <- data.frame(SenStat, file = GG) )
## SenStat file
## 1 0.46 text2.txt
## 2 0.24 text.txt
我们可以用
将其写入文件write.table(SenStatDf, "myFile.csv", sep = ", ", row.names = FALSE)
2014年7月21日更新:
由于结果正在写入文件,因此使用
可以更简单(更快)( SenStatDf <- cbind(
SenSlope = c(lapply(GG, function(x){
y <- readLines(x)
z <- y[grepl("SEN SLOPE", y)]
unlist(strsplit(z, split = ".*=\\s+"))[-1]
}), recursive = TRUE),
file = GG
) )
# SenSlope file
# [1,] ".46" "test2.txt"
# [2,] ".24" "test.txt"
然后用
写入并读入R.write.table(SenStatDf, "myFile.txt", row.names = FALSE)
read.table("myFile.txt", header = TRUE)
# SenSlope file
# 1 1.24 test2.txt
# 2 0.24 test.txt
答案 1 :(得分:4)
首先制作一个示例文本文件:
cat('*****Auto-Corelation Results******
1 .09 -.19 .18 non-Significant
*****STATISTICS FOR MANN-KENDELL TEST******
S= 609
VAR(S)= 162409.70
Z= 1.51
Random : No trend at 95%
*****SENs STATISTICS ******
SEN SLOPE = .24',file='samp.txt')
然后阅读:
tf <- readLines('samp.txt')
现在提取相应的行:
sen_text <- grep('SEN SLOPE',tf,value=T)
然后得到超过等号的值:
sen_value <- as.numeric(unlist(strsplit(sen_text,'='))[2])
然后将这些结果合并到每个文件中(原始问题中没有提到的文件结构)
答案 2 :(得分:1)
如果您的文本文件始终采用该格式,(例如Sen Slope始终位于第11行)并且文本与您的所有文件完全相同,则只需两行即可完成所需的文本。
char_vector <- readLines("Path/To/Document/sample.txt")
statistic <- as.numeric(strsplit(char_vector[11]," ")[[1]][5])
那会给你0.24。
然后通过apply语句或for循环遍历所有文件。
为清楚起见:
> char_vector[11]
[1] "SEN SLOPE = .24"
和
> strsplit(char_vector[11]," ")
[[1]]
[1] "SEN" "SLOPE" "=" "" ".24"
因此你想要strsplit的结果[[1]] [5]。
答案 3 :(得分:1)
步骤1:将完整fileNames
保存在单个变量中:
fileNames <- dir(dataDir,full.names=TRUE)
步骤2:让我们读取并处理其中一个文件,并确保它给出正确的结果:
data.frame(
file=basename(fileNames[1]),
SEN.SLOPE= as.numeric(tail(
strsplit(grep('SEN SLOPE',readLines(fileNames[1]),value=T),"=")[[1]],1))
)
步骤3:在所有fileNames
do.call(
rbind,
lapply(fileNames,
function(fileName) data.frame(
file=basename(fileName),
SEN.SLOPE= as.numeric(tail(
strsplit(grep('SEN SLOPE',
readLines(fileName),value=T),"=")[[1]],1)
)
)
)
)
希望这会有所帮助!!