Buku "The Art of Programming dalam R. Immersing in Big Data"

gambar Hai, habrozhiteli! Banyak pengguna menggunakan R untuk tugas-tugas spesifik - di sini untuk membuat histogram, di sana untuk melakukan analisis regresi atau melakukan operasi terpisah lainnya yang terkait dengan pemrosesan data statistik. Tetapi buku ini ditulis untuk mereka yang ingin mengembangkan perangkat lunak dalam R. Keterampilan pemrograman pembaca yang dituju buku ini dapat berkisar dari kualifikasi profesional hingga "Saya mengambil kursus pemrograman di perguruan tinggi," tetapi kuncinya adalah menulis kode R untuk tujuan tertentu . (Pengetahuan statistik yang menyeluruh umumnya tidak diperlukan.)

Beberapa contoh pembaca yang mungkin mendapat manfaat dari buku ini:

  • Seorang analis (misalnya, bekerja di rumah sakit atau lembaga pemerintah) yang harus secara teratur menerbitkan laporan statistik dan mengembangkan program untuk tujuan ini.
  • Seorang ilmuwan yang terlibat dalam pengembangan metodologi statistik - baru atau mengintegrasikan metode yang ada ke dalam prosedur terintegrasi. Metodologi perlu dikodekan sehingga dapat digunakan dalam komunitas penelitian.
  • Spesialis dalam pemasaran, dukungan hukum, jurnalisme, penerbitan, dll., Terlibat dalam pengembangan kode untuk membangun representasi grafik data yang kompleks.
  • Pemrogram profesional dengan pengalaman pengembangan perangkat lunak ditugaskan untuk proyek yang berkaitan dengan analisis statistik.
  • Siswa mempelajari statistik dan pemrosesan data.


Dengan demikian, buku ini bukan referensi ke metode statistik yang tak terhitung jumlahnya dari paket luar biasa R. Bahkan, buku ini dikhususkan untuk pemrograman dan berkaitan dengan masalah pemrograman yang jarang ditemukan di buku-buku lain tentang R. Bahkan topik-topik mendasar dipertimbangkan dari sudut pemrograman. Beberapa contoh pendekatan ini:

  • Buku ini berisi bagian dari "Contoh Lanjut". Biasanya, mereka menyediakan fungsi tujuan umum yang lengkap alih-alih potongan kode terisolasi berdasarkan data tertentu. Selain itu, beberapa fungsi ini mungkin berguna dalam pekerjaan sehari-hari Anda dengan R. Dengan mempelajari contoh-contoh ini, Anda tidak hanya akan belajar bagaimana konstruksi R tertentu bekerja, tetapi juga belajar bagaimana menggabungkannya ke dalam program yang bermanfaat. Dalam banyak kasus, saya memberikan deskripsi solusi alternatif dan menjawab pertanyaan: "Mengapa ini dilakukan dengan cara ini?"
  • Materi disajikan dengan mempertimbangkan persepsi programmer. Sebagai contoh, ketika menggambarkan frame data, saya tidak hanya mengklaim bahwa frame data dalam R adalah daftar, tetapi saya juga menunjukkan konsekuensi dari fakta ini dari sudut pandang pemrograman. Juga dalam teks, R dibandingkan dengan bahasa lain di mana ini mungkin berguna (untuk pembaca yang berbicara bahasa ini).
  • Debugging memainkan peran penting dalam pemrograman dalam bahasa apa pun, tetapi sebagian besar buku tentang R tidak menyebutkan topik ini. Dalam buku ini, saya mengabdikan seluruh bab untuk alat debugging, menggunakan prinsip "contoh-contoh lanjutan", dan menyajikan demo yang dikembangkan sepenuhnya tentang bagaimana program-program tersebut benar-benar dipertanyakan.
  • Saat ini, komputer multi-core telah muncul di semua rumah, dan pemrograman prosesor grafis (GPU) menghasilkan revolusi yang tak terlihat di bidang komputasi ilmiah. Semakin banyak aplikasi R membutuhkan jumlah komputasi yang sangat besar, dan pemrosesan paralel telah menjadi relevan bagi programmer R. Seluruh bab dikhususkan untuk topik ini dalam buku ini, selain menjelaskan mekanika, contoh-contoh lanjutan juga diberikan.
  • Bab terpisah membahas tentang bagaimana menggunakan informasi tentang implementasi internal dan aspek-aspek R lainnya untuk mempercepat pekerjaan kode R.
  • Salah satu bab berfokus pada antarmuka R dengan bahasa pemrograman lain seperti C dan Python. Sekali lagi, perhatian khusus diberikan pada contoh dan rekomendasi canggih untuk debugging.

