Jadi saya punya file data (dipisahkan titik koma) yang memiliki banyak detail dan baris yang tidak lengkap (menyebabkan Access dan SQL tersedak). Kumpulan data tingkat kabupaten dipecah menjadi segmen, sub-segmen, dan sub-sub-segmen (dengan total ~ 200 faktor) selama 40 tahun. Singkatnya, ini sangat besar, dan tidak akan masuk ke dalam memori jika saya mencoba untuk membacanya.
Jadi pertanyaan saya adalah ini, mengingat saya ingin semua wilayah, tetapi hanya satu tahun (dan hanya tingkat segmen tertinggi ... yang pada akhirnya mengarah ke sekitar 100.000 baris), apa cara terbaik untuk mendapatkan rollup ini menjadi R?
Saat ini saya mencoba untuk memotong tahun-tahun yang tidak relevan dengan Python, mengatasi batas ukuran file dengan membaca dan beroperasi pada satu baris pada satu waktu, tetapi saya lebih suka solusi R-only (paket CRAN OK). Apakah ada cara yang mirip untuk membaca dalam file sepotong demi sepotong di R?
Ide apa pun akan sangat dihargai.
Memperbarui:
- Kendala
- Perlu menggunakan mesin saya , jadi tidak ada instans EC2
- Sebagai R-only mungkin. Kecepatan dan sumber daya tidak menjadi perhatian dalam kasus ini ... asalkan mesin saya tidak meledak ...
- Seperti yang Anda lihat di bawah, datanya berisi jenis campuran, yang perlu saya operasikan nanti
- Data
- Datanya 3,5GB, dengan sekitar 8,5 juta baris dan 17 kolom
- Beberapa ribu baris (~ 2k) salah format, dengan hanya satu kolom, bukan 17
- Ini sama sekali tidak penting dan dapat dibatalkan
- Saya hanya membutuhkan ~ 100.000 baris dari file ini (Lihat di bawah)
Contoh data:
County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP; ...
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1; ...
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5; ...
NC [Malformed row]
[8.5 Mill rows]
Saya ingin memotong beberapa kolom dan memilih dua dari 40 tahun yang tersedia (2009-2010 dari 1980-2020), sehingga datanya dapat masuk ke dalam R:
County; State; Year; Quarter; Segment; GDP; ...
Ada County;NC;2009;4;FIRE;80.1; ...
Ada County;NC;2010;1;FIRE;82.5; ...
[~200,000 rows]
Hasil:
Setelah mengutak-atik semua saran yang dibuat, saya memutuskan bahwa readLines, yang disarankan oleh JD dan Marek, akan bekerja paling baik. Saya memberi Marek cek karena dia memberi contoh implementasi.
Saya telah mereproduksi versi implementasi Marek yang sedikit diadaptasi untuk jawaban akhir saya di sini, menggunakan strsplit dan cat untuk hanya menyimpan kolom yang saya inginkan.
Perlu juga dicatat bahwa ini JAUH kurang efisien daripada Python ... seperti dalam, Python mengolah file 3.5GB dalam 5 menit sementara R membutuhkan waktu sekitar 60 ... tetapi jika yang Anda miliki hanyalah R maka ini tiketnya.
## Open a connection separately to hold the cursor position
file.in <- file('bad_data.txt', 'rt')
file.out <- file('chopped_data.txt', 'wt')
line <- readLines(file.in, n=1)
line.split <- strsplit(line, ';')
# Stitching together only the columns we want
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
## Use a loop to read in the rest of the lines
line <- readLines(file.in, n=1)
while (length(line)) {
line.split <- strsplit(line, ';')
if (length(line.split[[1]]) > 1) {
if (line.split[[1]][3] == '2009') {
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
}
}
line<- readLines(file.in, n=1)
}
close(file.in)
close(file.out)
Kegagalan dengan Pendekatan:
- sqldf
- Ini pasti yang akan saya gunakan untuk jenis masalah ini di masa mendatang jika datanya terbentuk dengan baik. Namun, jika tidak, maka SQLite akan tersedak.
- MapReduce
- Sejujurnya, para dokter sedikit mengintimidasi saya tentang hal ini, jadi saya tidak sempat mencobanya. Sepertinya itu membutuhkan objek untuk berada dalam ingatan juga, yang akan mengalahkan poin jika memang begitu.
- memori besar
- Pendekatan ini ditautkan dengan rapi ke data, tetapi hanya dapat menangani satu jenis dalam satu waktu. Akibatnya, semua vektor karakter saya turun ketika dimasukkan ke dalam tabel besar. Jika saya perlu merancang kumpulan data yang besar untuk masa depan, saya akan mempertimbangkan hanya menggunakan angka saja untuk menjaga opsi ini tetap hidup.
- memindai
- Pemindaian tampaknya memiliki masalah jenis yang serupa dengan memori besar, tetapi dengan semua mekanisme readLines. Singkatnya, kali ini tidak sesuai dengan tagihan.
sed
dan / atauawk
membuat versi CSV cincang yang dapat Anda baca secara langsung. Karena ini lebih merupakan solusi daripada jawaban, saya akan meninggalkannya sebagai komentar.fread
Fungsi jauh lebih cepat daripadaread.table
. Gunakan sesuatu sepertix = fread(file_path_here, data.table=FALSE)
untuk memuatnya sebagaidata.frame
objek.Jawaban:
Saya mencoba dengan
readLines
. Potongan kode ini dibuatcsv
dengan tahun-tahun tertentu.file_in <- file("in.csv","r") file_out <- file("out.csv","a") x <- readLines(file_in, n=1) writeLines(x, file_out) # copy headers B <- 300000 # depends how large is one pack while(length(x)) { ind <- grep("^[^;]*;[^;]*; 20(09|10)", x) if (length(ind)) writeLines(x[ind], file_out) x <- readLines(file_in, n=B) } close(file_in) close(file_out)
sumber
Saya bukan ahli dalam hal ini, tetapi Anda mungkin mempertimbangkan untuk mencoba MapReduce , yang pada dasarnya berarti mengambil pendekatan "bagi dan taklukkan". R memiliki beberapa opsi untuk ini, termasuk:
Sebagai alternatif, R menyediakan beberapa paket untuk menangani data besar yang keluar dari memori (ke disk). Anda mungkin dapat memuat seluruh dataset ke dalam sebuah
bigmemory
objek dan melakukan pengurangan sepenuhnya dalam R. Lihat http://www.bigmemory.org/ untuk seperangkat alat untuk menangani ini.sumber
bigmemory
mungkin lebih mudah bagi Anda untuk mencoba dulu, dalam hal ini.Iya. Fungsi readChar () akan membaca dalam satu blok karakter tanpa mengasumsikan mereka dihentikan oleh null. Jika Anda ingin membaca data dalam satu baris, Anda dapat menggunakan readLines () . Jika Anda membaca blok atau baris, melakukan operasi, lalu menulis datanya, Anda dapat menghindari masalah memori. Meskipun jika Anda ingin menjalankan instans memori besar di Amazon EC2, Anda bisa mendapatkan hingga 64GB RAM. Itu harus menyimpan file Anda ditambah banyak ruang untuk memanipulasi data.
Jika Anda membutuhkan lebih banyak kecepatan, maka rekomendasi Shane untuk menggunakan Pengurangan Peta adalah rekomendasi yang sangat bagus. Namun jika Anda menggunakan instans memori besar di EC2, Anda harus melihat paket multicore untuk menggunakan semua core pada mesin.
Jika Anda menemukan diri Anda ingin membaca banyak pertunjukan data yang dibatasi ke R, Anda setidaknya harus meneliti paket sqldf yang memungkinkan Anda untuk mengimpor langsung ke sqldf dari R dan kemudian mengoperasikan data dari dalam R. Saya telah menemukan sqldf menjadi satu cara tercepat untuk mengimpor sejumlah data ke R, seperti yang disebutkan dalam pertanyaan sebelumnya .
sumber
Ada paket baru bernama colbycol yang memungkinkan Anda membaca hanya variabel yang Anda inginkan dari file teks yang sangat besar:
http://colbycol.r-forge.r-project.org/
Ini meneruskan argumen apa pun ke read.table, jadi kombinasinya akan membuat Anda subset cukup erat.
sumber
The
ff
paket adalah cara transparan untuk menangani file besar.Anda dapat melihat situs paket dan / atau presentasi tentangnya.
saya harap ini membantu
sumber
Bagaimana dengan penggunaan
readr
danread_*_chunked
keluarga?Jadi dalam kasus Anda:
testfile.csv
County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP Ada County;NC;2009;4;FIRE;Financial;Banks;80.1 Ada County;NC;2010;1;FIRE;Financial;Banks;82.5 lol Ada County;NC;2013;1;FIRE;Financial;Banks;82.5
Kode sebenarnya
require(readr) f <- function(x, pos) subset(x, Year %in% c(2009, 2010)) read_csv2_chunked("testfile.csv", DataFrameCallback$new(f), chunk_size = 1)
Ini berlaku
f
untuk setiap potongan, mengingat nama kolom dan menggabungkan hasil yang difilter pada akhirnya. Lihat?callback
yang merupakan sumber dari contoh ini.Ini menghasilkan:
# A tibble: 2 × 8 County State Year Quarter Segment `Sub-Segment` `Sub-Sub-Segment` GDP * <chr> <chr> <int> <int> <chr> <chr> <chr> <dbl> 1 Ada County NC 2009 4 FIRE Financial Banks 801 2 Ada County NC 2010 1 FIRE Financial Banks 825
Anda bahkan dapat meningkatkan
chunk_size
tetapi dalam contoh ini hanya ada 4 baris.sumber
Anda dapat mengimpor data ke database SQLite dan kemudian menggunakan RSQLite untuk memilih subset.
sumber
Apakah Anda menyimpan kenangan besar ? Lihat ini dan ini .
sumber
Mungkin Anda dapat bermigrasi ke MySQL atau PostgreSQL untuk mencegah diri Anda dari batasan MS Access.
Sangat mudah untuk menghubungkan R ke sistem ini dengan konektor database berbasis DBI (tersedia di CRAN).
sumber
scan () memiliki argumen nlines dan argumen lewati. Adakah alasan mengapa Anda bisa menggunakannya untuk membaca dalam potongan baris waktu, memeriksa tanggal untuk melihat apakah itu sesuai? Jika file input diurutkan berdasarkan tanggal, Anda dapat menyimpan indeks yang memberi tahu Anda apa yang harus dilewati dan nline Anda yang akan mempercepat proses di masa mendatang.
sumber
Saat ini, 3,5GB tidak terlalu besar, saya bisa mendapatkan akses ke mesin dengan RAM 244GB (r3.8xlarge) di cloud Amazon seharga $ 2,80 / jam. Berapa jam yang Anda perlukan untuk mencari tahu cara menyelesaikan masalah menggunakan solusi tipe data besar? Berapa nilai waktu Anda? Ya, Anda akan membutuhkan satu atau dua jam untuk mengetahui cara menggunakan AWS - tetapi Anda dapat mempelajari dasar-dasarnya pada tingkat gratis, mengunggah data dan membaca 10 ribu baris pertama ke dalam R untuk memeriksa apakah berfungsi dan kemudian Anda dapat menjalankan a Instance memori besar seperti r3.8xlarge dan baca semuanya! Hanya 2c saya.
sumber
Sekarang, 2017, saya akan menyarankan untuk menggunakan spark dan sparkR.
sintaksnya dapat ditulis dengan cara sederhana yang mirip dplyr
itu cukup cocok untuk memori kecil (kecil dalam arti 2017)
Namun, mungkin ini pengalaman yang menakutkan untuk memulai ...
sumber
Saya akan mencari DB dan kemudian membuat beberapa pertanyaan untuk mengekstrak sampel yang Anda butuhkan melalui DBI
Harap hindari mengimpor file csv 3,5 GB ke SQLite. Atau setidaknya periksa kembali apakah db BESAR Anda sesuai dengan batas SQLite, http://www.sqlite.org/limits.html
Ini DB yang sangat besar yang Anda miliki. Saya akan menggunakan MySQL jika Anda membutuhkan kecepatan. Tetapi bersiaplah untuk menunggu berjam-jam hingga impor selesai. Kecuali Anda memiliki perangkat keras yang tidak biasa atau Anda menulis dari masa depan ...
EC2 Amazon bisa menjadi solusi yang baik juga untuk membuat instance server yang menjalankan R dan MySQL.
nilai dua sen saya yang sederhana.
sumber