2016-03-23 39 views
3

我試圖導入一個由|用R.分隔的文本文件,但在某些字符串中包含分隔符的轉義版本。例如:如何忽略在R中導入文本文件時被轉義的分隔符?

12341 |銀行| 234225

135543 |單\ |辦公| 25343452

7897 |辦公| 80909

25223 |銀行| 9870

我想觀察在第二行,第二列讀作「單一」。

保存|並不重要。如果我完全可以忽略\ |,或者用另一個字符(例如「/」)替換它,我也可以。即「單一辦公室」或「單人/辦公室」都很好。

我需要這樣做,而不使用shell命令(無「sed」)。

什麼是在一個大文本文件(〜20GB)中做到這一點的最快方法?預先感謝您的幫助!

+0

當你在數據讀取方面會發生什麼? R是否將轉義的分隔符標識爲分隔符,並將上一個值作爲新行創建? – cgage

+0

我得到這個錯誤: 「期待36列,但第471行包含處理所有列後的文本。很可能這是由於一個或多個字段已嵌入sep ='|'和/或(非轉義的)'\ n'字符在不平衡的未轉義的引號內,fread無法處理這些不明確的情況,並且這些行可能沒有按預期讀入,請閱讀fread中的引號部分。 – Max

回答

3

下面是兩種不同的可能性,嘗試:

1)重讀試試這個,看看文件的大小允許這樣做。它使用readLines讀入文件,刪除\ |字符和重新讀取它:

read.table(text = gsub("\\|", "", readLines("myfile.dat"), fixed = TRUE), sep = "|") 

2)sqldf這確實在SQLite數據庫卸載R.它的數據讀入名爲file一個SQLite表的處理,消除在所述內使用replace所指示的字符選擇。向外移動時,下一個選擇將每行分割爲第一個字段和其後的所有內容,而外部選擇將所有內容分割到其餘兩個字段中,並將相關字段轉換爲數字。最後它被讀入R.除了讀入R的最後一步發生在R之外,R的限制將不適用。

library(sqldf) 

read.csv.sql("myfile.dat", header = FALSE, sql = 
    "select cast(V1 as numeric) V1, 
      substr(V2, 1, instr(V2, '|') - 1) V2, 
      cast(substr(V2, instr(V2, '|') + 1) as numeric) V3 
     from (select substr(V1, 1, instr(V1, '|') - 1) V1, 
       substr(V1, instr(V1, '|') + 1) V2 
      from (select replace(V1, '\\|', '') V1 from file))") 

3)sqldf - 2使用sqldf在SQL更換分隔符的數據這一個讀取,以避免作爲R做它,然後將其讀入R.然後將其寫入到一個文件,並讀取它又回來了。這個?應該用沒有出現在文件中的任何字符替換。如果空間有限,您可能希望取消註釋rm()

library(sqldf) 

dat <- read.csv.sql("myfile.dat", sep = "?", header = FALSE, 
      sql = "select replace(V1, '\\|', '') V1 from file") 
write.table(dat, file = "myfile2.dat", sep = "?", row.names = FALSE, quote = FALSE) 
# rm(dat) 
read.table("myfile2.dat", sep = "|", skip = 1) 

注:(1)以下是一些自包含上述的可再現的運行:

Lines <- "12341|bank|234225 
135543|single\\|office|25343452 
7897|office|80909 
25223|bank|9870" 
cat(Lines, "\n", file = "myfile.dat") 

read.table(text = gsub("\\|", "", readLines("myfile.dat"), fixed = TRUE), sep = "|") 

,並提供:

 V1   V2  V3 
1 12341   bank 234225 
2 135543 singleoffice 25343452 
3 7897  office 80909 
4 25223   bank  9870 

(2)和

Lines <- "12341|bank|234225 
135543|single\\|office|25343452 
7897|office|80909 
25223|bank|9870" 
cat(Lines, "\n", file = "myfile.dat") 

library(sqldf) 
read.csv.sql("myfile.dat", header = FALSE, sql = 
    "select cast(V1 as numeric) V1, 
      substr(V2, 1, instr(V2, '|') - 1) V2, 
      cast(substr(V2, instr(V2, '|') + 1) as numeric) V3 
     from (select substr(V1, 1, instr(V1, '|') - 1) V1, 
       substr(V1, instr(V1, '|') + 1) V2 
      from (select replace(V1, '\\|', '') V1 from file))") 

,並提供:

 V1   V2  V3 
1 12341   bank 234225 
2 135543 singleoffice 25343452 
3 7897  office 80909 
4 25223   bank  9870 

(3)和

Lines <- "12341|bank|234225 
135543|single\\|office|25343452 
7897|office|80909 
25223|bank|9870" 
cat(Lines, "\n", file = "myfile.dat") 

library(sqldf) 

dat <- read.csv.sql("myfile.dat", sep = "?", header = FALSE, 
     sql = "select replace(V1, '\\|', '') V1 from file") 
write.table(dat, file = "myfile2.dat", sep = "?", row.names = FALSE, quote = FALSE) 
# rm(dat) 
read.table("myfile2.dat", sep = "|", skip = 1) 

,並提供:

 V1   V2  V3 
1 12341   bank 234225 
2 135543 singleoffice 25343452 
3 7897  office 80909 
4 25223   bank  9870 
+0

添加註釋和對sqldf代碼的一些更新。 –

+0

如果我不知道哪一列可能包含轉義的分隔符,我該如何修改代碼?在實際數據中,我有36列,其中任何一列都可以包含\ |。 – Max

+0

上面的代碼(包括1和2)在所有列中替換它,但是如果你有36列,那麼你最好堅持(1),因爲擴展(2)到那將是尷尬的。 –

相關問題