Kutipan. 7.8.4. Kapan variabel global digunakan?


Tidak ada konsensus tentang penggunaan variabel global dalam komunitas programmer. Jelas, tidak ada jawaban yang tepat untuk pertanyaan yang diajukan dalam judul bagian ini, karena ini adalah pertanyaan tentang preferensi dan gaya pribadi. Namun demikian, banyak programmer percaya bahwa pelarangan lengkap pada variabel global, yang didukung oleh banyak guru pemrograman, akan sangat sulit. Pada bagian ini, kami menguji manfaat yang mungkin dari variabel global dalam konteks struktur R. Istilah “variabel global” berarti setiap variabel yang berada dalam hierarki lingkungan di atas tingkat kode kepentingan.

Menggunakan variabel global dalam R lebih umum daripada yang Anda harapkan. Anehnya, R menggunakan variabel global sangat luas dalam implementasi internal (baik dalam kode C dan dalam fungsi R). Jadi, operator super-tugas << - digunakan dalam banyak fungsi pustaka R (meskipun biasanya digunakan untuk menulis ke variabel yang terletak hanya satu tingkat lebih tinggi dalam hierarki variabel). Kode multi-threaded dan kode GPU yang digunakan untuk menulis program cepat (lihat bab 16) biasanya menggunakan variabel global yang menyediakan mekanisme utama interaksi antara pelaksana paralel.

Sekarang, untuk konkret, mari kita kembali ke contoh sebelumnya dari bagian 7.7:

