Статистички софтвер 1: Функције у R-у

Стефан Малбашић, Математички факултет, Универзитет у Београду

Дефинисање функција

У програмском језику R функција се дефинише на следећи начин: function_name <- function(arg1, arg2, arg3, ...) {function body}.

Функција се позива са function_name(arg1, arg2, ...) са конкретним аргументима.

function_name <- function(parameters){
  function body 
}

Ако желимо да видимо код постојећих функција, куцамо само име функције без аргумената.

factorial
## function (x) 
## gamma(x + 1)
## <bytecode: 0x0000021688a18780>
## <environment: namespace:base>
  • Функција која рачуна биномни коефицијент \(\binom{n}{k}\).
binomni <- function(n, k){
  koef <- factorial(n) / (factorial(k) * factorial(n-k))
  return(koef)
}

binomni(4, 2)
## [1] 6

Када позивамо функцију, аргументе наводимо истим редом као у дефиницији функције, осим ако их наведемо по имену. Тада је редослед произвољан.

binomni(k = 2, n = 4)
## [1] 6
binomni(n = 4, k = 2)
## [1] 6
binomni(2, 4)

Warning in gamma(x + 1) : NaNs produced
  • Функција која спаја два вектора као колоне матрице.
spoji <- function(v1, v2){
  return (cbind(v1, v2))
}

spoji(c(0, 1, 2, 3), seq(0, 3, 1))
##      v1 v2
## [1,]  0  0
## [2,]  1  1
## [3,]  2  2
## [4,]  3  3

Функција не мора да садржи RETURN наредбу, може само да се направе неке измене које важе само у телу функције.

  • Функција која рачуна квадрат броја
SQ <- function(x){
  x <- x^2
}

a <- 3

print(SQ(a))
## [1] 9
a # nije se izmenilo van funkcije
## [1] 3
  • Функција која рачуна површину круга.
circumference  <- function(r){
    2*pi*r
}
print(circumference (2))
## [1] 12.56637
  • Задавање вредности аргументима функције.
my_faculty <- function(faculty = "Математички факултет") {
  paste("Марко иде на", faculty)
}

my_faculty("Економски факултет")
## [1] "Марко иде на Економски факултет"
my_faculty() # vraca podrazumevanu vrednost
## [1] "Марко иде на Математички факултет"
  • Функција која црта два графика \(y(x)\) и \(x(y)\) у произвољној боји.
# colors() - ispisuje sve postojece boje u R-u
nacrtaj <- function(v1, v2){
  par(mfrow = c(1,2))
  plot(v1, v2, col="turquoise")
  plot(v2, v1, col="turquoise")
  par(mfrow = c(1,1))
}

nacrtaj(sample(1:1000,100), sample(1:1000,100))

  • Функција која има више повратних вредности.
mean_median <- function(vector){
    mean <- mean(vector)
    median <- median(vector)
    return(c(mean, median))
}
print(mean_median(c(1, 1, 1, 2, 3)))
## [1] 1.6 1.0
Rectangle = function(length, width){
  area = length * width
  perimeter = 2 * (length + width)
   
  result = list("Area" = area, "Perimeter" = perimeter)
  return(result)
}
 
resultList = Rectangle(2, 3)
print(resultList["Area"])
## $Area
## [1] 6
print(resultList["Perimeter"])
## $Perimeter
## [1] 10
  • Позивање једне функције у телу друге функције.
radius_from_diameter <- function(d){
    d/2
}

circumference <- function(r){
    2*pi*r
}

print(circumference(radius_from_diameter(4)))
## [1] 12.56637
sum_circle_ares <- function(r1, r2, r3){
    circle_area <- function(r){
        pi*r^2
    }
    circle_area(r1) + circle_area(r2) + circle_area(r3)
}

print(sum_circle_ares(1, 2, 3))
## [1] 43.9823

Приметимо да је функција circle_area дефинисана у телу функције sum_circle_ares и видљива је само локално у тој функцији.

print(circle_area(10))

Error in circle_area(10): could not find function "circle_area"
Traceback:

1. print(circle_area(10))
  • Могуће је дефинисати и рекурзивне функције, тј. функције које позивају саму себе.
tri_recursion <- function(k) {
  if (k > 0) {
    result <- k + tri_recursion(k - 1)
    print(result)
  } else {
    result = 0
    return(result)
  }
}

