我有一个文件格式有点奇怪,如下:
Cluster 1 Score:3.96
Category Term Count
GOTERM_BP_FAT GO:0006412 34
KEGG_PATHWAY hsa00970 9
GOTERM_BP_FAT GO:0043038 9
GOTERM_BP_FAT GO:0043039 9
Cluster 2 Score:3.94
Category Term Count
GOTERM_BP_FAT GO:0006414 21
KEGG_PATHWAY hsa03010 20
GOTERM_BP_FAT GO:0034660 16
GOTERM_BP_FAT GO:0006399 11
GOTERM_BP_FAT GO:0042254 10
GOTERM_BP_FAT GO:0022613 12
...还有几个“子数据帧”(包括中间空格)和Cluster X
行之后的行的附加(此处省略)列。
我想做的是以某种方式读取每个单独的簇,将其作为数据帧(即名称为Category, Term, Count
的数据帧),稍微操纵数据帧(根据计算添加列,大多数情况下)然后将操作数据框和Cluster X
行写入一个与其开始时格式完全相同的新文件。
我已经绞尽脑汁想要做一些聪明的方法,但除了分别阅读每一行并根据行的类型做不同的事情之外,我还没有真正想出任何东西,比如:
con <- file('test.txt', open="r")
# Read file line for line
while ( length(currentLine <- readLines(con, n=1, warn=FALSE)) > 0 ) {
line = strsplit(currentLine, '\t')[[1]]
# Save previous data, initiate new cluster name/score
if ( grepl('Annotation Cluster', line[1]) ) {
# Save previous data if available
if ( exists('currentData') ) {
## save the current data somehow
}
# Initiate new
clusterInfo = line
}
# Initiate new, empty data frame
else if ( grepl('Category', line[1]) ) {
currentData = data.frame(t(rep(NA, length(line))))
names(currentData) = line
}
# Add data to data frame
else if ( grepl('GOTERM', line[1]) || grepl('KEGG', line[1]) ) {
currentData = rbind(currentData, line)
# Delete NAs if line row
if ( nrow(currentData) == 2 ) {
currentData = na.omit(currentData)
}
}
}
以上显然没有完成(我不确定如何将clusterInfo
与currentData
一起保存为相同的格式),但我希望我能理解。我并不是真的太喜欢这种方法,但是对我来说,像这样逐行创建数据帧似乎很奇怪,并且在你启动的同时尝试保存数据下一个数据块的开始。
有没有更好的方法呢?
答案 0 :(得分:5)
您可以从我的GitHub read.mtable
尝试"SOfun" package。
用法如下:
library(SOfun)
read.mtable(x, "Cluster", header = TRUE) ## Replace "x" with your file name
# $`Cluster 1 Score:3.96`
# Category Term Count
# 1 GOTERM_BP_FAT GO:0006412 34
# 2 KEGG_PATHWAY hsa00970 9
# 3 GOTERM_BP_FAT GO:0043038 9
# 4 GOTERM_BP_FAT GO:0043039 9
#
# $`Cluster 2 Score:3.94`
# Category Term Count
# 1 GOTERM_BP_FAT GO:0006414 21
# 2 KEGG_PATHWAY hsa03010 20
# 3 GOTERM_BP_FAT GO:0034660 16
# 4 GOTERM_BP_FAT GO:0006399 11
# 5 GOTERM_BP_FAT GO:0042254 10
# 6 GOTERM_BP_FAT GO:0022613 12
如您所见,“群集”信息将保留为列表名称。因此,您可以继续使用lapply
进行您需要做的任何计算,然后以您需要的任何形式重新编写数据。
可重复的样本数据:
x <- tempfile()
writeLines("Cluster 1 Score:3.96
Category Term Count
GOTERM_BP_FAT GO:0006412 34
KEGG_PATHWAY hsa00970 9
GOTERM_BP_FAT GO:0043038 9
GOTERM_BP_FAT GO:0043039 9
Cluster 2 Score:3.94
Category Term Count
GOTERM_BP_FAT GO:0006414 21
KEGG_PATHWAY hsa03010 20
GOTERM_BP_FAT GO:0034660 16
GOTERM_BP_FAT GO:0006399 11
GOTERM_BP_FAT GO:0042254 10
GOTERM_BP_FAT GO:0022613 12", con = x, sep = "\n")
答案 1 :(得分:1)
您可以使用readLines
和split
来读取文件,并使用基于具有“群集”的行创建的数字索引('indx')。使用read.table
读取列表元素,创建两个新列('Cluster'和'Score')并对列表元素进行rbind以创建单个数据集。
lines <- readLines('Clusterfile.txt')
indx <- cumsum(grepl('^Cluster', lines))
res <- do.call(rbind,lapply(split(lines, indx), function(x) {
d1 <-read.table(text=x[-1], header=TRUE, stringsAsFactors=FALSE)
d2 <- read.table(text=gsub('[^0-9.]+', ' ', x[1]),
col.names=c('Cluster', 'Score'))
cbind(d1, d2)}))
row.names(res) <- NULL
head(res,3)
# Category Term Count Cluster Score
#1 GOTERM_BP_FAT GO:0006412 34 1 3.96
#2 KEGG_PATHWAY hsa00970 9 1 3.96
#3 GOTERM_BP_FAT GO:0043038 9 1 3.96