Saya telah melihat-lihat StackOverflow, tetapi saya tidak dapat menemukan solusi khusus untuk masalah saya, yang melibatkan penambahan baris ke bingkai data R.
Saya menginisialisasi bingkai data 2 kolom kosong, sebagai berikut.
df = data.frame(x = numeric(), y = character())
Kemudian, tujuan saya adalah untuk mengulang melalui daftar nilai dan, di setiap iterasi, menambahkan nilai ke akhir daftar. Saya mulai dengan kode berikut.
for (i in 1:10) {
df$x = rbind(df$x, i)
df$y = rbind(df$y, toString(i))
}
Saya juga berusaha fungsi c
, append
dan merge
tanpa hasil. Tolong beri tahu saya jika Anda punya saran.
Jawaban:
Memperbarui
Tidak tahu apa yang Anda coba lakukan, saya akan membagikan satu saran lagi: Lakukan pra-alokasi vektor dari jenis yang Anda inginkan untuk setiap kolom, masukkan nilai ke dalam vektor tersebut, dan kemudian, pada akhirnya, buat
data.frame
.Melanjutkan dengan Julian
f3
(yang dialokasikan sebelumnyadata.frame
) sebagai opsi tercepat sejauh ini, yang didefinisikan sebagai:Berikut adalah pendekatan yang serupa, tetapi pendekatan yang
data.frame
dibuat sebagai langkah terakhir.microbenchmark
dari paket "microbenchmark" akan memberi kita wawasan yang lebih komprehensif daripadasystem.time
:f1()
(pendekatan di bawah) sangat tidak efisien karena seberapa sering ia memanggildata.frame
dan karena menumbuhkan objek seperti itu umumnya lambat di R.f3()
jauh lebih baik karena pra-alokasi, tetapidata.frame
struktur itu sendiri mungkin menjadi bagian dari hambatan di sini.f4()
mencoba melewati kemacetan itu tanpa mengorbankan pendekatan yang ingin Anda ambil.Jawaban asli
Ini sebenarnya bukan ide yang bagus, tetapi jika Anda ingin melakukannya dengan cara ini, saya rasa Anda dapat mencoba:
Perhatikan bahwa dalam kode Anda, ada satu masalah lain:
stringsAsFactors
jika Anda ingin karakter tidak diubah menjadi faktor. Menggunakan:df = data.frame(x = numeric(), y = character(), stringsAsFactors = FALSE)
sumber
data.frame
ukuran akhir yang Anda harapkan dan menambahkan nilai dengan[
ekstraksi / penggantian.Mari kita tolak ukur tiga solusi yang diusulkan:
Solusi terbaik adalah mengalokasikan ruang terlebih dahulu (seperti yang dimaksudkan di R). Solusi terbaik berikutnya adalah menggunakan
list
, dan solusi terburuk (setidaknya berdasarkan hasil waktu ini) tampaknyarbind
.sumber
df <- rbind(df, data.frame(x = i, y = toString(i)))
Misalkan Anda tidak mengetahui ukuran data.frame sebelumnya. Bisa jadi beberapa baris, atau beberapa juta. Anda perlu memiliki semacam wadah, yang tumbuh secara dinamis. Mempertimbangkan pengalaman saya dan semua jawaban terkait di SO saya datang dengan 4 solusi berbeda:
rbindlist
ke data.frameGunakan operasi
data.table
cepatset
dan pasangkan dengan menggandakan tabel secara manual bila diperlukan.Gunakan
RSQLite
dan tambahkan ke tabel yang disimpan dalam memori.data.frame
kemampuan sendiri untuk mengembangkan dan menggunakan lingkungan kustom (yang memiliki semantik referensi) untuk menyimpan data.frame sehingga tidak akan disalin saat kembali.Berikut adalah pengujian semua metode untuk jumlah baris yang ditambahkan kecil dan besar. Setiap metode memiliki 3 fungsi yang terkait dengannya:
create(first_element)
yang mengembalikan objek pendukung yang sesuai denganfirst_element
dimasukkan.append(object, element)
yang menambahkanelement
akhir tabel (diwakili olehobject
).access(object)
mendapatkandata.frame
dengan semua elemen yang disisipkan.rbindlist
ke data.frameItu cukup mudah dan tidak berbelit-belit:
data.table::set
+ menggandakan tabel secara manual saat diperlukan.Saya akan menyimpan panjang sebenarnya dari tabel dalam
rowcount
atribut.SQL harus dioptimalkan untuk penyisipan rekaman cepat, jadi saya awalnya memiliki harapan tinggi untuk
RSQLite
solusiIni pada dasarnya adalah salin & tempel jawaban Karsten W. di utas serupa.
data.frame
lingkungan kustom + penambahan baris sendiri.Rangkaian pengujian:
Untuk kenyamanan, saya akan menggunakan satu fungsi uji untuk mencakup semuanya dengan panggilan tidak langsung. (Saya memeriksa: menggunakan
do.call
alih-alih memanggil fungsi secara langsung tidak membuat kode berjalan terukur lebih lama).Mari kita lihat kinerja untuk n = 10 penyisipan.
Saya juga menambahkan fungsi 'plasebo' (dengan akhiran
0
) yang tidak melakukan apa-apa - hanya untuk mengukur overhead pengaturan pengujian.Untuk 1E5 baris (pengukuran dilakukan pada Intel (R) Core (TM) i7-4710HQ CPU @ 2.50GHz):
Sepertinya sulusi berbasis SQLite, meskipun mendapatkan kembali beberapa kecepatan pada data besar, tidak jauh dari pertumbuhan eksponensial data.table + manual. Perbedaannya hampir dua kali lipat!
Ringkasan
Jika Anda tahu bahwa Anda akan menambahkan jumlah baris yang agak kecil (n <= 100), lanjutkan dan gunakan solusi yang paling sederhana: cukup tetapkan baris ke data.frame menggunakan notasi braket dan abaikan fakta bahwa data.frame adalah tidak diisi sebelumnya.
Untuk semua yang lain gunakan
data.table::set
dan kembangkan data.table secara eksponensial (misalnya menggunakan kode saya).sumber
Perbarui dengan purrr, tidyr & dplyr
Karena pertanyaannya sudah bertanggal (6 tahun), jawabannya tidak ada solusi dengan paket yang lebih baru tidyr dan purrr. Jadi bagi orang-orang yang bekerja dengan paket ini, saya ingin menambahkan solusi ke jawaban sebelumnya - semuanya cukup menarik, khususnya.
Keuntungan terbesar dari purrr dan tidyr adalah IMHO keterbacaan yang lebih baik. purrr menggantikan lapply dengan keluarga map () yang lebih fleksibel, tidyr menawarkan metode super-intuitif add_row - lakukan saja apa yang dikatakan :)
Solusi ini singkat dan intuitif untuk dibaca, dan relatif cepat:
Ini berskala hampir linier, jadi untuk 1e5 baris, kinerjanya adalah:
yang akan membuatnya berada di peringkat kedua setelah data.table (jika Anda mengabaikan plasebo) dalam tolok ukur oleh @Adam Ryczkowski:
sumber
add_row
. Sebagai contoh:map_dfr(1:1e5, function(x) { tibble(x = x, y = toString(x)) })
.bind_rows(df, map_dfr(1:1e5, function(x) { tibble(x = x, y = toString(x)) }))
daripada menggunakanadd_row
.Mari kita ambil 'titik' vektor yang memiliki angka dari 1 sampai 5
point = c(1,2,3,4,5)
jika kita ingin menambahkan angka 6 di mana saja di dalam vektor maka perintah di bawah ini mungkin berguna
i) Vektor
new_var = append(point, 6 ,after = length(point))
ii) kolom tabel
new_var = append(point, 6 ,after = length(mtcars$mpg))
Perintah tersebut
append
membutuhkan tiga argumen:sederhana...!! Permintaan maaf jika terjadi ...!
sumber
Solusi yang lebih umum untuk mungkin adalah sebagai berikut.
Fungsi extensionDf () memperluas bingkai data dengan n baris.
Sebagai contoh:
sumber
Solusi saya hampir sama dengan jawaban asli tetapi tidak berhasil untuk saya.
Jadi, saya memberi nama untuk kolom dan berhasil:
sumber