tri_recursion(6)
## [1] 1
## [1] 3
## [1] 6
## [1] 10
## [1] 15
## [1] 21
  • Глобално и локално дефинисане променљиве и функције.
txt <- "awesome"
my_function <- function() {
  paste("R is", txt)
}

my_function()
## [1] "R is awesome"
txt <- "global variable"

my_function <- function() {
  txt = "fantastic"
  paste("R is", txt)
}

my_function()
## [1] "R is fantastic"
txt 
## [1] "global variable"

IF наредбе и FOR, WHILE, REPEAT петље

Било која целина или блок наредби може се издвојити заградама \(\{ \}\). Ако у конзоли пређемо у нови ред, а траје блок, појавиће се + да то означи.

IF наредба

  • Постоје два основна типа логичог гранања:
  1. if (expr_1) expr_2
  2. if (expr_1) expr_2 else expr_3 при чему израз expr_1 мора имати логичку вредност.
x <- 5
if(x > 0){
  print("Positive number")
}
## [1] "Positive number"
x <- -5
if(x >= 0){
  print("Non-negative number")
} else {
  print("Negative number")
}
## [1] "Negative number"
  • Претходно је могуће записати компактно у једној линији. Наредбе могу да буду и сложене, само би се онда ограничиле са \(\{\}\).
if(x >= 0) print("Non-negative number") else print("Negative number")
x <- -5
y <- if(x > 0) 5 else 6
y
## [1] 6

IF ELSE лествице

x <- 0

if (x < 0) {
  print("Negative number")
} else if (x > 0) {
  print("Positive number")
} else
  print("Zero")
## [1] "Zero"
x <- 20

if (x > 0) {

  if (x %% 2 == 0) {
    print("x је позитиван паран број")
  } else {
    print("x је позитиван непаран број")
  }

} else {

  if (x %% 2 == 0) {
    print("x је негативан паран број")
  } else {
    print("x је негативан непаран број")
  }
}
## [1] "x је позитиван паран број"

IFELSE наредба

  • Функција ifelse представља векторску репрезентацију if else гранања: ifelse(vector_with_condition, value_if_TRUE, value_if_FALSE).
ifelse(seq(1, 5) < 5, TRUE, FALSE)
## [1]  TRUE  TRUE  TRUE  TRUE FALSE
x <- c("male", "male", "female", "male", "female")
y <- c(10, 14, 80, 56, 27)

ifelse (x == "male", ifelse(y > 18, "Adult male", "Underage male"),
        ifelse(y > 18, "Adult female", "Underage female"))
## [1] "Underage male" "Underage male" "Adult female"  "Adult male"   
## [5] "Adult female"
ifelse (y > 30 | y <= 10, 1, 0) 
## [1] 1 0 1 1 0

FOR петља

for(i in start:finish) {statement}

for (i in 1:10) print(i)
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
  • Пролазак бројача кроз листу, а не вектор.
colors <- c("green", "blue", "red")
for (color in colors){
   print(paste0("Color: ", color))
}
## [1] "Color: green"
## [1] "Color: blue"
## [1] "Color: red"
  • Цртање графика помоћу for петље.
x <- seq(0, 1, 0.05)
plot(x, x, type = "l")

for(i in 2:8){
  lines(x, x^i)
}

  • Двострука for петља.
a <- matrix(nrow = 5, ncol = 4) # Prazna matrica

for(i in 1:5)
  for(j in 1:4)
    a[i,j] <- i+j
a
##      [,1] [,2] [,3] [,4]
## [1,]    2    3    4    5
## [2,]    3    4    5    6
## [3,]    4    5    6    7
## [4,]    5    6    7    8
## [5,]    6    7    8    9
  • Пример оцењивања расподеле узорачке средњих вредности на основу хистограма.
set.seed(1)  # Setting a seed for reproducibility
rep <- 50000 # Number of repetitions
n <- 2       # Number of points

Mean <- numeric(rep)

for (i in 1:rep) {
    x <- runif(n)
    Mean[i] <- mean(x)
}


hist(Mean, breaks = 40, main = paste("n = ", n))

Next и break наредбе

for (i in 1:15) {

  if (i == 3) {
        next  
    }

    if (i == 6) {
        break   
    }

  print(i)
}
## [1] 1
## [1] 2
## [1] 4
## [1] 5

WHILE петља

while (logic_condition) {statement}

  • Одређивање факторијела задатог броја.
