Wczytanie danych oraz pakietów
# Wczytanie kopii df, żeby nie ściągać znowu z chmury przy testowaniu
df <- df_copy
# Dodanie zmienny pochodnych
# Wcześniej koszt_propon i koszt_konkur służyły tylko do przekształceń -> teraz je uwzględniamy
df$bardzo_wysoka_kwota <- as.integer(df$kwota_kredytu > quantile(df$kwota_kredytu, 0.9, na.rm = TRUE))
df$roznica_oproc <- df$oproc_propon - df$oproc_konkur
df$fico_vs_oproc <- df$scoring_FICO * df$roznica_oproc
df$koszt_propon <- df$kwota_kredytu * (df$oproc_propon / 100) * (df$okres_kredytu / 12) # potrzebne do przekształceń
df$koszt_konkur <- df$kwota_kredytu * (df$oproc_konkur / 100) * (df$okres_kredytu / 12) # potrzebne do przekształceń
df$roznica_kosztu <- df$koszt_propon - df$koszt_konkur
df$ryzyko_vs_oproc <- df$grupa_ryzyka * df$roznica_oproc
df$stopien_refinansowania <- as.integer(df$oproc_refin > 0)
df$stosunek_refin_konkur <- df$oproc_refin / ifelse(df$oproc_konkur == 0, 0.0001, df$oproc_konkur)
df$umowa_N_roznica_oproc <- as.integer(df$typ_umowy == "N") * df$roznica_oproc
df$wartosc_refinansowania <- (df$oproc_refin / 100) * df$kwota_kredytu
df$wysoka_kwota <- as.integer(df$kwota_kredytu > quantile(df$kwota_kredytu, 0.75, na.rm = TRUE))
df$kwota_na_miesiac <- df$kwota_kredytu / df$okres_kredytu
# Usunięcie zmiennych służących do przekształceń
df <- df %>% select(-koszt_propon, -koszt_konkur)
# Sprawdzenie braków
sum(is.na(df))
## [1] 0
# Zdefiniowanie bad
df$bad <- ifelse(df$akceptacja_klienta == 1, 0, 1)
df <- df %>% select(-akceptacja_klienta)
# NOWE ZMIENNE
df$fico_znormalizowana_kwota <- log1p(df$kwota_kredytu) / (df$scoring_FICO + 1)
df$skorygowana_atrakcyjnosc <- (df$oproc_konkur - df$oproc_propon) - df$koszt_pieniadza
df$ryzyko_vs_kwota <- df$grupa_ryzyka * df$kwota_kredytu
df$wskaźnik_refin_zysku <- ifelse(df$typ_umowy == "R", (df$oproc_refin - df$oproc_konkur) * df$kwota_kredytu,0)
df$presja_ratalna <- df$kwota_kredytu / df$scoring_FICO * log1p(df$okres_kredytu)
df$obciazenie_vs_fico <- (df$kwota_kredytu / df$okres_kredytu) / df$scoring_FICO
df$atrakcyjnosc_oferty <- (df$oproc_konkur - df$oproc_propon) / df$oproc_konkur
#df$kwota_kredytu_ln <- log(df$kwota_kredytu)
#df$kwota_kredytu_pół <- df$kwota_kredytu / 2
#df$kwota_na_fico <- df$kwota_kredytu / df$scoring_FICO
#te 3 zmienne pogorszyły AUC,Gini, pomimo wysokiego IV
# Sprawdzenie liczby unikalnych wartości w każdej kolumnie
sapply(df, function(x) length(unique(x)))
## grupa_ryzyka kod_partnera typ_umowy
## 4 3 3
## scoring_FICO okres_kredytu kwota_kredytu
## 246 5 14344
## oproc_refin oproc_konkur koszt_pieniadza
## 688 37 71
## oproc_propon bardzo_wysoka_kwota roznica_oproc
## 468 2 1043
## fico_vs_oproc roznica_kosztu ryzyko_vs_oproc
## 11750 20476 1423
## stopien_refinansowania stosunek_refin_konkur umowa_N_roznica_oproc
## 2 2756 217
## wartosc_refinansowania wysoka_kwota kwota_na_miesiac
## 10057 2 15575
## bad fico_znormalizowana_kwota skorygowana_atrakcyjnosc
## 2 27776 4247
## ryzyko_vs_kwota wskaźnik_refin_zysku presja_ratalna
## 15652 10919 31979
## obciazenie_vs_fico atrakcyjnosc_oferty
## 29967 1713
binned <- c("grupa_ryzyka", "kod_partnera","typ_umowy", "bardzo_wysoka_kwota", "stopien_refinansowania", "wysoka_kwota", "okres_kredytu")
breaks_list <- lapply(binned, function(x) NULL)
names(breaks_list) <- binned
breaks_list <- list(
grupa_ryzyka = c(1, 2, 3, 4),
kod_partnera = c(1, 2, 3),
typ_umowy = c("R", "N", "U"),
bardzo_wysoka_kwota = c(0, 1),
stopien_refinansowania = c(0, 1),
wysoka_kwota = c(0, 1),
okres_kredytu = c(36,48,60,66,72)
)
# Kubełkowanie zmiennych metodą "tree"
#bins <- woebin(df, "bad", method = "tree", min_perc_fine_bin = 0.05, breaks_list=breaks_list)
# Kubełkowanie zmiennych metodą "chimerge"
bins <- woebin(df, "bad", method = "chimerge", min_perc_fine_bin = 0.05, breaks_list=breaks_list, bin_num_limit = 8)
## ℹ Creating woe binning ...
## ℹ The option bin_close_right was set to FALSE.
## Warning in check_breaks_list(breaks_list, xs): There are 21 x variables that
## are not specified in breaks_list, and instead are using optimal binning.
## ✔ Binning on 40000 rows and 29 columns in 00:00:06
df_woe <-woebin_ply(df, bins)
## ℹ Converting into woe values ...
## ✔ Woe transformating on 40000 rows and 28 columns in 00:00:02
# Wyznaczenie IV
iv_table <- iv(df_woe, y = "bad") %>%
select(variable, info_value)
# Liczba unikalnych wartości (binów) po WOE
bin_counts <- df_woe %>%
select(-bad) %>%
summarise(across(everything(), n_distinct)) %>%
pivot_longer(cols = everything(), names_to = "variable", values_to = "bins_count")
iv_table <- left_join(iv_table, bin_counts, by = "variable")
# Wykres
wykres <- ggplot(iv_table, aes(x = reorder(variable, -info_value), y = info_value, fill = as.factor(bins_count))) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Wartości IV dla zmiennych i liczba wyznaczonych bins",
x = "Zmienna",
y = "Information Value (IV)",
fill = "Liczba bins") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(iv_table)
## variable info_value bins_count
## <char> <num> <int>
## 1: kwota_kredytu_woe 0.955631617 8
## 2: obciazenie_vs_fico_woe 0.952142396 8
## 3: ryzyko_vs_kwota_woe 0.939819672 8
## 4: kwota_na_miesiac_woe 0.895670415 8
## 5: presja_ratalna_woe 0.894304149 8
## 6: fico_znormalizowana_kwota_woe 0.556959467 8
## 7: roznica_kosztu_woe 0.469888837 7
## 8: wysoka_kwota_woe 0.412053905 2
## 9: typ_umowy_woe 0.403734127 3
## 10: umowa_N_roznica_oproc_woe 0.339554718 2
## 11: oproc_refin_woe 0.283733390 3
## 12: stosunek_refin_konkur_woe 0.272992843 3
## 13: atrakcyjnosc_oferty_woe 0.247819248 7
## 14: skorygowana_atrakcyjnosc_woe 0.235136052 8
## 15: ryzyko_vs_oproc_woe 0.232398005 8
## 16: fico_vs_oproc_woe 0.231643594 8
## 17: roznica_oproc_woe 0.231053148 8
## 18: wskaźnik_refin_zysku_woe 0.227169472 2
## 19: kod_partnera_woe 0.220400987 3
## 20: stopien_refinansowania_woe 0.220269966 2
## 21: oproc_konkur_woe 0.211246035 8
## 22: bardzo_wysoka_kwota_woe 0.187756872 2
## 23: oproc_propon_woe 0.182445249 8
## 24: grupa_ryzyka_woe 0.175409351 4
## 25: wartosc_refinansowania_woe 0.102656754 2
## 26: scoring_FICO_woe 0.092191078 8
## 27: okres_kredytu_woe 0.070220937 5
## 28: koszt_pieniadza_woe 0.007908854 8
## variable info_value bins_count
print(wykres)

