2012-05-15 25 views
7

Çok sayıda veri içeren büyük bir dosyam var ve bunu veri alanına okumak istiyorum ancak bazı geçersiz satırlar buldu. Bu geçersiz satırlar, read.table'ın kırılmasına neden oluyor. Geçersiz çizgileri atlamak için aşağıdaki yöntemi deneyin, ancak performans çok kötü görünüyor.R çerçevesindeki dosyadan veri çerçevesi okunurken geçersiz satırlar nasıl atlanır?

counts<-count.fields(textConnection(lines),sep="\001") 
raw_data<-read.table(textConnection(lines[counts == 34]), sep="\001") 

Bunu başarmanın daha iyi bir yolu var mı? Teşekkürler

+2

Tanımınızda kötü olan nedir? –

+1

Herhangi bir nedenle 'read.table' doğrudan kullanmıyor musunuz? Çeşitli "kötü" karakterleri seçmek ve yok saymak için çok fazla argüman var. Eksik olan satırları "doldurmak" için bir argüman var, eğer sahip olduğunuz problem buysa. –

cevap

18

: istediğiniz gibi

read.table("test.csv", sep = ";", fill=TRUE) 

o zaman ilgi UA ilgileneceğim.

+1

Cevabınızı ek bir seçenek olarak ekledim –

+0

Lazy me-- bu benim ilk yorumumda benim cevabımdı, ama yorumunuzu daha iyi ayrıntılarla yazdınız –

+0

@Carl, +1 yorumunuz için. – BenBarnes

5

Yapabilecekleriniz, dosyadaki satırların üzerinden yinelemek ve yalnızca doğru uzunlukta olan satırları eklemektir. başarısız

1;2;3;4 
1;2;3;4 
1;2;3 
1;2;3;4 

read.table Kullanılması:

> read.table("test.csv", sep = ";") 
Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings, :                  
    line 3 did not have 4 elements 

Şimdi iteratif yaklaşım: Bu Tabii

require(plyr) 
no_lines = 4 
correct_length = 4 
file_con = file("test.csv", "r") 
result = ldply(1:no_lines, function(line) { 
    dum = strsplit(readLines(file_con, n = 1), split = ";")[[1]] 
    if(length(dum) == correct_length) { 
    return(dum) 
    } else { 
    cat(sprintf("Skipped line %s\n", line)) 
    return(NULL) 
    } 
    }) 
close(file_con) 

> result 
    V1 V2 V3 V4 
1 1 2 3 4 
2 1 2 3 4 
3 1 2 3 4 

olarak önemsiz bir örnektir

ben aşağıdaki test csv dosyasını tanımlanan dosya gerçekten küçüktür. Bir referans noktası olarak hareket etmek için daha zor bir örnek oluşturalım. kriter

# Iterative approach 
system.time({file_con <- file("big_test.csv", "r") 
    result_test <- ldply(1:norow, function(line) { 
     dum = strsplit(readLines(file_con, n = 1), split = ";")[[1]] 
     if(length(dum) == correct_length) { 
     return(dum) 
     } else { 
     # Commenting this speeds up by 30% 
     #cat(sprintf("Skipped line %s\n", line)) 
     return(NULL) 
     } 
     }) 
    close(file_con)}) 
    user system elapsed 
20.559 0.047 20.775 

# Normal read.table 
system.time(result_normal <- read.table("big_normal.csv", sep = ";")) 
    user system elapsed 
    1.060 0.015 1.079 

# read.table with fill = TRUE 
system.time({result_fill <- read.table("big_test.csv", sep = ";", fill=TRUE) 
      na_rows <- complete.cases(result_fill) 
      result_fill <- result_fill[-na_rows,]}) 
    user system elapsed 
    1.161 0.033 1.203 

# Specifying which type the columns are (e.g. character or numeric) 
# using the colClasses argument. 
system.time({result_fill <- read.table("big_test.csv", sep = ";", fill=TRUE, 
             colClasses = rep("numeric", 4)) 
      na_rows <- complete.cases(result_fill) 
      result_fill <- result_fill[-na_rows,]}) 
    user system elapsed 
    0.933 0.064 1.001 

Şimdi

# First file with invalid rows 
norow = 10e5 # number of rows 
no_lines = round(runif(norow, min = 3, max = 4)) 
no_lines[1] = correct_length 
file_content = ldply(no_lines, function(line) paste(1:line, collapse = ";")) 
writeLines(paste(file_content[[1]], sep = "\n"), "big_test.csv") 

# Same length with valid rows 
file_content = ldply(rep(4, norow), function(line) paste(1:line, collapse = ";")) 
writeLines(paste(file_content[[1]], sep = "\n"), "big_normal.csv") 

Yani iteratif yaklaşım biraz daha yavaş olmakla birlikte, (bu kabul edilebilir bir tanımına bağlı olmasına rağmen) 1000000 satırlar için 20 saniye kabul edilebilir olabilir. Özellikle de sadece bir kez buna sahip olduğunuzda ve daha sonra geri almak için save'u kullanarak kaydedin. @Paolo tarafından önerilen çözüm neredeyse read.table'a yapılan normal arama kadar hızlıdır. Yanlış miktarda sütun içeren satırlar (bu nedenle NA 'ler) complete.cases kullanılarak elimine edilir. Sütunların hangi sınıfların daha fazla performans göstereceğini belirlemek, sütunların ve satırların miktarının büyüdüğünde bu etkinin daha büyük olacağını düşünüyorum.

Sonuç olarak, en iyi seçenek, fill = TRUE ile sütunların sınıflarını belirtirken read.table'u kullanmaktır. ldply'u kullanarak yinelemeli yaklaşım, satırların nasıl okunacağı seçiminde daha fazla esneklik istiyorsanız, sadece iyi bir seçenektir, örn. Sadece belirli bir değer eşiğin üzerindeyse satırı oku. Fakat muhtemelen bu, tüm verileri R'ye okuyarak ve bir alt küme oluşturmadan daha hızlı yapılabilir. Sadece veriler RAM'inizden daha büyük olduğu zaman, yinelemeli yaklaşımın kendi değerlerine sahip olduğunu hayal edebilirdim. PaulHiemstra en örnek verilerin @ kullanılarak

İlgili konular