factorialR <- function(x) {
  
  if (x == 0) {
    res <- 1
  } else {
  
  res <- x
  
    while(x > 1){
      res <- (x - 1) * res
      x <- x - 1
    }
  }
  return(res)
}

factorialR(8)
## [1] 40320
factorialR(0)
## [1] 1
  • Одређивање првог природног броја чији квадрат је већи од задате границе.
n <- 0
square <- 0

while(square <= 4000) {
    n <- n + 1
    square <- n ^ 2
}

REPEAT наредба

Садржи наредбе које се извршавају, као и услов за излазак из петље, иначе имамо бесконачну петљу!

repeat{statement if (logic_condition) break}

y <- 0
repeat{
  y <- y+1
  if(y >= 5) break
}
y
## [1] 5
  • Функција која из базе sleep брише елементе код којих је параметар extra мањи од задатог броја.
data(sleep)
sleep
##    extra group ID
## 1    0.7     1  1
## 2   -1.6     1  2
## 3   -0.2     1  3
## 4   -1.2     1  4
## 5   -0.1     1  5
## 6    3.4     1  6
## 7    3.7     1  7
## 8    0.8     1  8
## 9    0.0     1  9
## 10   2.0     1 10
## 11   1.9     2  1
## 12   0.8     2  2
## 13   1.1     2  3
## 14   0.1     2  4
## 15  -0.1     2  5
## 16   4.4     2  6
## 17   5.5     2  7
## 18   1.6     2  8
## 19   4.6     2  9
## 20   3.4     2 10
brisi <- function(x){
  return (sleep[sleep$extra >= x,])
}

brisi(2.1)
##    extra group ID
## 6    3.4     1  6
## 7    3.7     1  7
## 16   4.4     2  6
## 17   5.5     2  7
## 19   4.6     2  9
## 20   3.4     2 10

Ако хоћемо да нам функција врати више ствари, на пример, хоћемо као претходно, али и да враћа број обрисаних елемената. Потребно је да функција врати две ставке различитог типа, па морамо направити листу.

brisi1 <- function(x){
  return (list(sleep[sleep$extra >= x,], nrow(sleep[sleep$extra < x,])))
}

brisi1(2.1)
## [[1]]
##    extra group ID
## 6    3.4     1  6
## 7    3.7     1  7
## 16   4.4     2  6
## 17   5.5     2  7
## 19   4.6     2  9
## 20   3.4     2 10
## 
## [[2]]
## [1] 14

*apply функције

Фамилија функција *apply са функцијама apply, sapply и lapply чини основу функционалног програмирања у R-у. У пиитању су функције које служе за пресликавање елемената (вектора/матрица/листи) у нове елементе применом једне исте функције на сваки елемент.

apply(X,       # Array, matrix or data frame
      MARGIN,  # 1: rows, 2: columns, c(1, 2): rows and columns
      FUN,     # Function to be applied
      ...)     # Additional arguments to FUN

Функција sapply

Позив функције: sapply(v, f), где је v вектор, матрица или листа, а f функција коју треба применити на сваки елемент од v.

sapply(X,   # Vector, list or expression object
       FUN, # Function to be applied
       ..., # Additional arguments to be passed to FUN
       simplify = TRUE,  # If FALSE returns a list. If "array" returns an array if possible 
       USE.NAMES = TRUE) # If TRUE and if X is a character vector, uses the names of X

Дакле, sapply примењује дату функцију на сваки елемент датог вектра/матрице/листе и враћа резултујући вектор. Напоменимо да увек покушава да врати вектор, а уколико то није могуће враћа листу.

  • Кореновање сваког члана вектора.
sapply(1:4, sqrt)
## [1] 1.000000 1.414214 1.732051 2.000000
sapply(1:4, function(i) sqrt(i)) 
## [1] 1.000000 1.414214 1.732051 2.000000
my_fun <- function(i) {
    sqrt(i)
}

sapply(1:4, my_fun) 
## [1] 1.000000 1.414214 1.732051 2.000000

Аргумент функције не мора бити вектор, може бити и листа, али као излазну вредност опет добијамо вектор.

List <- list(A = 1:5, B = 6:20, C = 1)
sapply(List, length)
##  A  B  C 
##  5 15  1
  • За листу матрица желимо да одредимо суму свих вредности у матрици.
matrix_list <- list(diag(5), diag(7), matrix(1:10, nrow = 2))
matrix_sums <- sapply(matrix_list, sum)
matrix_sums
## [1]  5  7 55

Ово је исто што и

