簡體   English   中英

如何使用不同的分隔符讀取數據?

[英]How to read data with different separators?

我有一個文件看起來像:

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

第1和第2之間的分隔符是'\\ t',其他分隔符是逗號。 如何將此類數據集讀取為具有5個字段的數據幀。

我可能會這樣做。

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", ...)用標簽替換每個逗號,所以現在我們只有一種分隔字符。
  • read.table()text =參數讓它知道你傳遞的字符向量是直接讀取的(而不是包含文本數據的文件的名稱)。

“平衡”數據

從您對問題的表達方式來判斷,您似乎知道您的數據是“平衡的”(矩形)。

您在尋找更快捷的選擇嗎? 您可能希望將來自“data.table”的fread與我的實驗性concat.split.DT函數結合起來。

該解決方案看起來是這樣的(替代" ""\\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

“不平衡”數據

雖然它不適用於您的問題,但我應該提及這可能是為了其他可能需要解決類似問題的人的利益:

上述的一個限制是concat.split.DT僅處理“平衡”數據。 fread沒有像read.table那樣的fill參數(我似乎記得在某個地方讀過它很可能沒有這樣的參數)。

這是我所說的不平衡的一個例子:

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函數 它不是那么快,但仍然表現得很好:

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
Scanner scan = new Scanner(file);
while (scan.hasNextLine()) {
    String[] a = scan.nextLine().replace("\\t", ",").split(",");
    //do something with the array
}
scan.close();

這樣做:

  1. 創建掃描儀來處理文件(掃描儀掃描)
  2. 基於hasNextLine()掃描每個文件行的下一個文件行(scan.nextLine())
  3. 用逗號(.replace(“\\ t”,“,”))替換制表符,因此分隔符都是相同的
  4. 用逗號分成數組。 現在,無論每條線的長度如何,您都可以處理所有數據。
  5. 完成后別忘了關閉掃描儀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM