##### Rozdział 3: Klasyfikacja metodą najbliższych sąsiadów --------------------

## Przykład: klasyfikowanie próbek nowotworów ----
## Etap 2: badanie i przygotowywanie danych ---- 

# importujemy plik CSV
wbcd <- read.csv("wisc_bc_data.csv")

# badamy strukturę ramki danych wbcd
str(wbcd)

# odrzucamy cechę id
wbcd <- wbcd[-1]

# tabela diagnoz
table(wbcd$diagnosis)

# przekształcamy diagnozy w czynnik
wbcd$diagnosis <- factor(wbcd$diagnosis, levels = c("B", "M"),
                         labels = c("Benign", "Malignant"))

# tabela proporcji z bardziej czytelnymi etykietami
round(prop.table(table(wbcd$diagnosis)) * 100, digits = 1)

# podsumowujemy trzy cechy liczbowe
summary(wbcd[c("radius_mean", "area_mean", "smoothness_mean")])

# tworzymy funkcję normalizacji
normalize <- function(x) {
  return ((x - min(x)) / (max(x) - min(x)))
}

# testujemy funkcję normalizacji - wynik powinien być identyczny
normalize(c(1, 2, 3, 4, 5))
normalize(c(10, 20, 30, 40, 50))

# normalizujemy dane wbcd
wbcd_n <- as.data.frame(lapply(wbcd[2:31], normalize))

# upewniamy się, że normalizacja zadziałała
summary(wbcd_n$area_mean)

# tworzymy dane treningowe i testowe
wbcd_train <- wbcd_n[1:469, ]
wbcd_test <- wbcd_n[470:569, ]

# tworzymy etykiety dla danych treningowych i testowych

wbcd_train_labels <- wbcd[1:469, 1]
wbcd_test_labels <- wbcd[470:569, 1]

## Etap 3: trenowanie model na danych ----

# wczytujemy bibliotekę "class"
library(class)

wbcd_test_pred <- knn(train = wbcd_train, test = wbcd_test,
                      cl = wbcd_train_labels, k = 21)

## Etap 4: ewaluacja modelu ----

# wczytujemy bibliotekę "gmodels"
library(gmodels)

# tworzymy tabelę krzyżową "przewidziane a rzeczywiste"
CrossTable(x = wbcd_test_labels, y = wbcd_test_pred,
           prop.chisq = FALSE)

## Etap 5: poprawianie działania modelu ----

# używamy funkcji scale(), aby poddać ramkę danych standaryzacji Z
wbcd_z <- as.data.frame(scale(wbcd[-1]))

# upewniamy się, że przekształcenie przebiegło poprawnie
summary(wbcd_z$area_mean)

# tworzymy treningowy i testowy zbiór danych
wbcd_train <- wbcd_z[1:469, ]
wbcd_test <- wbcd_z[470:569, ]

# ponownie klasyfikujemy przypadki testowe
wbcd_test_pred <- knn(train = wbcd_train, test = wbcd_test,
                      cl = wbcd_train_labels, k = 21)

# tworzymy tabelę krzyżową "przewidziane a rzeczywiste"
CrossTable(x = wbcd_test_labels, y = wbcd_test_pred,
           prop.chisq = FALSE)

# wypróbowujemy kilka różnych wartości k
wbcd_train <- wbcd_n[1:469, ]
wbcd_test <- wbcd_n[470:569, ]

k_values <- c(1, 5, 11, 15, 21, 27)

# pętla for do testowania wszystkich wartości k w wektorze k_values
for (k_val in k_values) {
  wbcd_test_pred <- knn(train = wbcd_train,
                        test = wbcd_test,
                        cl = wbcd_train_labels,
                        k = k_val)
  CrossTable(x = wbcd_test_labels,
             y = wbcd_test_pred,
             prop.chisq = FALSE)
}