c(sum(diag(5)), sum(diag(7)), sum(matrix(1:10, nrow=2)))
## [1]  5  7 55

Уколико се примењује вишедимензиона функција, функција sapply може да врати и матрицу.

sapply(1:5, function(k) c(k, k^2))
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    2    3    4    5
## [2,]    1    4    9   16   25

Свака колона је један резултат примењене функције. Прва врста је \(k\), а друга је \(k^2\).

  • Функцију sapply можемо применити и на базе података.
data <- data.frame(a = c(1, 3, 7, 12, 9),
                   b = c(4, 4, 6, 7, 8),
                   c = c(14, 15, 11, 10, 6))
data
##    a b  c
## 1  1 4 14
## 2  3 4 15
## 3  7 6 11
## 4 12 7 10
## 5  9 8  6
sapply(data, mean)
##    a    b    c 
##  6.4  5.8 11.2
sapply(data, function(d) d*2)
##       a  b  c
## [1,]  2  8 28
## [2,]  6  8 30
## [3,] 14 12 22
## [4,] 24 14 20
## [5,] 18 16 12
  • Можемо користити функцију sapply за цртање графика.
plot(rnorm(10), ylim = c(-6, 6))

nlines <- 5

invisible(sapply(1:nlines, function(i) lines(-i:i, col = i, lwd = 3)))

Функција lapply

Користи се на исти начин као и функција sapply, само што као резултат враћа листу, а не вектор. Дакле, када не очекујемо да резултат буде увек истог типа и димензије, већ желимо да излаз буде листа, користимо функцију lapply.

lapply(X,   # List or vector
       FUN, # Function to be applied
       ...) # Additional arguments to be passed to FUN
  • Примена на елементе вектора.
b <- c(12, 18, 6)
lapply(b, sqrt)
## [[1]]
## [1] 3.464102
## 
## [[2]]
## [1] 4.242641
## 
## [[3]]
## [1] 2.44949
  • За неки вектор направимо листу дијагоналних матрица одговарајуће димензије.
dimensions <- c(1, 3, 5)
lapply(dimensions, function(d) diag(d))
## [[1]]
##      [,1]
## [1,]    1
## 
## [[2]]
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    1    0
## [3,]    0    0    1
## 
## [[3]]
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    0    0    0    0
## [2,]    0    1    0    0    0
## [3,]    0    0    1    0    0
## [4,]    0    0    0    1    0
## [5,]    0    0    0    0    1

Исти резултат преко for петље:

result <- list()
i <- 1
for (d in dimensions) {
  result[[i]] <- diag(d)
  i <- i + 1
}
result
## [[1]]
##      [,1]
## [1,]    1
## 
## [[2]]
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    1    0
## [3,]    0    0    1
## 
## [[3]]
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    0    0    0    0
## [2,]    0    1    0    0    0
## [3,]    0    0    1    0    0
## [4,]    0    0    0    1    0
## [5,]    0    0    0    0    1
  • Функција lapply са додатним аргументима.
c <- list(A = c(56, 12, 57, 24), B = c(89, 12, 64, 18, 65, 76))

lapply(c,                           # List
       quantile,                    # Applied function
       probs = c(0.25, 0.5, 0.75))  # Additional argument of the quantile function
## $A
##   25%   50%   75% 
## 21.00 40.00 56.25 
## 
## $B
##   25%   50%   75% 
## 29.50 64.50 73.25

lapply или sapply

lapply(c(4, 9, 16), FUN = sqrt)
## [[1]]
## [1] 2
## 
## [[2]]
## [1] 3
## 
## [[3]]
## [1] 4
sapply(c(4, 9, 16), FUN = sqrt)
## [1] 2 3 4
sapply(c(4, 9, 16), FUN = sqrt, simplify = FALSE)
## [[1]]
## [1] 2
## 
## [[2]]
## [1] 3
## 
## [[3]]
## [1] 4
as.list(sapply(c(4, 9, 16), sqrt)) 
## [[1]]
## [1] 2
## 
## [[2]]
## [1] 3
## 
## [[3]]
## [1] 4
unlist(lapply(c(4, 9, 16), sqrt)) 
## [1] 2 3 4
simplify2array(lapply(c(4, 9, 16), sqrt)) 
## [1] 2 3 4

Функција apply

Функција apply се користи када имамо вишедимензиони улаз (нпр. матрица или база податакa), а желимо да применимо неку функцију по колонама или по врстама.

