Pemrograman Fungsi dan OOP

Pendahuluan

Fungsi (function) adalah kode-kode yang disusun untuk melakukan tugas tertentu, seperti perhitungan matematis, pembacaan data, analisis statistik, dan lainnya. Di dalam paket pemrograman R banyak fungsi yang dapat dimanfaatkan untuk komputasi dan grafik. Fungsi yang tidak ada, dapat diciptakan sendiri.

Membuat Fungsi

Struktur dalam membuat fungsi dapat dituliskan sebagai berikut

myfunction <- function(arg1, arg2, … ){
statements
return(object)
}

  • myfunction adalah nama fungsi yang akan dibuat.
  • arg adalah argumen atau input fungsi. Fungsi pada umumnya memiliki argumen. Argumen tersebut dapat diberikan nilai default, contoh: function(x=10) sehingga dalam fungsi tersebut terdapat argumen x dengan nilai default 10. Argumen juga dapat ditulis berulang/ tidak didefinisikan pasti (menggunakan “…”) contoh function(x=10, ...). Selain itu juga, argumen fungsi R dapat menerima nama fungsi R lain untuk dijalankan, contoh apply(x,1,mean).
  • statements adalah badan fungsi yang berisi perintah yang akan dijalankan pada fungsi tersebut.
  • return adalah output/ luaran dari fungsi. Output ini merupakan sebuah objek yang dapat dituliskan secara langsung atau menggunakan fungsi return. Jika output memiliki mode berbeda, umumnya digunakan objek list.

Untuk menggunakan fungsi yang telah dibuat dapat menggunakan perintah namafungsi(arg1, arg2, ...). Jika argumen dituliskan secara berurutan tidak perlu menuliskan nama argumen, namun jika argumen tidak dituliskan secara berurutan, maka perlu menuliskan nama argumen. Sebagai contoh sebuah fungsi dengan nama fungsi1 yang memiliki argumen arg1 dan arg2 atau dapat dituliskan fungsi1(arg1, arg2) jika fungsi tersebut dipanggil dengan penulisan argumen yang berurutan maka dapat dituliskan dengan fungsi1(10,20) namun, jika argumen tidak berurutan maka dituliskan dengan fungsi(arg2=20, arg1=10).

