R:从带有重复选项卡的制表符分隔文件中读取数据

时间:2015-04-17 12:03:03

标签: r

我需要将一个非常大的制表符分隔的文本文件读入R(大约2千兆字节)。问题是该文件包含大量重复的选项卡(两个后续选项卡之间没有任何内容)。它们似乎会造成麻烦,因为它们(有些?)被解释为行尾。

由于数据量巨大,我上传了一小部分来说明问题,请参阅下面的代码。

count.fields(file = "http://m.uploadedit.com/ba3c/1429271380882.txt", sep = "\t")
read.table(file = "http://m.uploadedit.com/ba3c/1429271380882.txt", 
       header = TRUE, sep = "\t")

感谢您的帮助。

修改

编辑:该示例并未完美地说明原始问题。对于整个数据,我每行应该总共有6312个字段,但是当我对它进行count.fields()时,行会在4571 - 1741 - 4571 - 1741 - ...模式中分解,因此有一个字段编号4571后的附加行尾。

3 个答案:

答案 0 :(得分:2)

似乎在列名中随机散布着\n个字符串。如果我们使用\nsubstr()在文件中查找前5次出现的gregexpr(),结果似乎很奇怪:

library(readr) # useful pkg to read files
df <- read_file("http://m.uploadedit.com/ba3c/1429271380882.txt")

> substr(df, gregexpr("\n", df)[[1]][1]-10, gregexpr("\n", df)[[1]][1]+10)
[1] "1-024.Top \nAlleles\tCF"

> substr(df, gregexpr("\n", df)[[1]][2]-10, gregexpr("\n", df)[[1]][2]+10)
[1] "053.Theta\t\nCFF01-053."

> substr(df, gregexpr("\n", df)[[1]][3]-10, gregexpr("\n", df)[[1]][3]+10)
[1] "CFF01-072.\nTop Allele"

> substr(df, gregexpr("\n", df)[[1]][4]-10, gregexpr("\n", df)[[1]][4]+10)
[1] "CFF01-086.\nTheta\tCFF0"

> substr(df, gregexpr("\n", df)[[1]][5]-10, gregexpr("\n", df)[[1]][5]+10)
[1] "ype\tCFF01-\n303.Top Al"

所以,问题显然不是随后的两个\t,而是随机分散的换行符。这显然会导致read.table解析器崩溃。

但是:如果问题是随机分散的换行符,让我们将它们全部删除并将它们插入正确的位置。以下代码将正确读取已发布的示例数据。您可能需要为ID_REF变量提供一个更好的正则表达式,以便在ID字符串之前自动将其替换为\n,以防ID字符串变化超过示例数据:

library(readr)

df <- read_file("http://m.uploadedit.com/ba3c/1429271380882.txt")

df <- gsub("\n", "", df)
df <- gsub("abph1", "\nabph1", df)
df <- read_delim(df, delim = "\t")

答案 1 :(得分:1)

检查您的报价和评论字符。默认行为是不计算引号内(或注释后)的制表符或其他分隔符。因此,每行的字段数保持交替,并且2个值添加到正确的数字这一事实表明在每行上的字段4570之后有一个引号字符。所以第一行读取第一个4570记录,查看引号并读取该行的其余部分,将下一行的前4570个字段作为单个字段读取,然后将第二行的剩余1741行作为单个字段读取,重复第3和第4行等

count.fieldsread.table及相关函数具有设置引号字符和注释字符的参数。将这些更改为空字符串将告诉R忽略引号和注释,这是测试我的理论的快速方法。

答案 2 :(得分:0)

好吧,我没有找到问题的根源,但我发现你在表格中有重复的rownames。我在R工作区中加载了你的数据。

to.load = readLines("http://m.uploadedit.com/ba3c/1429271380882.txt")
data = read.csv(text = to.load, sep = "\t",  nrows=length(to.load) - 1, row.names=NULL)