Функција се позива са apply(mat, dim, f), где је mat матрица или база података, dim је димензија по којој примењујемо функцију (1 је за врста, а 2 за колоне), a f je функција коју примењујемо на сваку врсту или колону.

apply(X,       # Array, matrix or data frame
      MARGIN,  # 1: rows, 2: columns, c(1, 2): rows and columns
      FUN,     # Function to be applied
      ...)     # Additional arguments to FUN
  • Збир елемената у свакој колони неке матрице.
mat <- matrix(1:12, ncol = 4)
mat
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12
apply(mat, 2, sum)
## [1]  6 15 24 33

Ово је еквивалентно са

colSums(mat)
## [1]  6 15 24 33
  • Ако желимо просек по врстама
apply(mat, 1, mean)
## [1] 5.5 6.5 7.5

Што је еквивалентно са

rowMeans(mat)
## [1] 5.5 6.5 7.5

Резултат не мора бити вектор, можемо вратити резултат позива функције summary на сваку колону базе и добијамо матрицу.

head(cars) 
##   speed dist
## 1     4    2
## 2     4   10
## 3     7    4
## 4     7   22
## 5     8   16
## 6     9   10
apply(cars, 2, summary)
##         speed   dist
## Min.      4.0   2.00
## 1st Qu.  12.0  26.00
## Median   15.0  36.00
## Mean     15.4  42.98
## 3rd Qu.  19.0  56.00
## Max.     25.0 120.00
  • Примена функције на сваки елемент базе.
(m <- matrix(c(seq(from = -98, to = 100, by = 2)), nrow = 10, ncol = 10))
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
##  [1,]  -98  -78  -58  -38  -18    2   22   42   62    82
##  [2,]  -96  -76  -56  -36  -16    4   24   44   64    84
##  [3,]  -94  -74  -54  -34  -14    6   26   46   66    86
##  [4,]  -92  -72  -52  -32  -12    8   28   48   68    88
##  [5,]  -90  -70  -50  -30  -10   10   30   50   70    90
##  [6,]  -88  -68  -48  -28   -8   12   32   52   72    92
##  [7,]  -86  -66  -46  -26   -6   14   34   54   74    94
##  [8,]  -84  -64  -44  -24   -4   16   36   56   76    96
##  [9,]  -82  -62  -42  -22   -2   18   38   58   78    98
## [10,]  -80  -60  -40  -20    0   20   40   60   80   100
apply(m, c(1, 2), function(x) x%%10) 
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
##  [1,]    2    2    2    2    2    2    2    2    2     2
##  [2,]    4    4    4    4    4    4    4    4    4     4
##  [3,]    6    6    6    6    6    6    6    6    6     6
##  [4,]    8    8    8    8    8    8    8    8    8     8
##  [5,]    0    0    0    0    0    0    0    0    0     0
##  [6,]    2    2    2    2    2    2    2    2    2     2
##  [7,]    4    4    4    4    4    4    4    4    4     4
##  [8,]    6    6    6    6    6    6    6    6    6     6
##  [9,]    8    8    8    8    8    8    8    8    8     8
## [10,]    0    0    0    0    0    0    0    0    0     0
  • Стандардизација колона базе података

Извршимо стандардизацију колоне базе података применом функције apply. Применићемо следећу трансформацију \(\frac{X-m}{\sigma}\) да бисмо добили случајну величину са очекивањем 0 и дисперзијом 1.

scaled_cars <- apply(cars, 2, function(x){
  (x - mean(x)) / sd(x)
})
head(scaled_cars)
##          speed       dist
## [1,] -2.155969 -1.5902596
## [2,] -2.155969 -1.2798136
## [3,] -1.588609 -1.5126481
## [4,] -1.588609 -0.8141446
## [5,] -1.399489 -1.0469791
## [6,] -1.210369 -1.2798136

Израчунајмо просек и дисперзију оригиналних и скалираних података.

round(apply(cars, 2, function(x) c(mean(x), var(x))), 5)
##         speed     dist
## [1,] 15.40000  42.9800
## [2,] 27.95918 664.0608
round(apply(scaled_cars, 2, function(x) c(mean(x), var(x))), 5)
##      speed dist
## [1,]     0    0
## [2,]     1    1

Дакле, очекивано, скалирани подаци су такви да су просек и дисперзија сваке колоне редом 0 и 1.