Untuk menangani kesalahan dalam fungsi disediakan fungsi-fungsi:

  • try: pembungkus untuk menjalakan ekspresi yang mungkin gagal dan memungkinkan kode pengguna untuk menangani pemulihan kesalahan. Contoh: try(log("a"))
  • tryCatch: menyediakan mekanisme untuk menangani kondisi tidak biasa, termasuk kesalahan dan peringatan. Contoh: tryCatch(log(10), finally =print("Hello)).
  • warning: menghasilkan pesan peringatan yang sesuai dengan argumennya.
  • stop: menghentikan eksekusi ekspresi saat ini.

Contoh membuat fungsi angka acak z yang memerlukan 2 argumen n dan pw. Dimana argumen n akan digunakan untuk menjalankan angka acak dari distribusi uniform, dan pw akan digunakan untuk memangkatkan formula yang sudah dibuat. Ouput dari fungsi ini adalah angka acak.

Fungsi 1 dengan output hanya nilai z saja.

angka_acak1 = function(n,pw) {
  x=runif(n)
  y=runif(n)
  z=(x+y)^pw
  return(z)
}
# menggunakan fungsi  
angka_acak1(10,2)
 [1] 0.8109101 0.5256765 0.8093137 1.2340366 0.8599421 1.7641868 0.2828971
 [8] 1.0366930 2.7104007 0.1193721

Fungsi 2 dengan output berupa nilai x, y, dan z.

# Membuat fungsi
angka_acak2 = function(n,pw) {
  x = runif(n)
  y = runif(n)
  z = (x+y)^pw
  return(list(x=x,y=y,z=z))
}

# Menggunakan fungsi
angka_acak2(10,2)
$x
 [1] 0.9697166 0.4538758 0.7011635 0.8405922 0.5078023 0.8986305 0.4554238
 [8] 0.2650108 0.5855058 0.6683247

$y
 [1] 0.91332522 0.07449606 0.14467379 0.17599052 0.77209842 0.29575276
 [7] 0.26532362 0.34370593 0.54473201 0.55445346

$z
 [1] 3.5458464 0.2791768 0.7154408 1.0334404 1.6381458 1.4265514 0.5194768
 [8] 0.3705360 1.2774376 1.4951865

Fungsi 3 dengan memberikan nilai default pada argumen berupa n=1 dan pw = 2, sehingga ketika fungsi tersebut dipanggil tanpa menuliskan argumen, akan dijalankan fungsi defaultnya.

angka_acak3 = function(n=10,pw=2) {
  x = runif(n)
  y = runif(n)
  z = (x+y)^pw
  return(z)
}

angka_acak3()
 [1] 1.6890573 2.7296310 0.3688170 0.3195596 0.3388521 1.0603032 1.1353316
 [8] 1.1567037 0.5341865 2.5667743

Fungsi 4 dituliskan tanpa menggunakan argumen. Ketika fungsi tersebut akan digunakan maka dilakukan assign nilai yang diperlukan di dalam fungsi tersebut.

angka_acak4 = function() {
  x = runif(n)
  y = runif(n)
  z = (x+y)^pw
  return(z)
}

n <- 5; pw <- 3
angka_acak4()
[1] 0.09108059 0.69106836 0.35606088 1.85456456 0.03303008

Fungsi mencari median dari suatu vektor

med <- function(vect) {
  n <- length(vect)
  vects <- sort(vect)
  if(n%%2 == 1) {
    m <- vects[(n+1)/2]
    }
  else {
    m <- (vects[n/2]+vects[(n/2)+1])/2
    }
  return(m)
}

x1 <- c(1,5,3,7,3,4,2,7)
med(x1)
[1] 3.5

Fungsi mencari modus dari suatu vektor

modus <- function(vect) {
  v <- unique(vect)
  f <- NULL
  for(i in v) {
    byk <- sum(vect==i)
    f <- c(f,byk)
  }
  
fmax <- max(f)
vf <- cbind(v,f)
mode <- vf[f==fmax,]
return(mode)
}
modus(x1)
     v f
[1,] 3 2
[2,] 7 2

Fungsi untuk menduga parameter pada regresi berganda

# Membuat fungsi
p.est <- function(A) {
  if(!is.matrix(A))
    stop("input must be on matrix")
  x1<-A[,-1]
  y <-A[,1]
  one<-rep(1,nrow(A))
  x <-cbind(one,x1)
  colnames(x)<-paste("x",1:ncol(x),sep="")
  b.est<-as.vector(solve(t(x) %*% x) %*% (t(x) %*% y))
  names(b.est)<-paste("b",0:(length(b.est)-1),sep="")
  fitted.value<-as.vector(x%*%b.est)
  error<-as.vector(y-fitted.value)
  names(fitted.value)<-names(error)<-1:nrow(A)
  list(beta.est=b.est,fit.val=fitted.value,error=error)
}

# Memasukkan data
Pendapatan<-c(3.5,3.2,3.0,2.9,4.0,2.5,2.3)
Biaya.Iklan<-c(3.1,3.4,3.0,3.2,3.9,2.8,2.2)
Jumlah.Warung<-c(30,25,20,30,40,25,30)
X<-cbind(Pendapatan,Biaya.Iklan,Jumlah.Warung)
p.est(X)
$beta.est
         b0          b1          b2 
-0.21381852  0.89843390  0.01745279 

$fit.val
       1        2        3        4        5        6        7 
3.094910 3.277176 2.830539 3.184754 3.988185 2.738116 2.286320 

$error
          1           2           3           4           5           6 
 0.40508982 -0.07717642  0.16946108 -0.28475357  0.01181483 -0.23811608 
          7 
 0.01368033 
# Melakukan pengecekan dengan fungsi lm
model<-lm(Pendapatan~Biaya.Iklan+Jumlah.Warung)

# Mengeluarkan koefisien dari model regresi
model$coefficients
  (Intercept)   Biaya.Iklan Jumlah.Warung 
  -0.21381852    0.89843390    0.01745279 
# Mengeluarkan fitted values
model$fitted.values
       1        2        3        4        5        6        7 
3.094910 3.277176 2.830539 3.184754 3.988185 2.738116 2.286320 
# Mengeluarkan residuals
model$residuals
          1           2           3           4           5           6 
 0.40508982 -0.07717642  0.16946108 -0.28475357  0.01181483 -0.23811608 
          7 
 0.01368033 

Object Oriented Programming

Pemrograman berorientasi objek merupakan sebuah paradigma dalam pembuatan sebuah program. OOP menitikberatkan pada identifikasi objek-objek yang terlibat dalam sebuah program dan bagaimana objek-objek tersebut berinterakasi. Pada OOP, program yang dibangun akan dibagi-bagi menjadi objek-objek. OOP menyediakan class dan object sebagai alat dasar untuk meminimalisir dan mengatur kompleksitas dari program.

Sebagai contoh, kita dapat menganggap class seperti sebuah sketsa mobil yang memiliki semua detail mengenai nama_model, nomor_model, mesin, dll. Berdasarkan deskripsi tersebut maka kita akan memilih sebuah mobil. Mobil tersebut adalah sebuah object. Setiap objek mobil memiliki karakteristik dan fitur masing masing.

Beberapa prinsip dasar dari OOP adalah abstraksi, enkapsulasi, inherintance (pewarisan), dan polymorphism.

Class (kelas)

Merupakan definisi statik (kerangka dasar) dari objek yang akan diciptakan.
Suatu class dibagi menjadi:

  • Property, merupakan data atau state yang dimiliki oleh class. Contoh pada class Mobil, memiliki property: warna, Model, Produsen.
  • Method, merupakan behavior (perilaku) sebuah class. Bisa dikatakan sebagai aksi atau tindakan yang bisa dilakukan oleh suatu class. Contoh pada class Mobil, memiliki method: Start, Stop, Change Gear, Turn.

Object

Objek adalah komponen yang diciptakan dari class (instance of class). Satu class bisa menghasilkan banyak objek. Proses untuk membuat sebuah objek disebut instantiation. Setiap objek memiliki karakteristik dan fitur masing masing. Objek memiliki siklus creation, manipulation, dan destruction.

Sebagai ilustrasi, objek mobil mazda dan kijang diturunkan dari class yang sama yaitu class mobil, namun memiliki property yang berbeda seperti warna dan model.

OOP in R

R telah mengimplementasikan pemrograman berorientasi objek. Semua dalam R adalah objek. Pengembangan awal objek di R menggunakan Class System S3 yang tidak terlalu ketat. Pendefinisian yang ketat secara formal, R menggunakan Class System S4.

Ilustrasi:
Sebuah class coords dirancang untuk digunakan dengan menyimpan data koordinat titik pada dua buah vektor X dan Y. Metode pada class ini terdiri dari metode print, length, bbox, dan plot. Class lain dirancang sebagai turunan dari class coords dengan menambahkan data nilai (value) untuk setiap titik pada koordinat X dan Y. Metode pada class vcoords merupakan pewarisan dari class coords dan operasi-operasi aritmetik terhadap nilai (value)-nya.

Object - Class System S3

Suatu class dalam system S3 tidak didefinisikan dengan ketat. Fungsi class digunakan untuk menjadikan sebuah objek menjadi class yang diinginkan.
Sebagai contoh:

# List creation with its attributes x and y.
pts <- list(x=round(rnorm(5),2),
            y = round(rnorm(5),2))
class(pts)
[1] "list"
pts
$x
[1]  1.11 -1.12 -0.78 -0.41 -1.44

$y
[1]  0.47  0.74 -0.67 -0.04 -0.30

Menjadikan pts sebagai class baru:

# Membuat class coords
#class(pts) <- "coords"
class(pts)
[1] "list"
# Membuat object
pts
$x
[1]  1.11 -1.12 -0.78 -0.41 -1.44

$y
[1]  0.47  0.74 -0.67 -0.04 -0.30

Contoh lain:

# Membuat list Mobil1
Mobil1 <- list(Nama="Toyota",
               Panjang=3.5,
               Lebar=2,
               Kecepatan=180)
class(Mobil1)
[1] "list"
# Membuat class mobil
class(Mobil1) <- "mobil"

# Membuat list Mobil2
Mobil2 <- list(Nama="Suzuki",
               Panjang=1,
               Lebar=1.8,
               Kecepatan=150)

# Membuat class mobil
class(Mobil2) <- "mobil"

Langkan sederhana dalam membuat objek dari suatu class seperti ini sangat tidak dianjurkan karena nilai-nilai instance-nya mungkin tidak tepat.

Konstruktor

Sebuah fungsi konstruktor dibutuhkan untuk mengecek instance sesuai dengan objek. Misalkan mengecek x dan y harus berupa numerik, vektor tidak boleh NA, vektor harus memiliki panjang yang sama, dll.

Fungsi Konstruktor untuk Membuat Class coords

coords <- function (x,y){
  if (!is.numeric (x)|| !is.numeric (y)||!all(is.finite(x))|| !all(is.finite(y)))
    stop ("Titik koordinat tidak tepat !")
  if (length (x) != length (y))
    stop ("Panjang koordinat berbeda")
  pts <- list (x=x,y=y)
  class (pts)= "coords"
  pts
  }

pts <- coords (x= round ( rnorm (5),2),
               y= round ( rnorm (5),2))

Fungsi Konstruktor untuk Membuat Class mobil

Mobil <- function(Nama, Panjang, Lebar, Kecepatan) {
  if(Panjang<2 || Lebar<1.5 || Kecepatan<80)
    stop("atribut tidak sesuai")
  Mobil <- list(Nama=Nama,
                Panjang=Panjang,
                Lebar=Lebar,
                Kecepatan=Kecepatan)
  class(Mobil) <- "mobil"
  Mobil
}

Mobil3 <- Mobil("Daihatsu", 2.1, 1.9, 120)
Mobil3
$Nama
[1] "Daihatsu"

$Panjang
[1] 2.1

$Lebar
[1] 1.9

$Kecepatan
[1] 120

attr(,"class")
[1] "mobil"

Aksesor

Sebagai ilustrasi, untuk mengakses dalam class coords, dapat menggunakan akses objek awalnya (list). Tetapi, secara formal tidak dianjurkan mengakses data secara langsung. Diperlukan suatu fungsi aksesor untuk mengakses pada class coords.

Ilustrasi akses pada class coord dengan menggunakan 2 fungsi

xcoords= function (obj)obj $x
ycoords= function (obj)obj $y
xcoords(pts)
[1]  0.86 -0.87 -1.67 -2.40 -1.13
ycoords(pts)
[1] -1.55  0.51  1.81 -1.42  0.16

Ilustrasi akses pada class mobil secara langsung

Mobil2$Nama
[1] "Suzuki"
Mobil3$Panjang
[1] 2.1

Ilustrasi akses pada class mobil menggunakan fungsi aksesor

nama <- function(objek) objek$Nama
kecepatan <- function(objek) objek$Kecepatan
panjang <- function(objek) objek$Panjang
lebar<- function(objek) objek$Lebar
nama(Mobil1)
[1] "Toyota"
kecepatan(Mobil3)
[1] 120
panjang(Mobil3)
[1] 2.1

Fungsi Generik

Fungsi generik merupakan suatu method dari suatu class objek dalam R. Fungsi generik bertindak untuk beralih memilih fungsi tertentu atau metode tertentu yang dijalankan sesuai dengan class-nya. Untuk mendefinisi ulang suatu fungsi generik digunakan syntax method.class <-function() ekspresibaru. Terdapat beberapa fungsi generik yang sudah ada: print, plot, dll.

Method Length

Fungsi length menghitung banyaknya anggota dari objek.

Pada ilustrasi ini, length akan menghitung banyaknya anggota list pada coord sebelumnya, sehingga kurang tepat.

length(pts)
[1] 2

Definisi ulang untuk class coords:

length.coords = function(obj)
  length(xcoords(obj))
length(pts)
[1] 5

Membuat Fungsi Generik Baru

Untuk membuat suatu method yang dapat diwariskan, maka method tersebut harus dijadikan fungsi generik. Misal akan dibuat method bbox yang merupakan sebuah boundary box.

bbox <- function (obj)
  UseMethod ("bbox") #menjadikan bbox sebagai fungsi generik

bbox.coords <- function (obj){
  matrix (c(range (xcoords(obj)),
            range (ycoords(obj))),
          nc=2, dimnames = list (
            c("min", "max"),
            c("x:", "y:")))
  }
bbox(pts)
       x:    y:
min -2.40 -1.55
max  0.86  1.81

Misalkan akan dibuat plot khusus untuk class coords

plot.coords <- function (obj,bbox=FALSE,...){
  if (bbox){
    plot (xcoords(obj),ycoords(obj),...);
    x <- c(bbox(obj)[1],bbox(obj)[2],bbox(obj)[2],bbox(obj)[1]);
    y <- c(bbox(obj)[3],bbox(obj)[3],bbox(obj)[4],bbox(obj)[4]);
    polygon (x,y)
    } else {
      plot (xcoords(obj),ycoords(obj),...)
    }
  }

Plot

plot(pts)

plot(pts, bbox=T, pch=19, col="red")

Pewarisan Class

Sebagai ilustrasi, jika diinginkan sebuah objek yang berisi lokasi (coords) dan terdapat nilai pada lokasi tersebut maka diperlukan class baru vcoords sebagai turunan dari coords.

Fungsi konstruktor dari class vcoords

vcoords <- function (x,y,v){
  if (!is.numeric (x)|| !is.numeric (y) || !is.numeric (v)|| !all(is.finite(x))|| !all(is.finite(y)))
    stop ("Titik koordinat tidak tepat !")
  if (length (x) != length (y)||
      length (x) != length (v))
    stop ("Panjang koordinat berbeda")
  pts <- list (x=x,y=y,v=v)
  class (pts)= c("vcoords", "coords")
  pts
  }

nilai <- function (obj)obj$v

Fungsi xcoords dan ycoords dan method bbox dari class coords masih sama sehingga tidak perlu didefinisi ulang.

vpts <- vcoords(x= round ( rnorm (5),2),
                y= round ( rnorm (5),2),
                v= round ( runif (5,0,100)))
vpts
[1] (-0.76, -0.41) (-0.42, -1.71) ( 0.27,  1.07) (-0.01,  1.46) (-0.43,  0.07)
xcoords(vpts)
[1] -0.76 -0.42  0.27 -0.01 -0.43
ycoords(vpts)
[1] -0.41 -1.71  1.07  1.46  0.07
bbox(vpts)
       x:    y:
min -0.76 -1.71
max  0.27  1.46

Method print juga masih diwariskan dari class coords tetapi perlu didefinisi ulang.

print.vcoords <- function (obj){
  print (paste ("(",
                format (xcoords(obj)),
                ", ",
                format (ycoords(obj)),
                "; ", format (nilai(obj)),
                ")",sep=""),
         quote =FALSE)
}
vpts
[1] (-0.76, -0.41; 99) (-0.42, -1.71;  5) ( 0.27,  1.07; 56) (-0.01,  1.46; 42)
[5] (-0.43,  0.07; 65)

Method plot perlu didefinisi ulang

plot.vcoords <- function (
  obj,txt=FALSE,bbox=FALSE,...){
  if (bbox){
    if (!txt){
      plot (xcoords(obj),
            ycoords(obj),...);
      } else {
        plot (xcoords(obj),
              ycoords(obj),type="n",...);
        text (xcoords(obj),
              ycoords(obj),nilai(obj),...);
        }
    x <- c(bbox(pts)[1],
           bbox(pts)[2],bbox(pts)[2],bbox(pts)[1]);
    y <- c(bbox(pts)[3],bbox(pts)[3],bbox(pts)[4],bbox(pts)[4]);
    polygon (x,y)
    } else {
      if (!txt){
        plot (xcoords(obj),
              ycoords(obj),...);
        } else {
          plot (xcoords(obj),
                ycoords(obj),type="n",...);
          text (xcoords(obj), 
                ycoords(obj),nilai(obj) ,...);
        }
    }
  }

Membuat Plot

plot (vpts)

plot (vpts,txt=T,bbox=T,col ="red ")

Pemeriksaan suatu class objek

Untuk mengecek apakah suatu objek merupakan suatu class digunakan fungsi inherits

inherits (pts,"coords")
[1] TRUE
inherits (pts,"vcoords")
[1] FALSE
inherits (vpts,"coords")
[1] TRUE
inherits (vpts,"vcoords")
[1] TRUE

Object : Class System S4

Class System S4 mengatasi masalah dalam Class System S3 dengan sistem objek lebih formal. Salah satu keuntungannya adalah sistem penurunan dari class/ objek. Dalam sistem objek formal, setiap objek didefinisikan secara formal dalam suatu class. Sebuah class terdiri dari slot dengan tipe atau class spesifik. Class dideklarasikan dengan fungsi setClass.

Contoh, mendefinisikan ulang class coords sebelumnya ke class system S4

setClass("coords",
         representation(x="numeric",
                        y="numeric"))

Contoh, membuat objek car

setClass("car",
         representation(Nama="character",
                        Panjang="numeric",
                        Lebar="numeric",
                        Kecepatan="numeric"))

Car1 <- new("car",
            Nama="Toyota",
            Panjang=3.5, Lebar=2,
            Kecepatan=180)

Konstruktor

Membuat objek coords

coords <- function (x,y){
  if ( length (x) != length (y))
    stop (" length x dan y harus bernilai sama ")
  if (!is.numeric (x)|| !is.numeric (y))
    stop ("x dan y harus vektor numeric ")
  new("coords",
      x= as.vector (x), 
      y= as.vector (y))
}
pts <- coords (round (rnorm (5),2),
               round (rnorm (5),2))
pts
An object of class "coords"
Slot "x":
[1]  1.54 -0.91 -0.56 -1.72 -0.81

Slot "y":
[1] -1.14  0.04 -1.36 -0.56 -0.96

Membuat object car menggunakan fungsi konstruktor

car <- function(Nama,Panjang,Lebar,Kecepatan) {
  if(Panjang<2 || Lebar<1.5 || Kecepatan<80)
    stop("atribut tidak sesuai")
  new("car", Nama=Nama, Panjang=Panjang,
      Lebar=Lebar, Kecepatan=Kecepatan)
}

Car2 <- car("Suzuki", 2.4, 1.8, 150)
class(Car2)
[1] "car"
attr(,"package")
[1] ".GlobalEnv"
class(Mobil1)
[1] "mobil"

Aksesor

Akses terhadap slot menggunakan fungsi slot atau operator @

slot(pts,"x")
[1]  1.54 -0.91 -0.56 -1.72 -0.81
pts@x
[1]  1.54 -0.91 -0.56 -1.72 -0.81

Tetapi disarankan dengan 2 fungsi seperti sebelumnya:

xcoords <- function (obj)obj@x
ycoords <- function (obj)obj@y
xcoords(pts)
[1]  1.54 -0.91 -0.56 -1.72 -0.81

Akses terhadap slot pada objek car

Car1@Nama
[1] "Toyota"
Car2@Kecepatan
[1] 150

Akses terhadap slot pada objek car dengan fungsi aksesor

nama1 <- function(objek) objek@Nama
kecepatan1 <- function(objek) objek@Kecepatan
nama1(Car1)
[1] "Toyota"
kecepatan1(Car2)
[1] 150

Fungsi Generik

Fungsi generik show setara dengan fungsi generik print pada Class System S3. Penciptaan fungsi generik menggunakan fungsi setMethod. Argumen didefinisikan dalam signature.

setMethod(show,
          signature(object= "coords"),
          function (object)
            print (paste ("(",
                          format (xcoords(object)),
                          ", ",
                          format (ycoords(object)),
                          ")",sep=""),
                   quote =FALSE))
pts
[1] ( 1.54, -1.14) (-0.91,  0.04) (-0.56, -1.36) (-1.72, -0.56) (-0.81, -0.96)
setMethod(show, "car",
          function(object) {
            print(cat("Nama : ", nama1(object), "\n",
                      "Kecepatan : ", kecepatan1(object),
                      sep="")
                  )}
          )
Car2
Nama : Suzuki
Kecepatan : 150NULL

Fungsi Generik Baru

setGeneric("bbox",
           function (obj)
             standardGeneric("bbox")) 
[1] "bbox"
#[1] " bbox "

setMethod("bbox",
          signature(obj= "coords"),
          function (obj)
            matrix (c(range (xcoords(obj)),
                      range (ycoords(obj))),
                    nc=2,
                    dimnames = list (c("min", "max"),
                                     c("x:", "y:"))))
bbox(pts)
       x:    y:
min -1.72 -1.36
max  1.54  0.04

Fungsi Generik Plot

setMethod("plot",
          signature(x="coords"),
          function (x,bbox=FALSE,...){
            if (bbox){
              plot (xcoords(x),ycoords(x),...);
              x.1 <- c(bbox(x)[1],
                       bbox(x)[2],
                       bbox(x)[2],
                       bbox(x)[1]);
              y.1 <- c(bbox(x)[3],
                       bbox(x)[3],
                       bbox(x)[4],
                       bbox(x)[4]);
              polygon (x.1,y.1)
              } else {
                plot (xcoords(x),ycoords(x),...)
                }
            })
plot(pts)

plot(pts,bbox=T,pch=19, col="red",xlab="x",ylab="y")

Pewarisan Class

Terdapat class baru yang diturunkan dari coords dengan menambahkan slot nilai

setClass("vcoords",
         representation(nilai= "numeric"),
         contains= "coords")

vcoords <- function (x,y,nilai){
  if (( length (x) != length (y))|| (length (x) != length (nilai)))
    stop ("length x, y, dan nilai harus bernilai sama")
  if (!is.numeric (x)|| !is.numeric (y) || !is.numeric (nilai))
    stop ("x, y, dan nilai harus vektor numeric")
  new("vcoords", 
      x= as.vector (x),
      y= as.vector (y),
      nilai= as.vector (nilai))
  }

nilai <- function (obj)obj@nilai

vpts <- vcoords(xcoords(pts),ycoords(pts), round (100*runif (5)))
vpts
[1] ( 1.54, -1.14) (-0.91,  0.04) (-0.56, -1.36) (-1.72, -0.56) (-0.81, -0.96)

Method show yang diwariskan perlu didefinisi ulang

setMethod(show,
          signature(object= " vcoords "),
          function (object)
            print ( paste ("(",
                           format (xcoords(object)),
                           ", ",
                           format (ycoords(object)),
                           "; ", format (nilai(object)),
                           ")",sep=""),
                    quote =FALSE))
vpts
[1] ( 1.54, -1.14) (-0.91,  0.04) (-0.56, -1.36) (-1.72, -0.56) (-0.81, -0.96)

Method plot perlu didefiniskan ulang

setMethod("plot", signature(x="vcoords"),
          function (x,txt=FALSE,bbox=FALSE,...){
            if (bbox){
              if (!txt){
                plot (xcoords(x),ycoords(x),...);
                } else {
                  plot (xcoords(x),ycoords(x),type="n",...);
                  text (xcoords(x),ycoords(x),nilai(x),...);
                  }
              x.1 <- c(bbox(x)[1],bbox(x)[2],bbox(x)[2],bbox(x)[1]);
              y.1 <- c(bbox(x)[3],bbox(x)[3],bbox(x)[4],bbox(x)[4]);
              polygon (x.1,y.1)
              } else {
                if (!txt){
                  plot (xcoords(x),ycoords(x),...);
                  } else {
                    plot (xcoords(x),ycoords(x),type="n",...);
                    text (xcoords(x),ycoords(x),nilai(x),...);
                  }
                }
            })

Membuat Plot

plot(vpts)

plot (vpts,txt=T,bbox=T,pch=19, col="red")

Pemeriksaan Suatu Class Objek

Untuk mengecek apakah suatu objek merupakan suatu class digunakan fungsi is()

is(pts,"coords")
[1] TRUE
is(pts,"vcoords")
[1] FALSE
is(vpts,"coords")
[1] TRUE
is(vpts,"vcoords")
[1] TRUE

Untuk men-coerce objek ke objek lain dari suatu class digunakan fungsi as()

as(vpts,"coords")
[1] ( 1.54, -1.14) (-0.91,  0.04) (-0.56, -1.36) (-1.72, -0.56) (-0.81, -0.96)
as(pts, "vcoords")
[1] ( 1.54, -1.14) (-0.91,  0.04) (-0.56, -1.36) (-1.72, -0.56) (-0.81, -0.96)

Latihan

Buat fungsi bernama three.M yang digunakan untuk menghitung mean, median, modus dari suatu vector (tanpa menggunakan fungsi mean, quantile atau pun fungsi “instan” lain yang sudah tersedia sebelumnya di R). Hitung mean, median, dan modus dari suatu data rbinom(100,10, 0.5) dengan seed(123)

three.M <- function(vect) {
  n <- length(vect) # banyak data 
  
  # menhitung rataan 
  jumlah <- sum(vect)
  rataan <- jumlah/n
  
  # menhitung median
  vects <- sort(vect) # urutkan
  if(n%%2 == 1) {m <- vects[(n+1)/2]}
  else {m <- (vects[n/2]+vects[(n/2)+1])/2} 
  
  # menghitung modus
  v <- unique(vect)
  f <- NULL
  for(i in v) {
    byk <- sum(vect==i)
    f <- c(f,byk)
    }
  
  fmax <- max(f)
  vf <- cbind(v,f)
  mode <- vf[f==fmax,]
  
  # output
  my_list <- list("mean" = rataan, "median" = m, "modus" = mode)
  return(my_list)
}

# hitung mean median modus distribusi normal
set.seed(123)
x1 <- rbinom(100,10,0.5)
three.M(x1)
$mean
[1] 4.99

$median
[1] 5

$modus
     v  f
[1,] 6 24
[2,] 5 24

Referensi

Raharjo, Mulianto. (17 Maret 2021). STA561 Pemrograman Statistika: Pemrograman Fungsi & OOP. Retrieved from https://newlms.ipb.ac.id/

Soleh, A.M. (2021). STA561 Pemrograman Statistika: Pemrograman Fungsi R. Retrieved from https://newlms.ipb.ac.id/

Primandari, Arum H. (2018). Membuat Fungsi dalam R. Retrieved from https://rpubs.com/arumprimandari/368914

R - Object Oriented Programming (2020) Retrieved from: here