# Filtrowanie zmiennych z IV > 0.1
iv_selected <- subset(iv_table, info_value > 0.1)
# Pobranie nazw zmiennych spełniających kryteria
selected_vars <- as.character(iv_selected$variable)
# Weryfikacja: tylko zmienne, które faktycznie istnieją w danych
selected_vars <- selected_vars[selected_vars %in% colnames(df_woe)]
selected_vars <- c("bad", selected_vars)
# Wybór kolumn
iv_df_woe <- df_woe[, ..selected_vars]
iv_df_woe <- as.data.frame(iv_df_woe)
# Model finalny
reg <- glm(bad ~ ., data = iv_df_woe, family = "binomial")
summary(reg)
##
## Call:
## glm(formula = bad ~ ., family = "binomial", data = iv_df_woe)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.07904 0.01455 74.176 < 2e-16 ***
## kwota_kredytu_woe 0.46048 0.06027 7.640 2.17e-14 ***
## obciazenie_vs_fico_woe 0.04789 0.06285 0.762 0.446008
## ryzyko_vs_kwota_woe 0.42720 0.03979 10.735 < 2e-16 ***
## kwota_na_miesiac_woe 0.52606 0.06646 7.916 2.45e-15 ***
## presja_ratalna_woe 0.17215 0.04702 3.661 0.000251 ***
## fico_znormalizowana_kwota_woe -0.38060 0.03830 -9.938 < 2e-16 ***
## roznica_kosztu_woe -0.25307 0.04697 -5.388 7.12e-08 ***
## wysoka_kwota_woe -0.28915 0.03580 -8.077 6.65e-16 ***
## typ_umowy_woe 0.07796 0.04358 1.789 0.073620 .
## umowa_N_roznica_oproc_woe 0.34149 0.04001 8.536 < 2e-16 ***
## oproc_refin_woe -0.02615 0.09203 -0.284 0.776288
## stosunek_refin_konkur_woe 0.03075 0.08836 0.348 0.727808
## atrakcyjnosc_oferty_woe 0.50233 0.12759 3.937 8.25e-05 ***
## skorygowana_atrakcyjnosc_woe 0.72462 0.11382 6.366 1.94e-10 ***
## ryzyko_vs_oproc_woe 0.52826 0.12606 4.190 2.78e-05 ***
## fico_vs_oproc_woe 0.47234 0.11992 3.939 8.19e-05 ***
## roznica_oproc_woe -0.70999 0.15853 -4.478 7.52e-06 ***
## wskaźnik_refin_zysku_woe 0.41439 0.08054 5.145 2.68e-07 ***
## kod_partnera_woe 1.18343 0.03573 33.121 < 2e-16 ***
## stopien_refinansowania_woe -0.75124 0.06819 -11.016 < 2e-16 ***
## oproc_konkur_woe 0.50787 0.04237 11.986 < 2e-16 ***
## bardzo_wysoka_kwota_woe 0.08380 0.04623 1.813 0.069866 .
## oproc_propon_woe -0.05315 0.07231 -0.735 0.462383
## grupa_ryzyka_woe -0.03616 0.09045 -0.400 0.689300
## wartosc_refinansowania_woe 1.30164 0.06797 19.151 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 45775 on 39999 degrees of freedom
## Residual deviance: 32977 on 39974 degrees of freedom
## AIC: 33029
##
## Number of Fisher Scoring iterations: 6
# Wyznaczenie punktacji
card_final <- scorecard(bins, reg)
# Niezbinowany zbiór z wybranymi zmiennymi
selected_vars_2 <- gsub("_woe", "", selected_vars)
iv_df <- df[, selected_vars_2, with=FALSE]
# Wyznaczenie AUC i Gini
auc <- bigstatsr::AUC(-scorecard_ply(iv_df, card_final)$score, iv_df$bad)
gini <- 2 * auc - 1
summary(scorecard_ply(iv_df, card_final)$score)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -92.0 197.0 270.0 274.7 363.0 599.0
print(paste("AUC:", round(auc, 4)))
## [1] "AUC: 0.8446"
print(paste("GINI:", round(gini, 4)))
## [1] "GINI: 0.6891"
# Zapisanie scorecarda
# Łączymy wszystkie data.table z card_final w jedną tabelę
card_final_df <- rbindlist(card_final,fill=TRUE)
# Wybieramy interesujace nas kolumny i sortujemy
card_final_df <- card_final_df[, .(variable, bin, points, count)]
setorder(card_final_df, variable, bin)
# Tworzymy flextable i scalamy komórki w kolumnie 'variable' posiadające tą samą wartość
ft <- flextable(card_final_df) %>%
merge_v(j = "variable") %>% # <- SCALANIE komórek w kolumnie 'variable'
valign(j = "variable", valign = "top") %>% # estetyka
autofit()
# Eksportujemy do worda
doc <- read_docx()
doc <- body_add_par(doc, "Scorecard Table", style = "heading 1")
doc <- body_add_flextable(doc, ft)
print(doc, target = "scorecard_merged.docx")
# Obliczanie score'u dla każdego rekordu
scored_data <- scorecard_ply(iv_df, card_final)
# Dołączenie kolumny ze scoringiem
iv_data_with_scores_all <- cbind(iv_df, scored_data)
head(iv_data_with_scores_all)
## bad kwota_kredytu obciazenie_vs_fico ryzyko_vs_kwota kwota_na_miesiac
## 1 1 26500.00 0.7864435 53000.00 552.0833
## 2 1 34999.99 0.6760931 69999.98 486.1110
## 3 1 28000.00 0.5818786 28000.00 466.6667
## 4 0 20750.69 0.4783469 20750.69 345.8448
## 5 1 19999.99 0.4025763 59999.97 277.7776
## 6 1 38000.00 0.9300049 38000.00 633.3333
## presja_ratalna fico_znormalizowana_kwota roznica_kosztu wysoka_kwota
## 1 146.9134 0.01448782 16.960000 0
## 2 208.8540 0.01453213 25.199993 1
## 3 143.5218 0.01275217 -6.160000 0
## 4 117.9854 0.01372981 -1.037534 0
## 5 124.3611 0.01433218 17.999991 0
## 6 229.3880 0.01546242 -2.660000 1
## typ_umowy umowa_N_roznica_oproc oproc_refin stosunek_refin_konkur
## 1 R 0.0000 0.0399 0.7995992
## 2 N 0.0120 0.0000 0.0000000
## 3 N -0.0044 0.0000 0.0000000
## 4 R 0.0000 0.0675 1.3527054
## 5 U 0.0000 0.0000 0.0000000
## 6 N -0.0014 0.0000 0.0000000
## atrakcyjnosc_oferty skorygowana_atrakcyjnosc ryzyko_vs_oproc fico_vs_oproc
## 1 -0.32064128 -0.0270 0.0320 11.2320
## 2 -0.25052192 -0.0230 0.0240 8.6280
## 3 0.11027569 -0.0066 -0.0044 -3.5288
## 4 0.02004008 -0.0100 -0.0010 -0.7230
## 5 -0.28355388 -0.0260 0.0450 10.3500
## 6 0.03508772 -0.0096 -0.0014 -0.9534
## roznica_oproc wskaźnik_refin_zysku kod_partnera stopien_refinansowania
## 1 0.0160 -265.0000 2 1
## 2 0.0120 0.0000 2 0
## 3 -0.0044 0.0000 3 0
## 4 -0.0010 365.2121 1 1
## 5 0.0150 0.0000 1 0
## 6 -0.0014 0.0000 3 0
## oproc_konkur bardzo_wysoka_kwota oproc_propon grupa_ryzyka
## 1 0.0499 0 0.0659 2
## 2 0.0479 0 0.0599 2
## 3 0.0399 0 0.0355 1
## 4 0.0499 0 0.0489 1
## 5 0.0529 0 0.0679 3
## 6 0.0399 0 0.0385 1
## wartosc_refinansowania score
## 1 10.57350 55
## 2 0.00000 149
## 3 0.00000 291
## 4 14.00672 468
## 5 0.00000 359
## 6 0.00000 283
summary(iv_data_with_scores_all$score)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -92.0 197.0 270.0 274.7 363.0 599.0
# Obliczanie przedziałów dla score'u
breaks_seq <- seq(floor(min(iv_data_with_scores_all$score)), ceiling(max(iv_data_with_scores_all$score)) + 24, by = 50)
# Tworzenie przedziałów co 20 punktów
iv_data_with_scores_all %>%
mutate(score_bin = cut(score, breaks = breaks_seq, right = FALSE)) %>%
group_by(score_bin) %>%
summarize(
bad_rate = mean(bad),
total = n(),
liczba_bad = sum(bad)
) -> goodrates_bins
# Wyświetlenie wyników
print(goodrates_bins)
## # A tibble: 14 × 4
## score_bin bad_rate total liczba_bad
## <fct> <dbl> <int> <dbl>
## 1 [-92,-42) 1 284 284
## 2 [-42,8) 0.992 254 252
## 3 [8,58) 0.993 908 902
## 4 [58,108) 0.985 2470 2434
## 5 [108,158) 0.973 2566 2497
## 6 [158,208) 0.946 4906 4639
## 7 [208,258) 0.897 6806 6102
## 8 [258,308) 0.816 6334 5166
## 9 [308,358) 0.679 4992 3390
## 10 [358,408) 0.520 4209 2188
## 11 [408,458) 0.354 3244 1149
## 12 [458,508) 0.227 2284 518
## 13 [508,558) 0.157 687 108
## 14 [558,608) 0.0714 56 4
Wykres good(bad) rate w zależności od przedziałów score
ggplot(goodrates_bins, aes(x = score_bin, y = bad_rate, group = 1)) +
geom_line(color = "steelblue", size = 1) +
geom_point(color = "darkblue", size = 2) +
labs(
title = "Bad rate względem przedziałów score",
x = "Przedział score",
y = "Bad rate"
) +
scale_y_continuous(
limits = c(0, 1),
breaks = seq(0, 1, 0.2)
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1)
)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Wykres krzyewj ROC
# Tworzenie krzywej ROC
roc_obj <- roc(iv_data_with_scores_all$bad, -iv_data_with_scores_all$score)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc_value <- auc(roc_obj)
gini_value <- 2*auc_value - 1
# Podstawowe informacje o krzywej ROC
cat(sprintf("AUC: %.4f\n", auc_value))
## AUC: 0.8446
cat(sprintf("Gini: %.4f\n", gini_value))
## Gini: 0.6891
# Wizualizacja krzywej ROC
roc_data <- data.frame(
specificity = roc_obj$specificities,
sensitivity = roc_obj$sensitivities
)
# Tworzenie wykresu
ggplot(roc_data, aes(x = 1 - specificity, y = sensitivity)) +
geom_line(color = "blue", size = 1) +
geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "gray") +
labs(
title = "Krzywa ROC dla modelu scoringowego",
subtitle = sprintf("AUC = %.4f, Gini = %.4f", auc_value, gini_value),
x = "1 - Swoistość", # Polska nazwa dla 1-Specificity
y = "Czułość" # Polska nazwa dla Sensitivity
) +
theme_minimal() +
coord_equal() +
annotate("text", x = 0.75, y = 0.25,
label = sprintf("AUC = %.4f\nGini = %.4f", auc_value, gini_value),
hjust = 0, size = 4) +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 10),
axis.title = element_text(size = 10),
panel.grid.minor = element_blank()
)