Задатак за вежбу

  1. Имплементирати функцију Remove која из базе iris брише елементе код којих је параметар Sepal.Length мањи од средње вредности и параметар Sepal.Width мањи од медијане вредности у посматраној колони.
Remove <- function(){
  Mean <- mean(iris$Sepal.Length)
  Median <- median(iris$Sepal.Width)
  
  condition <- iris$Sepal.Length >= Mean & iris$Sepal.Width >= Median
  
  return(iris[condition,])
}

Remove()
##     Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 51           7.0         3.2          4.7         1.4 versicolor
## 52           6.4         3.2          4.5         1.5 versicolor
## 53           6.9         3.1          4.9         1.5 versicolor
## 57           6.3         3.3          4.7         1.6 versicolor
## 62           5.9         3.0          4.2         1.5 versicolor
## 66           6.7         3.1          4.4         1.4 versicolor
## 71           5.9         3.2          4.8         1.8 versicolor
## 76           6.6         3.0          4.4         1.4 versicolor
## 78           6.7         3.0          5.0         1.7 versicolor
## 86           6.0         3.4          4.5         1.6 versicolor
## 87           6.7         3.1          4.7         1.5 versicolor
## 92           6.1         3.0          4.6         1.4 versicolor
## 101          6.3         3.3          6.0         2.5  virginica
## 103          7.1         3.0          5.9         2.1  virginica
## 105          6.5         3.0          5.8         2.2  virginica
## 106          7.6         3.0          6.6         2.1  virginica
## 110          7.2         3.6          6.1         2.5  virginica
## 111          6.5         3.2          5.1         2.0  virginica
## 113          6.8         3.0          5.5         2.1  virginica
## 116          6.4         3.2          5.3         2.3  virginica
## 117          6.5         3.0          5.5         1.8  virginica
## 118          7.7         3.8          6.7         2.2  virginica
## 121          6.9         3.2          5.7         2.3  virginica
## 125          6.7         3.3          5.7         2.1  virginica
## 126          7.2         3.2          6.0         1.8  virginica
## 128          6.1         3.0          4.9         1.8  virginica
## 130          7.2         3.0          5.8         1.6  virginica
## 132          7.9         3.8          6.4         2.0  virginica
## 136          7.7         3.0          6.1         2.3  virginica
## 137          6.3         3.4          5.6         2.4  virginica
## 138          6.4         3.1          5.5         1.8  virginica
## 139          6.0         3.0          4.8         1.8  virginica
## 140          6.9         3.1          5.4         2.1  virginica
## 141          6.7         3.1          5.6         2.4  virginica
## 142          6.9         3.1          5.1         2.3  virginica
## 144          6.8         3.2          5.9         2.3  virginica
## 145          6.7         3.3          5.7         2.5  virginica
## 146          6.7         3.0          5.2         2.3  virginica
## 148          6.5         3.0          5.2         2.0  virginica
## 149          6.2         3.4          5.4         2.3  virginica
## 150          5.9         3.0          5.1         1.8  virginica
  1. Одредити средњу вредност и стандардну девијацију параметара Petal.Length и Petal.Width, а затим стандардизовати (нумеричке) колоне базе iris.
apply(iris[c(3,4)], 2, function(x) c("Mean" = mean(x), "SD" = sd(x)))
##      Petal.Length Petal.Width
## Mean     3.758000   1.1993333
## SD       1.765298   0.7622377
scaled_iris <- apply(iris[-5], 2, function(x){
  (x-mean(x))/sd(x)
})
head(scaled_iris)
##      Sepal.Length Sepal.Width Petal.Length Petal.Width
## [1,]   -0.8976739  1.01560199    -1.335752   -1.311052
## [2,]   -1.1392005 -0.13153881    -1.335752   -1.311052
## [3,]   -1.3807271  0.32731751    -1.392399   -1.311052
## [4,]   -1.5014904  0.09788935    -1.279104   -1.311052
## [5,]   -1.0184372  1.24503015    -1.335752   -1.311052
## [6,]   -0.5353840  1.93331463    -1.165809   -1.048667
  1. Одредити 25%, 50% и 75% квартил за сваку (нумеричку) колону базе iris.
apply(iris[-5], 2, quantile, probs = c(0.25, 0.5, 0.75))
##     Sepal.Length Sepal.Width Petal.Length Petal.Width
## 25%          5.1         2.8         1.60         0.3
## 50%          5.8         3.0         4.35         1.3
## 75%          6.4         3.3         5.10         1.8