【问题标题】:Text file to list in R在 R 中列出的文本文件
【发布时间】:2011-09-29 23:31:41
【问题描述】:

我有一个大文本文件,每行中的字段数量可变。每行中的第一个条目对应于一个生物通路,每个后续条目对应于该通路中的一个基因。前几行可能如下所示

path1   gene1 gene2
path2   gene3 gene4 gene5 gene6
path3   gene7 gene8 gene9

我需要将这个文件作为一个列表读入R中,每个元素都是一个字符向量,列表中每个元素的名称是该行的第一个元素,例如:

> pathways <- list(
+     path1=c("gene1","gene2"), 
+     path2=c("gene3","gene4","gene5","gene6"),
+     path3=c("gene7","gene8","gene9")
+ )
> 
> str(pathways)
List of 3
 $ path1: chr [1:2] "gene1" "gene2"
 $ path2: chr [1:4] "gene3" "gene4" "gene5" "gene6"
 $ path3: chr [1:3] "gene7" "gene8" "gene9"
> 
> str(pathways$path1)
 chr [1:2] "gene1" "gene2"
> 
> print(pathways)
$path1
[1] "gene1" "gene2"

$path2
[1] "gene3" "gene4" "gene5" "gene6"

$path3
[1] "gene7" "gene8" "gene9"

...但我需要为数千行自动执行此操作。我看到了similar question posted here previously,但我无法从该线程中弄清楚如何做到这一点。

提前致谢。

【问题讨论】:

  • 查看这篇文章以获得灵感,可能帮助stackoverflow.com/questions/6592850/…
  • 感谢大家提供多样而优雅的解决方案。在不到一个小时的时间内 4 个有效答案是我使用 SO 的原因。非常感谢。

标签: list r text statistics


【解决方案1】:

另一种解决方案:

sl <- c("path1 gene1 gene2", "path2 gene1 gene2 gene3") # created by readLines 
f <- function(l, s) {
  v <- strsplit(s, " ")[[1]]
  l[[v[1]]] <- v[2:length(v)]
  return(l)
}
res <- Reduce(f, sl, list())

【讨论】:

  • +1 很好地使用了Reduce。 OP 的文件有多个空格,因此您需要在 strsplit 调用中处理它。
【解决方案2】:

这是一种方法:

# Read in the data
x <- scan("data.txt", what="", sep="\n")
# Separate elements by one or more whitepace
y <- strsplit(x, "[[:space:]]+")
# Extract the first vector element and set it as the list element name
names(y) <- sapply(y, `[[`, 1)
#names(y) <- sapply(y, function(x) x[[1]]) # same as above
# Remove the first vector element from each list element
y <- lapply(y, `[`, -1)
#y <- lapply(y, function(x) x[-1]) # same as above

【讨论】:

  • 谢谢!我不完全理解 [[[ 在做什么,但是明确的函数定义非常有意义。
  • 这只是一种显式调用子集函数的方法。像+%*%等,都得引用。它们是 .Primitive,因此它们仅根据位置匹配参数。
【解决方案3】:

基于链接页面的快速解决方案...

inlist <- strsplit(readLines("file.txt"), "[[:space:]]+")
pathways <- lapply(inlist, tail, n = -1)
names(pathways) <- lapply(inlist, head, n = 1)

【讨论】:

  • 我考虑过使用readLines,但它会为空行(可能在文件末尾?)提供缺失值("")。
  • 是的,我注意到了。如果您使用我的答案中的连接并执行readLines(con),您会看到这个换行问题。
【解决方案4】:

一种解决方案是通过read.table() 读取数据,但使用fill = TRUE 参数填充具有较少“条目”的行,将生成的数据框转换为列表,然后清理“空”元素.

首先,读取您的 sn-p 数据:

con <- textConnection("path1   gene1 gene2
path2   gene3 gene4 gene5 gene6
path3   gene7 gene8 gene9
")
dat <- read.table(con, fill = TRUE, stringsAsFactors = FALSE)
close(con)

接下来我们删除第一列,先将其保存为以后的列表名称

nams <- dat[, 1]
dat <- dat[, -1]

将数据框转换为列表。这里我只是在索引 1,2,...,n 上拆分数据框,其中 n 是行数:

ldat <- split(dat, seq_len(nrow(dat)))

清理空单元格:

ldat <- lapply(ldat, function(x) x[x != ""])

最后,应用名称

names(ldat) <- nams

给予:

> ldat
$path1
[1] "gene1" "gene2"

$path2
[1] "gene3" "gene4" "gene5" "gene6"

$path3
[1] "gene7" "gene8" "gene9"

【讨论】:

  • 有意思,没想到会这样。
  • 同上您的解决方案。我的 regex-fu 很弱,所以没有看到使用 scan() 的简单方法。
  • 这个解决方案容易出现一个潜在的难以发现的bug:stackoverflow.com/questions/32066049,你应该先获取最大列数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-20
  • 2016-10-23
相关资源
最近更新 更多