R simbol data.table dan operator yang harus Anda ketahui

Kode R data.table menjadi lebih efisien - dan elegan - bila Anda memanfaatkan simbol dan fungsinya yang khusus. Dengan mengingat hal itu, kita akan melihat beberapa cara khusus untuk membuat subset, menghitung, dan membuat kolom baru.

Untuk demo ini, saya akan menggunakan data dari survei pengembang Stack Overflow 2019, dengan sekitar 90.000 tanggapan. Jika Anda ingin mengikutinya, Anda dapat mendownload data dari Stack Overflow.

Jika paket data.table tidak diinstal pada sistem Anda, instal dari CRAN dan kemudian muat seperti biasa dengan library(data.table). Untuk memulai, Anda mungkin ingin membaca hanya dalam beberapa baris pertama dari kumpulan data untuk mempermudah pemeriksaan struktur data. Anda dapat melakukannya dengan fread()fungsi data.table dan nrowsargumennya. Saya akan membaca dalam 10 baris:

data_sample <- fread ("data / survey_results_public.csv", nrows = 10)

Seperti yang akan Anda lihat, ada 85 kolom untuk diperiksa. (Jika Anda ingin mengetahui arti semua kolom, ada file yang di-download dengan skema data dan PDF dari survei asli.) 

Untuk membaca semua data, saya akan menggunakan:

mydt <- fread ("data / survey_results_public.csv")

Selanjutnya, saya akan membuat data.table baru hanya dengan beberapa kolom agar lebih mudah untuk bekerja dan melihat hasilnya. Pengingat bahwa data.table menggunakan sintaks dasar ini: 

mydt [i, j, oleh]

Pengenalan paket data.table mengatakan untuk membaca ini sebagai "ambil dt, subset atau susun ulang baris menggunakan i, hitung j, dikelompokkan berdasarkan." Perlu diingat bahwa i dan j mirip dengan urutan braket dasar R.: baris pertama, kolom kedua. Jadi i untuk operasi yang Anda lakukan pada baris (memilih baris berdasarkan nomor baris atau kondisi); j adalah apa yang Anda lakukan dengan kolom (pilih kolom atau buat kolom baru dari perhitungan). Namun, perhatikan juga bahwa Anda dapat melakukan lebih banyak hal di dalam kurung data.table daripada bingkai data dasar R. Dan bagian "oleh" baru untuk data.table.

Karena saya memilih kolom, kode itu berada di tempat "j", yang berarti tanda kurung perlu koma terlebih dahulu untuk mengosongkan tempat "i":

mydt [, j]

Pilih kolom data.table

Salah satu hal yang saya suka tentang data.table adalah mudah untuk memilih kolom baik dikutip atau tidak dikutip . Unquoted seringkali lebih nyaman (biasanya begitulah cara yang tepat). Tetapi kutipan berguna jika Anda menggunakan data.table di dalam fungsi Anda sendiri, atau jika Anda ingin meneruskan vektor yang Anda buat di tempat lain dalam kode Anda.

Anda dapat memilih kolom data.table dengan cara dasar R yang khas, dengan vektor konvensional dari nama kolom yang dikutip. Sebagai contoh: 

dt1 <- mydt [, c ("LanguageWorkedWith", "LanguageDesireNextYear",

"OpenSourcer", "CurrencySymbol", "ConvertedComp”,

“Penghobi”)]

Jika Anda ingin menggunakannya tanpa tanda kutip, buat daftar sebagai ganti vektor dan Anda dapat memasukkan nama tanpa tanda kutip . 

dt1 <- mydt [, list (LanguageWorkedWith, LanguageDesireNextYear,

OpenSourcer, CurrencySymbol, ConvertedComp,

Penghobi)]

Dan sekarang kita sampai pada simbol khusus pertama kita. Daripada mengetik list(), Anda bisa menggunakan titik:

dt1 <- mydt [,. (LanguageWorkedWith, LanguageDesireNextYear,

OpenSourcer, CurrencySymbol, ConvertedComp,

Penghobi)]

Itu .()adalah jalan pintas untuk list()tanda kurung di dalam data.table.

Bagaimana jika Anda ingin menggunakan vektor nama kolom yang sudah ada? Menempatkan nama objek vektor di dalam tanda kurung data.table tidak akan berfungsi. Jika saya membuat vektor dengan nama kolom yang dikutip, seperti ini: 

mycols <- c ("LanguageWorkedWith", "LanguageDesireNextYear",

"OpenSourcer", "CurrencySymbol", "ConvertedComp", "Hobbyist")

Maka kode ini tidak akan  berfungsi: 

dt1 <- mydt [, mycols]

Sebagai gantinya, Anda perlu meletakkan .. (itu dua titik) di depan nama objek vektor:

dt1 <- mydt [, ..mycols]

