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
Tanımınızda kötü olan nedir? –
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. –