Jawaban yang lain menunjukkan bagaimana untuk membuat daftar data.frames ketika Anda sudah memiliki sekelompok data.frames, misalnya, d1
, d2
, .... Memiliki berurutan bernama frame data masalah, dan menempatkan mereka dalam daftar adalah perbaikan yang baik, tetapi praktik terbaik adalah menghindari memiliki banyak data.frame tidak ada dalam daftar di tempat pertama.
Jawaban lain memberikan banyak detail tentang cara menetapkan bingkai data untuk mendaftar elemen, mengaksesnya, dll. Kami akan membahasnya sedikit di sini juga, tetapi Poin Utama adalah jangan menunggu sampai Anda memiliki banyak data.frames
untuk menambahkannya ke daftar. Mulailah dengan daftar.
Sisa dari jawaban ini akan mencakup beberapa kasus umum di mana Anda mungkin tergoda untuk membuat variabel berurutan, dan menunjukkan cara langsung ke daftar. Jika Anda baru mendaftar di R, Anda mungkin ingin juga membaca Apa perbedaan antara [[
dan [
dalam mengakses elemen daftar? .
Daftar dari awal
Jangan pernah membuat d1
d2
d3
, ..., dn
sejak awal. Buat daftar d
dengan n
elemen.
Membaca banyak file ke dalam daftar bingkai data
Ini dilakukan dengan cukup mudah saat membaca dalam file. Mungkin Anda punya file data1.csv, data2.csv, ...
di direktori. Sasaran Anda adalah daftar kerangka data mydata
. Disebut Hal pertama yang Anda butuhkan adalah vektor dengan semua nama file. Anda dapat membangun ini dengan pasta (misalnya, my_files = paste0("data", 1:5, ".csv")
), tapi mungkin lebih mudah untuk menggunakan list.files
untuk meraih semua file yang sesuai: my_files <- list.files(pattern = "\\.csv$")
. Anda dapat menggunakan ekspresi reguler untuk mencocokkan file, membaca lebih lanjut tentang ekspresi reguler dalam pertanyaan lain jika Anda memerlukan bantuan di sana. Dengan cara ini Anda dapat mengambil semua file CSV bahkan jika mereka tidak mengikuti skema penamaan yang bagus. Atau Anda dapat menggunakan pola regex yang lebih menarik jika Anda perlu mengambil file CSV tertentu dari banyak file.
Pada titik ini, sebagian besar pemula R akan menggunakan for
loop, dan tidak ada yang salah dengan itu, itu berfungsi dengan baik.
my_data <- list()
for (i in seq_along(my_files)) {
my_data[[i]] <- read.csv(file = my_files[i])
}
Cara yang lebih mirip R untuk melakukannya adalah dengan lapply
, yang merupakan jalan pintas untuk hal di atas
my_data <- lapply(my_files, read.csv)
Tentu saja, gantikan fungsi impor data lainnya read.csv
dengan cara yang sesuai. readr::read_csv
atau data.table::fread
akan lebih cepat, atau Anda mungkin juga memerlukan fungsi berbeda untuk jenis file yang berbeda.
Apa pun itu, akan mudah untuk memberi nama elemen daftar agar sesuai dengan file
names(my_data) <- gsub("\\.csv$", "", my_files)
# or, if you prefer the consistent syntax of stringr
names(my_data) <- stringr::str_replace(my_files, pattern = ".csv", replacement = "")
Memisahkan bingkai data menjadi daftar bingkai data
Ini super mudah, fungsi dasar split()
melakukannya untuk Anda. Anda dapat membagi dengan kolom (atau kolom) dari data, atau dengan apa pun yang Anda inginkan
mt_list = split(mtcars, f = mtcars$cyl)
# This gives a list of three data frames, one for each value of cyl
Ini juga merupakan cara yang bagus untuk memecah bingkai data menjadi potongan-potongan untuk validasi silang. Mungkin Anda ingin membagi mtcars
menjadi potongan pelatihan, tes, dan validasi.
groups = sample(c("train", "test", "validate"),
size = nrow(mtcars), replace = TRUE)
mt_split = split(mtcars, f = groups)
# and mt_split has appropriate names already!
Mensimulasikan daftar bingkai data
Mungkin Anda mensimulasikan data, sesuatu seperti ini:
my_sim_data = data.frame(x = rnorm(50), y = rnorm(50))
Tetapi siapa yang hanya melakukan satu simulasi? Anda ingin melakukan ini 100 kali, 1000 kali, lebih banyak! Tetapi Anda tidak ingin 10.000 frame data di ruang kerja Anda. Gunakan replicate
dan letakkan dalam daftar:
sim_list = replicate(n = 10,
expr = {data.frame(x = rnorm(50), y = rnorm(50))},
simplify = F)
Dalam hal ini khususnya, Anda juga harus mempertimbangkan apakah Anda benar-benar membutuhkan frame data yang terpisah, atau apakah frame data tunggal dengan kolom "grup" juga berfungsi? Menggunakan data.table
atau dplyr
cukup mudah untuk melakukan hal-hal "dengan grup" ke bingkai data.
Saya tidak memasukkan data saya dalam daftar :( Saya akan lain kali, tetapi apa yang bisa saya lakukan sekarang?
Jika mereka bermacam-macam aneh (yang tidak biasa), Anda dapat menetapkannya:
mylist <- list()
mylist[[1]] <- mtcars
mylist[[2]] <- data.frame(a = rnorm(50), b = runif(50))
...
Jika Anda memiliki data frame yang bernama dalam pola, misalnya, df1
, df2
, df3
, dan Anda ingin mereka dalam daftar, Anda bisa get
mereka jika Anda dapat menulis ekspresi reguler untuk mencocokkan nama-nama. Sesuatu seperti
df_list = mget(ls(pattern = "df[0-9]"))
# this would match any object with "df" followed by a digit in its name
# you can test what objects will be got by just running the
ls(pattern = "df[0-9]")
# part and adjusting the pattern until it gets the right objects.
Secara umum, mget
digunakan untuk mendapatkan banyak objek dan mengembalikannya dalam daftar bernama. Rekanannya get
digunakan untuk mendapatkan satu objek dan mengembalikannya (tidak ada dalam daftar).
Menggabungkan daftar frame data ke dalam frame data tunggal
Tugas umum adalah menggabungkan daftar bingkai data menjadi satu bingkai data besar. Jika Anda ingin menumpuknya di atas satu sama lain, Anda akan menggunakannya rbind
untuk sepasang mereka, tetapi untuk daftar bingkai data di sini adalah tiga pilihan yang baik:
# base option - slower but not extra dependencies
big_data = do.call(what = rbind, args = df_list)
# data table and dplyr have nice functions for this that
# - are much faster
# - add id columns to identify the source
# - fill in missing values if some data frames have more columns than others
# see their help pages for details
big_data = data.table::rbindlist(df_list)
big_data = dplyr::bind_rows(df_list)
(Demikian pula menggunakan cbind
atau dplyr::bind_cols
untuk kolom.)
Untuk menggabungkan (bergabung) daftar bingkai data, Anda dapat melihat jawaban ini . Seringkali, idenya adalah untuk digunakan Reduce
dengan merge
(atau fungsi penggabungan lainnya) untuk menyatukan mereka.
Mengapa memasukkan data dalam daftar?
Masukan data yang sama dalam daftar karena Anda ingin melakukan hal-hal yang mirip dengan setiap frame data, dan fungsi seperti lapply
, sapply
do.call
, yang purrr
paket , dan lama plyr
l*ply
fungsi membuatnya mudah untuk melakukan itu. Contoh orang yang dengan mudah melakukan sesuatu dengan daftar semuanya ada di SO.
Bahkan jika Anda menggunakan perulangan rendah untuk, lebih mudah untuk mengulangi elemen daftar daripada membangun nama variabel dengan paste
dan mengakses objek dengan get
. Lebih mudah di-debug juga.
Pikirkan skalabilitas . Jika Anda benar-benar hanya perlu tiga variabel, baik itu untuk digunakan d1
, d2
, d3
. Tetapi jika ternyata Anda benar-benar membutuhkan 6, itu lebih banyak mengetik. Dan waktu berikutnya, ketika Anda membutuhkan 10 atau 20, Anda menemukan diri Anda menyalin dan menyisipkan baris kode, mungkin menggunakan find / mengganti perubahan d14
untuk d15
, dan Anda berpikir ini bukan bagaimana pemrograman harus . Jika Anda menggunakan daftar, perbedaan antara 3 kasus, 30 kasus, dan 300 kasus paling banyak adalah satu baris kode --- tidak ada perubahan sama sekali jika jumlah kasus Anda terdeteksi secara otomatis oleh, misalnya, berapa banyak .csv
file di direktori.
Anda dapat memberi nama elemen daftar, jika Anda ingin menggunakan sesuatu selain indeks numerik untuk mengakses frame data Anda (dan Anda dapat menggunakan keduanya, ini bukan pilihan XOR).
Secara keseluruhan, menggunakan daftar akan membuat Anda menulis kode yang lebih bersih, lebih mudah dibaca, yang akan menghasilkan lebih sedikit bug dan lebih sedikit kebingungan.
=
tidak<-
di dalamdata.frame()
. Dengan menggunakan<-
Anda membuaty1
dany2
di lingkungan global Anda dan bingkai data Anda tidak seperti yang Anda inginkan.