Mengapa dua titik? Itu tampak agak acak bagi saya sampai saya membaca penjelasannya. Anggap saja seperti dua titik di terminal baris perintah Unix yang memindahkan Anda ke atas satu direktori. Di sini, Anda memindahkan satu namespace , dari lingkungan di dalam tanda kurung data.table hingga lingkungan global. (Itu benar-benar membantu saya mengingatnya!)

Hitung baris data.table

Ke simbol berikutnya. Untuk menghitung berdasarkan grup, Anda dapat menggunakan .Nsimbol data.table , yang  .Nberarti "jumlah baris". Ini bisa menjadi jumlah total baris, atau jumlah baris per grup jika Anda menggabungkan di bagian "oleh". 

Ekspresi ini mengembalikan jumlah baris dalam data.table: 

mydt [, .N]

Contoh berikut menghitung jumlah baris yang dikelompokkan berdasarkan satu variabel: apakah orang dalam survei juga membuat kode sebagai hobi ( Hobbyistvariabel).

mydt [, .N, Penghobi]

# kembali:

Penghobi N 1: Ya 71257 2: Tidak 17626

Anda dapat menggunakan nama kolom biasa dalam tanda kurung data.table jika hanya ada satu variabel. Jika Anda ingin mengelompokkan berdasarkan dua variabel atau lebih, gunakan .simbol. Sebagai contoh:

mydt [, .N,. (Hobi, OpenSourcer)]

Untuk mengurutkan hasil dari yang tertinggi ke terendah, Anda dapat menambahkan rangkaian tanda kurung kedua setelah yang pertama. The .Nsimbol secara otomatis menghasilkan kolom bernama N (tentu saja Anda dapat mengubah nama itu jika Anda ingin), sehingga pemesanan dengan jumlah baris dapat melihat sesuatu seperti ini:

mydt [, .N,. (Hobbyist, OpenSourcer)] [pesan (Hobbyist, -N)]

Saat saya mempelajari kode data.table, saya merasa terbantu untuk membacanya selangkah demi selangkah. Jadi saya akan membaca ini sebagai "Untuk semua baris di mydt (karena tidak ada apa-apa di tempat" I "), hitung jumlah baris, dikelompokkan berdasarkan Hobbyist dan OpenSourcer. Kemudian pesan pertama menurut Hobbyist, lalu jumlah baris menurun. ” 

Itu setara dengan kode dplyr ini:

mydf%>%

hitung (Hobbyist, OpenSourcer)%>%

pesan (Hobbyist, -n)

Jika Anda merasa pendekatan multi-baris konvensional tidyverse lebih mudah dibaca, kode data.table ini juga berfungsi:

mydt [, .N,

. (Penghobi, OpenSourcer)] [

pesan (Hobbyist, -N)

]

Tambahkan kolom ke data.table

Selanjutnya, saya ingin menambahkan kolom untuk melihat apakah setiap responden menggunakan R, apakah mereka menggunakan Python, apakah mereka menggunakan keduanya, atau jika mereka tidak menggunakan keduanya. The LanguageWorkedWithkolom memiliki informasi tentang bahasa yang digunakan, dan beberapa baris data yang terlihat seperti ini:

Sharon Machlis

Setiap jawaban adalah string karakter tunggal. Sebagian besar memiliki beberapa bahasa yang dipisahkan oleh titik koma.

Seperti yang sering terjadi, mencari Python lebih mudah daripada R, karena Anda tidak bisa hanya mencari "R" dalam string (Ruby dan Rust juga mengandung huruf besar R) seperti Anda dapat mencari "Python". Ini adalah kode yang lebih sederhana untuk membuat vektor TRUE / FALSE yang memeriksa apakah setiap string LanguageWorkedWithmengandung Python:

ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE)

Jika Anda tahu SQL, Anda akan mengenali sintaks "like". Saya, yah, seperti %like%. Ini cara sederhana yang bagus untuk memeriksa pencocokan pola. Dokumentasi fungsi mengatakan itu dimaksudkan untuk digunakan di dalam tanda kurung data.table, tetapi sebenarnya Anda dapat menggunakannya di kode Anda, tidak hanya dengan data.tables. Saya memeriksa dengan pembuat data.table Matt Dowle, yang mengatakan bahwa saran untuk menggunakannya di dalam tanda kurung adalah karena beberapa pengoptimalan kinerja tambahan terjadi di sana.

Selanjutnya, berikut kode untuk menambahkan kolom yang disebut PythonUser ke data.table:

dt1 [, PythonUser: = ifelse (LanguageWorkedWith% like% "Python", TRUE, FALSE)]

Perhatikan :=operatornya. Python memiliki operator seperti itu juga, dan sejak saya mendengarnya disebut “operator walrus,” itulah yang saya sebut. Saya pikir itu secara resmi "tugas berdasarkan referensi." Itu karena kode di atas mengubah objek dt1 data.table yang ada dengan menambahkan kolom baru - tanpa perlu menyimpannya ke variabel baru .