f <- function(lxxyy) { # lxxyy — ,  x  y ... lxxyy$x <- ... lxxyy$y <- ... return(lxxyy) } #  x  y lxy$x <- ... lxy$y <- ... lxy <- f(lxy) #   x  y ... <- lxy$x ... <- lxy$y 

Seperti disebutkan sebelumnya, kode ini dapat menjadi rumit, terutama jika x dan y adalah daftar itu sendiri.

Di sisi lain, lihat skema alternatif menggunakan variabel global:

 f <- function() { ... x <<- ... y <<- ... } #  x  y x <-... y <-... f() #  x  y  #   x  y ... <- x ... <- y 

Mungkin versi kedua jauh lebih bersih, kurang besar dan tidak memerlukan manipulasi daftar. Hapus kode biasanya membuat lebih sedikit masalah dalam penulisan, debugging, dan pemeliharaan.

Untuk alasan ini - untuk menyederhanakan dan mengurangi kebodohan kode - kami memutuskan untuk menggunakan variabel global alih-alih mengembalikan daftar dalam kode DES yang diberikan sebelumnya. Pertimbangkan contoh ini secara lebih rinci.

Dua variabel global digunakan (keduanya daftar berisi informasi yang berbeda): variabel sim dikaitkan dengan kode perpustakaan, dan variabel mm1glbls dikaitkan dengan kode aplikasi spesifik M / M / 1. Mari kita mulai dengan sim.

Bahkan programmer yang terkekang tentang variabel global setuju bahwa penggunaan variabel tersebut dapat dibenarkan jika mereka benar-benar global - dalam arti bahwa mereka banyak digunakan dalam program. Semua ini berkaitan dengan variabel sim dari contoh DES: digunakan baik dalam kode perpustakaan (dalam schedevnt (), getnextevnt () dan dosim ()) dan dalam kode M / M / 1 (dalam mm1reactevnt ()). Dalam contoh khusus ini, panggilan berikutnya ke sim terbatas pada membaca, tetapi merekam dimungkinkan dalam beberapa situasi. Contoh khas dari jenis ini adalah kemungkinan implementasi pembatalan acara. Misalnya, situasi seperti itu dapat terjadi ketika memodelkan prinsip "lebih awal dari dua": dua peristiwa direncanakan, dan ketika salah satu dari mereka terjadi, yang lain harus dibatalkan.

Dengan demikian, menggunakan sim sebagai variabel global tampaknya dibenarkan. Namun, jika kami dengan tegas menolak untuk menggunakan variabel global, sim dapat ditempatkan di variabel lokal di dalam dosim (). Fungsi ini akan meneruskan sim dalam argumen semua fungsi yang disebutkan dalam paragraf sebelumnya (schedevnt (), getnextevnt (), dll.), Dan masing-masing fungsi ini akan mengembalikan variabel sim yang dimodifikasi.
Misalnya, baris 94:

 reactevnt(head) 

dikonversi ke formulir berikut:

 sim <- reactevnt(head) 

Setelah itu, baris berikut harus ditambahkan ke fungsi mm1reactevnt () yang terkait dengan aplikasi tertentu:

 return(sim) 

Anda dapat melakukan sesuatu yang mirip dengan mm1glbls dengan memasukkan dalam dosim () variabel lokal dengan nama (misalnya) appvars. Tetapi jika ini dilakukan dengan dua variabel, maka mereka harus dimasukkan dalam daftar sehingga kedua variabel dapat dikembalikan dari fungsi, seperti pada contoh di atas dari fungsi f (). Dan kemudian struktur besar daftar di dalam daftar muncul, yang disebutkan di atas, atau lebih tepatnya, daftar di dalam daftar di dalam daftar.

Di sisi lain, penentang penggunaan variabel global memperhatikan bahwa kesederhanaan kode tidak sia-sia. Mereka khawatir bahwa selama proses debugging ada kesulitan dalam menemukan tempat di mana variabel global mengubah nilainya, karena perubahan dapat terjadi di mana saja dalam program. Tampaknya dalam dunia editor teks modern dan alat pengembangan terintegrasi yang akan membantu menemukan semua kemunculan variabel, masalahnya berjalan di pinggir jalan (artikel asli yang mendesak untuk meninggalkan penggunaan variabel global diterbitkan pada tahun 1970!). Namun demikian, faktor ini harus diperhitungkan.

Masalah lain yang disebutkan kritik ditemui ketika memanggil fungsi dari beberapa bagian yang tidak terkait dari suatu program dengan nilai yang berbeda. Sebagai contoh, bayangkan bahwa fungsi f () dipanggil dari berbagai bagian program, dengan setiap panggilan menerima nilai x dan y sendiri alih-alih satu nilai untuk masing-masing. Masalahnya dapat diselesaikan dengan membuat vektor nilai x dan y di mana setiap instance dari f () dalam program Anda memiliki elemen terpisah. Namun, ini akan kehilangan kesederhanaan menggunakan variabel global.

Masalah-masalah ini dihadapi tidak hanya dalam R, tetapi juga dalam konteks yang lebih umum. Namun, dalam R penggunaan variabel global di tingkat atas menciptakan masalah tambahan, karena pengguna di tingkat ini biasanya memiliki banyak variabel. Ada bahaya bahwa kode yang menggunakan variabel global secara tidak sengaja dapat mengganti variabel yang sama sekali asing dengan nama yang sama.

Tentu saja, masalahnya dapat diselesaikan dengan mudah - cukup pilih nama panjang untuk variabel global yang terkait dengan aplikasi tertentu. Namun, lingkungan juga memberikan kompromi yang masuk akal, seperti dalam situasi berikut untuk contoh DES.

Di dalam fungsi dosim (), baris

 sim <<- list() 

dapat diganti dengan string

 assign("simenv",new.env(),envir=.GlobalEnv) 

Ini menciptakan lingkungan baru yang dirujuk oleh variabel simenv di tingkat atas. Lingkungan ini berfungsi sebagai wadah untuk merangkum variabel global yang dapat diakses dengan panggilan untuk mendapatkan () dan menetapkan (). Misalnya, string

 if (is.null(sim$evnts)) { sim$evnts <<- newevnt 

di schedevnt () mengambil formulir

 if (is.null(get("evnts",envir=simenv))) { assign("evnts",newevnt,envir=simenv) 

Ya, solusi ini juga rumit, tetapi setidaknya tidak serumit daftar di dalam daftar di dalam daftar. Dan itu melindungi terhadap penulisan yang tidak disengaja ke variabel asing di tingkat atas. Menggunakan operator super-tugas masih memberikan kode yang kurang rumit, tetapi pertukaran ini harus diperhitungkan.

Seperti biasa, tidak ada gaya pemrograman tunggal yang memberikan hasil terbaik dalam semua situasi. Solusi dengan variabel global adalah opsi lain yang harus dimasukkan dalam gudang alat pemrograman Anda.

7.8.5. Sirkuit pendek


Biarkan saya mengingatkan Anda bahwa penutupan R terdiri dari argumen dan tubuh fungsi bersamaan dengan lingkungan pada saat panggilan berlangsung. Fakta bahwa lingkungan dimasukkan adalah terlibat dalam paradigma pemrograman, yang menggunakan konsep, juga disebut penutupan (ada beberapa istilah yang berlebihan di sini).

Penutupan adalah fungsi yang membuat variabel lokal, dan kemudian membuat fungsi lain yang mengakses variabel ini. Uraiannya terlalu abstrak, jadi saya lebih baik memberikan contoh.

 1 > counter 2 function () { 3 ctr <- 0 4 f <- function() { 5 ctr <<- ctr + 1 6 cat("this count currently has value",ctr,"\n") 7 } 8 return(f) 9 } 

Mari kita periksa bagaimana kode ini bekerja sebelum masuk ke detail implementasi:

 > c1 <- counter() > c2 <- counter() > c1 function() { ctr <<- ctr + 1 cat("this count currently has value",ctr,"\n") } <environment: 0x8d445c0> > c2 function() { ctr <<- ctr + 1 cat("this count currently has value",ctr,"\n") } <environment: 0x8d447d4> > c1() this count currently has value 1 > c1() this count currently has value 2 > c2() this count currently has value 1 > c2() this count currently has value 2 > c2() this count currently has value 3 > c1() this count currently has value 3 

Di sini, fungsi penghitung () dipanggil dua kali, dan hasilnya diberikan c1 dan c2. Seperti yang diharapkan, kedua variabel ini terdiri dari fungsi, yaitu salinan f (). Namun, f () mengakses variabel ctr melalui operator super-penugasan, dan variabel ini akan menjadi variabel dengan nama lokal yang ditentukan ke counter (), karena itu akan menjadi yang pertama di jalur dalam hierarki lingkungan. Ini adalah bagian dari lingkungan f (), dan dengan demikian dikemas ke dalam apa yang kembali ke sisi panggilan counter (). Poin kuncinya adalah bahwa dengan panggilan berbeda ke counter (), variabel ctr akan berada di lingkungan yang berbeda (dalam contoh lingkungan, ia disimpan dalam memori di alamat 0x8d445c0 dan 0x8d447d4). Dengan kata lain, panggilan yang berbeda untuk membalas () akan membuat instance ctr yang berbeda secara fisik.

Akibatnya, fungsi c1 () dan c2 () berfungsi sebagai penghitung yang sepenuhnya independen. Ini bisa dilihat dari contoh di mana setiap fungsi dipanggil beberapa kali.

»Informasi lebih lanjut tentang buku ini dapat ditemukan di situs web penerbit
» Isi
» Kutipan

Kupon diskon 25% untuk penjaja - R

Setelah pembayaran versi kertas buku, versi elektronik buku dikirim melalui email.

Source: https://habr.com/ru/post/id452746/


All Articles