U ovom postu, pokazaćemo na jednostavnom primeru primenu rekurzivne funkcije. Problem koji želimo da rešimo je sledeći. Imamo matricu dimenzija N x M. To može na primer biti dvodimenzionalna tabela kontingencije. Kolone koje imaju srednju vrednost manju od zadate vrednosti potrebno je sabrati sa susednom kolonom. U slučaju kada postoje dve susedne kolone bira se ona koja ima manju srednju vrednost. Ovakva vrsta problema se može elegantno rešiti primenom rekurzivnih funkcija.
U primeru ćemo koristiti matricu 5 x 8. Generisaćemo 40 celih brojeva u intervalu od 1 do 9.
# Definišemo početnu vrednost generatora slučajnih brojeva set.seed(155) # Kreiramo matricu 5 x 8 mat <- matrix(ceiling(runif(40, 0, 9)), 5, 8) # Imenujemo kolone i redove novokreirane matrice colnames(mat) <- LETTERS[1:8] rownames(mat) <- letters[1:5] # Štampanje kreirane matrice knitr::kable(mat) %>% kable_styling(full_width = F)
Želimo da pripojimo drugim kolonama sve kolone koje imaju srednju vrednost manju od 5. U ovom primeru, kolone sa srednjim vrednostima manjim od 5 su C, E i F. Kolonu C je potrebno pripojiti koloni B (srednja vrednost B < srednja vrednost D), a kolonu E je potrebno sabrati sa kolonom F (srednja vrednost F < srednja vrednost D). Kako je kolona F pripojena koloni E, nju nije potrebno spajati sa drugim kolonama.
# Računanje srednjih vrednosti kolona matrice col_means <- round(colMeans(mat), 1) # Štampanje srednjih vrednosti kolona matrice knitr::kable(t(as.matrix(col_mens))) %>% kable_styling(full_width = F)
Prvo ćemo kreirati pomoćnu funkciju merge_columns()
koja spaja dve kolone po gore opisanom algoritmu. Implementacija funkcije se nalazi u dodatku na kraju posta.
Rekurzivna funkcija će pozivati samu sebe dok god postoji kolona sa srednjom vrednošću manjom od 5.
collapsing_matrix <- function(mat, threshold) { col_means <- colMeans(mat) ind <- which(col_means < threshold)[1] if (!is.na(ind)) { mat <- merge_columns(mat, ind) # funkcija poziva samu sebe ako postoji kolona # sa srednjom vrednoscu manjom od zadatog praga collapsing_matrix(mat, threshold) } else { return(mat) } }
Primenom funkcije na gore definisanu matricu, dobijamo očekivani rezultat.
# Generisanje matrice prema zadatom kriterijumu new_mat <- collapsing_matrix(mat, threshold = 5) # Štampanje kreirane matrice knitr::kable(new_mat) %>% kable_styling(full_width = F)
Funkcija se može primeniti na matricu bilo kojih dimenzija.
Srednje vrednosti kolona matrice.
Rezultat posle poziva funkcije collapsing_matrix()
za vrednost praga 5.
Uz manje izmene u R kodu može se rekurzivna funkcija iz dodatka napisati tako da se umesto srednje vrednosti može koristiti neki drugi kriterijum, na primer, minimalna vrednost.
Dodatak
merge_columns <- function(mat, ind) { n_cols <- ncol(mat) col_ind <- 1:n_cols col_names <- colnames(mat) col_means <- colMeans(mat) if (ind == 1) { start <- NULL i <- 0 j <- 1 end <- setdiff(col_ind, c(1,2)) } else { if (ind == ncol(mat)) { start <- setdiff(col_ind, c(n_cols-1, n_cols)) i <- -1 j <- 0 end <- NULL } else { mean_before <- col_means[ind-1] mean_after <- col_means[ind+1] if (mean_before <= mean_after) { start <- col_ind[col_ind < ind-1] i <- -1 j <- 0 end <- col_ind[col_ind > ind] } else { start <- col_ind[col_ind < ind] i <- 0 j <- 1 end <- col_ind[col_ind > ind+1] } } } mat <- cbind(mat[,start], c(mat[,ind+i] + mat[,ind+j]), mat[,end]) new_col_names <- c(col_names[start], paste(col_names[ind+i], col_names[ind+j], sep = ","), col_names[end]) colnames(mat) <- new_col_names return(mat) }

Master Statistike. Razvija R pakete i Shiny aplikacije.