# Definiujemy wartości progowe score
thresholds <- c(0,100,200,300, 400, 500, 577)
# Tworzymy tabelę progową
#u nas bad to de facto good
threshold_table <- data.frame(score = thresholds) %>%
rowwise() %>%
mutate(
rzeczywisty_bad = sum(iv_data_with_scores_all$bad[iv_data_with_scores_all$score <= score], na.rm = TRUE),
przewidywany_bad = sum(iv_data_with_scores_all$score <= score, na.rm = TRUE)
) %>%
ungroup()
# Wyświetlenie wyniku
print(threshold_table)
## # A tibble: 7 × 3
## score rzeczywisty_bad przewidywany_bad
## <dbl> <dbl> <int>
## 1 0 524 526
## 2 100 3533 3569
## 3 200 10123 10452
## 4 300 21682 23762
## 5 400 27599 33199
## 6 500 29480 39024
## 7 577 29632 39988
Tabelka iv do worda
# Jeśli nie masz zainstalowanych tych pakietów:
# install.packages("flextable")
#install.packages("webshot2")
# webshot2::install_phantomjs() # uruchom raz, jeśli jeszcze nie masz PhantomJS
library(flextable)
library(webshot2)
## Warning: pakiet 'webshot2' został zbudowany w wersji R 4.4.3
# Przygotowanie tabeli
iv_selected <- subset(iv_table, info_value > 0.1)
iv_selected$Lp <- seq_len(nrow(iv_selected))
iv_selected <- iv_selected[, c("Lp", "variable", "info_value", "bins_count")]
# Tworzenie flextable
ft_iv <- flextable(iv_selected) %>%
set_header_labels(
Lp = "Lp",
variable = "Zmienna",
info_value = "IV",
bins_count = "Liczba binów"
) %>%
colformat_num(j = "info_value", digits = 4) %>%
autofit() %>%
theme_booktabs() %>%
add_header_lines(values = "Tabela zmiennych z IV > 0.1")
# Zapis jako plik HTML tymczasowy
html_path <- "iv_selected_table_temp.html"
save_as_html(ft_iv, path = html_path)
# Konwersja HTML do PNG
webshot2::webshot(url = html_path, file = "iv_selected_table.png", zoom = 2, vwidth = 1200)
## file:///C:/Users/mateu/Desktop/Semestr IV/Modele scoringowe/Projekt/Model konkursowy/iv_selected_table_temp.html screenshot completed

