如何使用不同的分隔符读取数据?

时间:2014-05-09 15:54:09

标签: r read.table

我的文件看起来像:

a 1,2,3,5
b 4,5,6,7
c 5,6,7,8
...

第1个和第2个之间的分隔符是'\ t',其他分隔符是逗号。如何将此类数据集读取为具有5个字段的数据框。

3 个答案:

答案 0 :(得分:21)

我可能会这样做。

read.table(text = gsub(",", "\t", readLines("file.txt")))
  V1 V2 V3 V4 V5
1  a  1  2  3  5
2  b  4  5  6  7
3  c  5  6  7  8

解压缩一下:

  • readLines()将文件作为字符向量读入R,每行包含一个元素。
  • gsub(",", "\t", ...)用标签替换每个逗号,以便现在我们只有一种分隔字符的行。
  • text =的{​​{1}}参数让它知道您正在传递一个要直接读取的字符向量(而不是包含文本数据的文件的名称​​)

答案 1 :(得分:8)

"均衡"数据

根据您表达问题的方式判断,您似乎知道您的数据已经平衡了#34; (矩形)。

您在寻找更快捷的选择吗?您可能希望合并来自" data.table"的fread我的实验concat.split.DT function

解决方案看起来像(将" "替换为"\t"选项卡):

concat.split.DT(fread("yourfile.txt", sep = " ", header=FALSE), "V2", ",")

让我们编写一些数据:

x <- c("a\t1,2,3,5", "b\t4,5,6,7","c\t5,6,7,8")
X <- c(replicate(10000, x))
temp <- tempfile()
writeLines(X, temp, sep="\n") ## Write it to a temporary file

乔希的回答:

system.time(out1 <- read.table(text = gsub(",", "\t", readLines(temp))))
#    user  system elapsed 
#   0.679   0.000   0.676 
head(out1)
#   V1 V2 V3 V4 V5
# 1  a  1  2  3  5
# 2  b  4  5  6  7
# 3  c  5  6  7  8
# 4  a  1  2  3  5
# 5  b  4  5  6  7
# 6  c  5  6  7  8
dim(out1)
# [1] 30000     5

fread + concat.split.DT(就像使用fread两次,但仍然超级快):

system.time(out2 <- concat.split.DT(fread(temp, sep = "\t", header=FALSE), "V2", ","))
#    user  system elapsed 
#   0.027   0.000   0.028 
head(out2)
#    V1 V2_1 V2_2 V2_3 V2_4
# 1:  a    1    2    3    5
# 2:  b    4    5    6    7
# 3:  c    5    6    7    8
# 4:  a    1    2    3    5
# 5:  b    4    5    6    7
# 6:  c    5    6    7    8
dim(out2)
# [1] 30000     5

&#34;不平衡&#34;数据

虽然它并不适用于您的问题,但我应该提及这一点,以便其他可能需要解决类似问题的人受益:

上述一个限制是concat.split.DT仅处理&#34;平衡&#34;数据。 fread没有像fill这样的read.table参数(而且我似乎记得在某个地方读过它最有可能赢得这样的论点)。

这是我所说的不平衡的一个例子:

x2 <- c("a\t1,2,3,5,6,7", "b\t4,5,6,7","c\t5,6,7,8,9,10,11,12,13")
X2 <- c(replicate(10000, x2))
temp2 <- tempfile()
writeLines(X2, temp2, sep="\n")

read.table可以使用fill = TRUE参数处理:

system.time(out1b <- read.table(text = gsub(",", "\t", readLines(temp2)), fill=TRUE))
#    user  system elapsed 
#   1.151   0.000   1.152 
head(out1b)
#   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1  a  1  2  3  5  6  7 NA NA  NA
# 2  b  4  5  6  7 NA NA NA NA  NA
# 3  c  5  6  7  8  9 10 11 12  13
# 4  a  1  2  3  5  6  7 NA NA  NA
# 5  b  4  5  6  7 NA NA NA NA  NA
# 6  c  5  6  7  8  9 10 11 12  13
在这种情况下,

concat.split.DT会给您一个令人讨厌的错误,但您可以尝试我的cSplit function。它不是那么快,但仍然表现得很好:

system.time(out2b <- cSplit(fread(temp2, sep = "\t", header=FALSE), "V2", ","))
#    user  system elapsed 
#   0.393   0.004   0.399 
head(out2b)
#    V1 V2_1 V2_2 V2_3 V2_4 V2_5 V2_6 V2_7 V2_8 V2_9
# 1:  a    1    2    3    5    6    7   NA   NA   NA
# 2:  b    4    5    6    7   NA   NA   NA   NA   NA
# 3:  c    5    6    7    8    9   10   11   12   13
# 4:  a    1    2    3    5    6    7   NA   NA   NA
# 5:  b    4    5    6    7   NA   NA   NA   NA   NA
# 6:  c    5    6    7    8    9   10   11   12   13

答案 2 :(得分:0)

Scanner scan = new Scanner(file);
while (scan.hasNextLine()) {
    String[] a = scan.nextLine().replace("\\t", ",").split(",");
    //do something with the array
}
scan.close();

这样做了:

  1. 创建扫描程序以处理文件(扫描仪扫描)
  2. 扫描进去 基于的每个文件行的下一个文件行(scan.nextLine()) hasNextLine()
  3. 用逗号替换制表符(.replace(“\ t”,“,”)), 所以分隔符都是一样的
  4. 拆分为数组 逗号。现在,无论如何,您都可以处理所有数据 每条线的长度。
  5. 请勿忘记关闭扫描仪 你已经完成了。