Untuk mencari R, saya akan menggunakan ekspresi reguler "\\bR\\b"yang berbunyi: “Temukan pola yang dimulai dengan batas kata - the \\b, lalu an R, dan diakhiri dengan batas kata lain. (Saya tidak bisa hanya mencari "R;" karena item terakhir di setiap string tidak memiliki titik koma.) 

Ini menambahkan kolom RUser ke dt1:

dt1 [, RUser: = ifelse (LanguageWorkedWith% like% "\\ bR \\ b", TRUE, FALSE)]

Jika Anda ingin menambahkan kedua kolom sekaligus dengan :=Anda perlu mengubah operator walrus itu menjadi fungsi dengan mengutipnya kembali, seperti ini:

dt1 [, `: =` (

PythonUser = ifelse (LanguageWorkedWith% seperti% "Python", TRUE, FALSE),

RUser = ifelse (LanguageWorkedWith% like% "\\ bR \\ b", TRUE, FALSE)

)]

Operator data.table yang lebih berguna

Ada beberapa operator data.table lain yang perlu diketahui. The  %between% operator memiliki sintaks ini:

vektor saya% antara% c (nilai_bawah, nilai_ atas)

Jadi jika saya ingin memfilter semua tanggapan yang kompensasi antara 50.000 dan 100.000 dibayarkan dalam dolar AS, kode ini berfungsi:

comp_50_100k <- dt1 [Simbol Mata Uang == "USD" &

ConvertedComp% antara% c (50000, 100000)]

Baris kedua di atas adalah kondisi antara. Perhatikan bahwa %between%operator menyertakan nilai bawah dan atas saat memeriksa.

Operator berguna lainnya adalah %chin%. Ia bekerja seperti basis R %in%tetapi dioptimalkan untuk kecepatan dan hanya untuk vektor karakter . Jadi, jika saya ingin memfilter semua baris di mana kolom OpenSourcer adalah "Tidak Pernah" atau "Kurang dari sekali per tahun", kode ini berfungsi:

rareos <- dt1 [OpenSourcer% chin% c ("Tidak Pernah", "Kurang dari sekali per tahun")]

Ini sangat mirip dengan basis R, kecuali bahwa basis R harus menentukan nama bingkai data di dalam braket dan juga memerlukan koma setelah ekspresi filter:

rareos_df <- df1 [df1 $ OpenSourcer% di% c ("Tidak Pernah", "Kurang dari sekali per tahun"),]

Fungsi fcase () baru

Untuk demo terakhir ini, saya akan mulai dengan membuat data.table baru hanya dengan orang yang melaporkan kompensasi dalam dolar AS:

usd <- dt1 [CurrencySymbol == "USD" &! is.na (ConvertedComp)]

Selanjutnya, saya akan membuat kolom baru yang disebut Languageapakah seseorang hanya menggunakan R, hanya Python, keduanya, atau tidak keduanya. Dan saya akan menggunakan fcase()fungsi baru . Pada saat artikel ini diterbitkan, fcase()hanya tersedia dalam versi pengembangan data.table. Jika Anda sudah menginstal data.table, Anda dapat memperbarui ke versi dev terbaru dengan perintah ini: 

data.table :: update.dev.pkg ()

Fungsi fcase () mirip dengan CASE WHENpernyataan SQL dan case_when()fungsi dplyr . Sintaks dasarnya adalah  fcase(condition1, "value1", condition2, "value2")dan seterusnya. Nilai default untuk "yang lainnya" dapat ditambahkan dengan default = value.

Berikut kode untuk membuat kolom Bahasa baru:

usd [, Bahasa: = fcase (

RUser &! PythonUser, "R",

PythonUser &! RUser, "Python",

PythonUser & RUser, "Keduanya",

! PythonUser &! RUser, "Tidak Ada"

)]

Saya meletakkan setiap ketentuan pada baris terpisah karena menurut saya lebih mudah untuk dibaca, tetapi Anda tidak perlu melakukannya.

Perhatian: Jika Anda menggunakan RStudio, struktur data.table tidak secara otomatis diperbarui di panel RStudio kanan atas setelah Anda membuat kolom baru dengan operator walrus. Anda perlu mengklik ikon segarkan secara manual untuk melihat perubahan pada jumlah kolom.

Ada beberapa simbol lain yang tidak akan saya bahas di artikel ini. Anda dapat menemukan daftarnya di file bantuan "simbol khusus" data.table dengan menjalankan help("special-symbols"). Salah satu yang paling berguna, .SD, sudah memiliki artikel dan video Lakukan Lebih Banyak Dengan R sendiri, "Cara menggunakan .SD dalam paket R data.table."

Untuk tips R lainnya, buka halaman "Lakukan Lebih Banyak Dengan R" atau lihat playlist YouTube "Lakukan Lebih Banyak Dengan R".