# Funkcja pozwalajaca wyznaczyć
score_function <- function(df) {
# Zmienne pochodne w modelu
df$bardzo_wysoka_kwota <- as.integer(df$kwota_kredytu > quantile(df$kwota_kredytu, 0.9, na.rm = TRUE))
df$roznica_oproc <- df$oproc_propon - df$oproc_konkur
df$fico_vs_oproc <- df$scoring_FICO * df$roznica_oproc
df$koszt_propon <- df$kwota_kredytu * (df$oproc_propon / 100) * (df$okres_kredytu / 12) # potrzebne do przekształceń
df$koszt_konkur <- df$kwota_kredytu * (df$oproc_konkur / 100) * (df$okres_kredytu / 12) # potrzebne do przekształceń
df$roznica_kosztu <- df$koszt_propon - df$koszt_konkur
df$ryzyko_vs_oproc <- df$grupa_ryzyka * df$roznica_oproc
df$stopien_refinansowania <- as.integer(df$oproc_refin > 0)
df$stosunek_refin_konkur <- df$oproc_refin / ifelse(df$oproc_konkur == 0, 0.0001, df$oproc_konkur)
df$umowa_N_roznica_oproc <- as.integer(df$typ_umowy == "N") * df$roznica_oproc
df$wartosc_refinansowania <- (df$oproc_refin / 100) * df$kwota_kredytu
df$wysoka_kwota <- as.integer(df$kwota_kredytu > quantile(df$kwota_kredytu, 0.75, na.rm = TRUE))
df$kwota_na_miesiac <- df$kwota_kredytu / df$okres_kredytu
df$fico_znormalizowana_kwota <- log1p(df$kwota_kredytu) / (df$scoring_FICO + 1)
df$skorygowana_atrakcyjnosc <- (df$oproc_konkur - df$oproc_propon) - df$koszt_pieniadza
df$ryzyko_vs_kwota <- df$grupa_ryzyka * df$kwota_kredytu ### GOAT
df$wskaźnik_refin_zysku <- ifelse(df$typ_umowy == "R", (df$oproc_refin - df$oproc_konkur) * df$kwota_kredytu,0)
df$presja_ratalna <- df$kwota_kredytu / df$scoring_FICO * log1p(df$okres_kredytu)
df$obciazenie_vs_fico <- (df$kwota_kredytu / df$okres_kredytu) / df$scoring_FICO
df$atrakcyjnosc_oferty <- (df$oproc_konkur - df$oproc_propon) / df$oproc_konkur
df$kwota_na_miesiac <- df$kwota_kredytu / df$okres_kredytu
# Wyliczenie wyniku scoringowego
score<- 310 +
case_when(df$atrakcyjnosc_oferty < -1 ~ -35,
df$atrakcyjnosc_oferty < -0.7 ~ -24,
df$atrakcyjnosc_oferty < -0.6 ~ -26,
df$atrakcyjnosc_oferty < -0.4 ~ -21,
df$atrakcyjnosc_oferty < -0.3 ~ -3,
df$atrakcyjnosc_oferty < -0.2 ~ 5,
TRUE ~ 15) +
case_when(df$bardzo_wysoka_kwota < 1 ~ 1,
TRUE ~ -10) +
case_when(df$fico_vs_oproc < 0 ~ 18,
df$fico_vs_oproc < 5 ~ 12,
df$fico_vs_oproc < 10 ~ 6,
df$fico_vs_oproc < 15 ~ -9,
df$fico_vs_oproc < 20 ~ -22,
df$fico_vs_oproc < 25 ~ -18,
df$fico_vs_oproc < 30 ~ -29,
TRUE ~ -23) +
case_when(df$fico_znormalizowana_kwota < 0.0125 ~ -38,
df$fico_znormalizowana_kwota < 0.013 ~ -16,
df$fico_znormalizowana_kwota < 0.0135 ~ -7,
df$fico_znormalizowana_kwota < 0.014 ~ 2,
df$fico_znormalizowana_kwota < 0.0145 ~ 11,
df$fico_znormalizowana_kwota < 0.015 ~ 22,
df$fico_znormalizowana_kwota < 0.0155 ~ 29,
TRUE ~ 32) +
case_when(df$grupa_ryzyka < 2 ~ -1,
df$grupa_ryzyka < 3 ~ 1,
df$grupa_ryzyka < 4 ~ 1,
TRUE ~ 1) +
case_when(df$kod_partnera < 2 ~ 26,
df$kod_partnera < 3 ~ -111,
TRUE ~ 3) +
case_when(df$kwota_kredytu < 10000 ~ 56,
df$kwota_kredytu < 15000 ~ 35,
df$kwota_kredytu < 20000 ~ 11,
df$kwota_kredytu < 25000 ~ -7,
df$kwota_kredytu < 30000 ~ -22,
df$kwota_kredytu < 35000 ~ -42,
df$kwota_kredytu < 45000 ~ -52,
TRUE ~ -56) +
case_when(df$kwota_na_miesiac < 200 ~ 60,
df$kwota_na_miesiac < 250 ~ 40,
df$kwota_na_miesiac < 300 ~ 25,
df$kwota_na_miesiac < 350 ~ 11,
df$kwota_na_miesiac < 400 ~ 3,
df$kwota_na_miesiac < 450 ~ -21,
df$kwota_na_miesiac < 500 ~ -26,
TRUE ~ -51) +
case_when(df$obciazenie_vs_fico < 0.3 ~ 5,
df$obciazenie_vs_fico < 0.4 ~ 3,
df$obciazenie_vs_fico < 0.5 ~ 1,
df$obciazenie_vs_fico < 0.6 ~ -1,
df$obciazenie_vs_fico < 0.7 ~ -3,
df$obciazenie_vs_fico < 0.8 ~ -4,
df$obciazenie_vs_fico < 1 ~ -5,
TRUE ~ -5) +
case_when(df$oproc_konkur < 0.04 ~ 1,
df$oproc_konkur < 0.044 ~ -29,
df$oproc_konkur < 0.046 ~ -31,
df$oproc_konkur < 0.048 ~ 6,
df$oproc_konkur < 0.052 ~ 7,
df$oproc_konkur < 0.054 ~ 3,
df$oproc_konkur < 0.056 ~ 20,
TRUE ~ 15) +
case_when(df$oproc_propon < 0.05 ~ -1,
df$oproc_propon < 0.06 ~ -2,
df$oproc_propon < 0.065 ~ 1,
df$oproc_propon < 0.07 ~ 0,
df$oproc_propon < 0.08 ~ 1,
df$oproc_propon < 0.085 ~ 3,
df$oproc_propon < 0.105 ~ 2,
TRUE ~ 3) +
case_when(df$oproc_refin < 0.06 ~ 1,
df$oproc_refin < 0.07 ~ -1,
TRUE ~ -2) +
case_when(df$presja_ratalna < 60 ~ 21,
df$presja_ratalna < 80 ~ 11,
df$presja_ratalna < 140 ~ 1,
df$presja_ratalna < 160 ~ -9,
df$presja_ratalna < 180 ~ -11,
df$presja_ratalna < 200 ~ -17,
df$presja_ratalna < 220 ~ -18,
TRUE ~ -19) +
case_when(df$roznica_kosztu < 0 ~ -10,
df$roznica_kosztu < 10 ~ -8,
df$roznica_kosztu < 20 ~ -2,
df$roznica_kosztu < 30 ~ 9,
df$roznica_kosztu < 40 ~ 15,
df$roznica_kosztu < 50 ~ 23,
TRUE ~ 29) +
case_when(df$roznica_oproc < 0.01 ~ -21,
df$roznica_oproc < 0.015 ~ -6,
df$roznica_oproc < 0.02 ~ 10,
df$roznica_oproc < 0.03 ~ 30,
df$roznica_oproc < 0.035 ~ 29,
df$roznica_oproc < 0.04 ~ 44,
df$roznica_oproc < 0.055 ~ 21,
TRUE ~ 48) +
case_when(df$ryzyko_vs_kwota < 20000 ~ 47,
df$ryzyko_vs_kwota < 30000 ~ 8,
df$ryzyko_vs_kwota < 40000 ~ -12,
df$ryzyko_vs_kwota < 50000 ~ -16,
df$ryzyko_vs_kwota < 60000 ~ -17,
df$ryzyko_vs_kwota < 70000 ~ -28,
df$ryzyko_vs_kwota < 80000 ~ -30,
TRUE ~ -43) +
case_when(df$ryzyko_vs_oproc < 0 ~ 20,
df$ryzyko_vs_oproc < 0.02 ~ 14,
df$ryzyko_vs_oproc < 0.04 ~ -5,
df$ryzyko_vs_oproc < 0.08 ~ -18,
df$ryzyko_vs_oproc < 0.1 ~ -22,
df$ryzyko_vs_oproc < 0.12 ~ -33,
df$ryzyko_vs_oproc < 0.22 ~ -13,
TRUE ~ -36) +
case_when(df$skorygowana_atrakcyjnosc < -0.07 ~ -46,
df$skorygowana_atrakcyjnosc < -0.055 ~ -33,
df$skorygowana_atrakcyjnosc < -0.035 ~ -36,
df$skorygowana_atrakcyjnosc < -0.03 ~ -10,
df$skorygowana_atrakcyjnosc < -0.02 ~ 5,
df$skorygowana_atrakcyjnosc < -0.015 ~ 18,
df$skorygowana_atrakcyjnosc < -0.01 ~ 20,
TRUE ~ 33) +
case_when(df$stopien_refinansowania < 1 ~ 18,
TRUE ~ -37) +
case_when(df$stosunek_refin_konkur < 1.2 ~ -1,
df$stosunek_refin_konkur < 1.4 ~ 1,
TRUE ~ 2) +
case_when(df$typ_umowy == "N" ~ -5,
df$typ_umowy == "R" ~ 4,
df$typ_umowy == "U" ~ 1,
TRUE ~ 0) +
case_when(df$umowa_N_roznica_oproc < 0.025 ~ 4,
TRUE ~ -57) +
case_when(df$wartosc_refinansowania < 12 ~ -14,
TRUE ~ 63) +
case_when(df$wskaźnik_refin_zysku < 200 ~ -8,
TRUE ~ 27) +
case_when(df$wysoka_kwota < 1 ~ -6,
TRUE ~ 30)
return(score)
}
# Wyznazcenie score na danych pierwotnych (bez przekształceń)
iv_data_with_scores_all$score_z_funkcji <- score_function(df_copy)
# Sprawdzenie, czy są różnice
iv_data_with_scores_all$scores_diff<- iv_data_with_scores_all$score-iv_data_with_scores_all$score_z_funkcji
summary(iv_data_with_scores_all$scores_diff)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 0 0 0 0 0
# Testowy dataset
df3<-data.frame(
LP = c(1, 2, 3, 4, 5),
data_akceptacji = structure(c(1113696000, 1113696000, 1113696000, 1113696000,1113696000),
tzone = "UTC", class = c("POSIXct", "POSIXt")),
grupa_ryzyka = c(2, 2, 1, 1, 3),
kod_partnera = c(2, 2, 3, 1, 1),
typ_umowy = c("R", "N", "N", "R", "U"),
scoring_FICO = c(702, 719, 802, 723, 690),
okres_kredytu = c(48, 72, 60, 60, 72),
kwota_kredytu = c(26500, 34999.99, 28000, 20750.69, 19999.99),
oproc_refin = c(0.0399, 0, 0, 0.0675, 0),
oproc_konkur = c(0.0499, 0.0479, 0.0399, 0.0499, 0.0529),
koszt_pieniadza = c(0.011, 0.011, 0.011, 0.011, 0.011),
oproc_propon = c(0.0659, 0.0599, 0.0355, 0.0489, 0.0679),
akceptacja_klienta = c(0, 0, 0, 1, 0))
df3$score <- score_function(df3)