﻿# -*- coding: utf-8 -*-
"""
@author: 
  Katedra Technologii Informatycznych 
  Wydział Zarządzania i Modelowania Komputerowego PŚk

  Klasyfikacja przezycia pasażera scharakteryzowanego przez pewne cechy
  w katastrofie Titanica z wykorzystaniem drzewa decyzyjnego
  Wersja progmu: bez wykresów
"""
# c:\Python\WykładyLaboratoria_MN\Programy_MN\CZ_06\

# Uwaga: ustal katalog roboczy dla programu
import pandas as pd
# Import  modułu dostarczającego narzędzia do budowy drzewa klasyfikacyjnego
# Jeżeli import jest nieudany, nalezy zainstalować biblioteke za pomoca
# programu pip w oknie konsoli 
# (pip.exe jest zainstalowany w c:\Program Files\Spyder\Python\)
from sklearn import tree

# Import  modułu do tworzenia wykresow
import matplotlib.pyplot as plt

# Wczytanie danych Titanica do ramki danych df1

# (1) ===>> SPRAWDZ ZAWARTOSC RAMKI DANYCH df1
df1 = pd.read_csv("titanic.csv")

# Usunięcie nieanalizowanych kolumn
# Metoda drop zwraca ramkę danych z usuniętymi kolumnami.
# Od teraz analizowana ramka danych ma identyfikator df
df=df1.drop(['name','sibsp','parch', 'ticket', 'cabin','boat', 'body', 'home_dest'], axis=1)
# Pozostałe zmienne oryginalne: pclass, survived, sex, age, fare, embarked 

# Kodowanie cech jakosciowych do nominalnych - wymaganie funkcji tworzącej drzewo; 
# Wywołanie funkcji 'map' ze słownikiem zamiast z funkcją
df['sex_kod'] = df['sex'].map( {'female': 1, 'male': 2} )
df['embarked_kod'] = df['embarked'].map( {'S': 1, 'C': 2, 'Q': 3} )

# Kategoryzacja cech ilosciowych (kodowanie do nominalnych); 
# Wykorzystanie własciwosci 'loc' obiektu DataFrame
df.loc[ df['age'] <= 10, 'age_kod'] = 10
df.loc[(df['age'] > 10) & (df['age'] <= 20), 'age_kod'] = 20
df.loc[(df['age'] > 20) & (df['age'] <= 30), 'age_kod'] = 30
df.loc[(df['age'] > 30) & (df['age'] <= 40), 'age_kod'] = 40
df.loc[(df['age'] > 40) & (df['age'] <= 50), 'age_kod'] = 50
df.loc[(df['age'] > 50) & (df['age'] <= 60), 'age_kod'] = 60
df.loc[(df['age'] > 60),'age_kod'] = 60

df.loc[ df['fare'] <= 7.91, 'fare_kod'] = 1
df.loc[(df['fare'] > 7.91) & (df['fare'] <= 14.454), 'fare_kod'] = 2
df.loc[(df['fare'] > 14.454) & (df['fare'] <= 31), 'fare_kod'] = 3
df.loc[ df['fare'] > 31, 'fare_kod'] = 4

# Usunięcie rekordów z brakami
df.dropna(how='any', inplace=True)

# (2) ===>> SPRAWDZ ZAWARTOSC RAMKI DANYCH df
print("Liczba wszystkich obserwacji:\t%5i\nLiczba obserwacji po usunięciau braków:\t%5i" %(10, 5) )

# (3) ===>> PRZEANALIZUJ WYKRESY SLUPKOWE POZIOME
Port=df.groupby("embarked_kod")["embarked_kod"].count()
Port.plot(kind='barh', title="Port zaokrętowania\n1-Southampton; 2-Cherbourg;3-Queenstown" )
plt.show()
Klasa=df.groupby("pclass")["pclass"].count()
Klasa.plot(kind='barh', 
      title="Wskaźnik statusu spoleczno-ekonomicznego\n 1-wysoki; 2-sredni; 3-niski" )
plt.show()
Plec=df.groupby("sex_kod")["sex_kod"].count()
Plec.plot(kind='barh', title="Plec pasażera\n1-kobieta, 2-mężczyzna" )
plt.show()
Wiek=df.groupby("age_kod")["age_kod"].count()
Wiek.plot(kind='barh', title="Wiek pasażera\nprawy koniec przedziału, co 10 lat" )
plt.show()
BiletC=df.groupby("fare_kod")["fare_kod"].count()
BiletC.plot(kind='barh', title="Cena biletu\n1-najtańsze, 4-najdroższe" )
plt.show()

# Drzewo decyzjne klasyfikujące cechę 'survived' (oryginalnie: 0 - NIE, 1 - TAK
# na podstawie zakodowanych cech: embarked, class, sex, age, fare
X=df[["embarked_kod", "pclass", "sex_kod", "age_kod", "fare_kod"]]
#   =================>> USUNAC Y=df["survived"]

# Wprowadzenie nowej nazwy zmiennej celu 'uratowany' i jej inne kodowanie
df.loc[ df['survived'] < 1, 'uratowany'] = -1  # <- NIE (wartosc ujemna) 
df.loc[ df['survived'] >= 1, 'uratowany'] = 1  # <- TAK (wartosc dodatnia) 
Y=df["uratowany"]

# Ustalenie głędbokosci drzewa i kryterium podziału: entropia 
# Podział w węzle następuje wg tej cechy, która powoduje maksymalizacje przyrostu informacji
# czyli minimalizację entropii. To oznacza, że porównuje się przyrosty informcji 
# (przyrost ten jest dany pewną zaleznoscią) dla podziału wg wszystkich mozliwych cech.
# Wybierana jest ta cecha, dla której ten przyrost jest największy.

#  Utworzenie klasyfikatora drzewiastego i wykres drzewa decyzyjnego
clf = tree.DecisionTreeClassifier(random_state=1, criterion='entropy', 
                                  min_impurity_decrease=0.003, max_depth=4)
clf = clf.fit(X, Y)
# Zmienna celu jest porządkowana rosnąco wg wartosci numerycznych 
# Dla dwuwartosciowej zmiennej celu: 
#    y[0] wartosc mniejsza (dla uratowany = -1 - dead), 
#    y[1] wartosc większa (dla uratowany = 1 - alive)

# Lewa gałąź w węzle drzewa reprezentuje odpowiedż True (tak) 
# a prawa odpowiedź False (Nie), na zapytanie dzielące zbior danych
plt.figure(figsize=(45, 25))
tree.plot_tree(clf, max_depth=4, feature_names=X.columns.values,
               class_names=["dead :-(", "alive :-)"], rounded=True, 
               filled=True, proportion=False, fontsize=30)
plt.show()

# Prognoza przeżycia katastrofy dla poszczególnychrekordów (osób) 
# Wyznaczenia miar oceny jakosci klasyfikacji
from sklearn import metrics #Import scikit-learn metrics do oceny jakoci klasyfikatora
Y_pred = clf.predict(X)
print("Dopasowanie: ", metrics.accuracy_score(Y, Y_pred))

# (4) ===>> OCEN JAKOSC KLASYFIKACJI NA PODSTAWIE MACIERZY POMYLEK
cm=metrics.confusion_matrix(Y, Y_pred)
#disp = metrics.ConfusionMatrixDisplay(confusion_matrix=cm,display_labels=clf.classes_)
#disp.plot()
disp = metrics.ConfusionMatrixDisplay(confusion_matrix=cm,display_labels=["dead :-(", "alive :-)"])
disp.plot()
plt.show()

# (5) ===>> SPRAWDZ WAZNOSC CECH W TWORZENIU KLASYFIKATORA DRZEWIASTEGO
importances=clf.feature_importances_
importances_frame = pd.DataFrame({'Feature': ["embarked_kod", "pclass", "sex_kod", "age_kod", "fare_kod"], 
                                  'Importance': importances})
print(importances_frame)
importances_frame.plot(kind = 'bar', y = 'Importance', x="Feature", legend=False, 
                       title="Ważność zmiennych")
#ax1 = plt.axes()
#x_axis = ax1.axes.get_xaxis()
#x_label = x_axis.get_label()
#x_label.set_visible(False)
plt.show()

# Czyszczenie okna konsoli Spydera
print("\033[H\033[J", end="")
# Slownik portow morskich
porty={'S':1, 'C':2, 'Q':3}

# Pobranie danych uzytkownika do prognozy
print("Podaj swoje dane")
port = input ('Port zaokrętowania (S, C, Q): ').upper()
port= 1 if port not in ['S','C','Q'] else porty[port] 
klasa = input ('Status społeczno-ekonomiczny (1-wyzszy, 2-sredni, 3-nizszy): ')
klasa= 1 if klasa not in ['1','2','3'] else int(klasa)
plec=input ('Plec (1-kobieta, 2-mezczyzna): ')
plec= 1 if plec not in ['1','2'] else int(plec)
wiek=input ('Wiek - wskaż górną granicę lat (10, 20, 30, 40, 50, 60): ')
wiek= 10 if wiek not in ['10','20','30','40','50','60'] else int(wiek)
bilet=input ('Cena biletu (1-bardzo niska, 2-niska, 3-rednia, 4-wysoka): ')
bilet= 1 if bilet not in ['1','2','3','4'] else int(bilet)
MD=[port, klasa, plec, wiek, bilet]
MojeDane=pd.DataFrame([[1,1,1,1,1]], columns=("embarked_kod", "pclass", "sex_kod", "age_kod", "fare_kod"))
MojeDane=pd.DataFrame([MD], columns=("embarked_kod", "pclass", "sex_kod", "age_kod", "fare_kod"))

# Prognoza przezycia uzytkownika
MojWyrok=clf.predict(MojeDane)
if MojWyrok[0] == -1:
    print("\nNiestety życie skończone w wodach Atlantyku")
else:
    print("\nGratulacje!!! Życie uratowane")

# (6) ---> KONIEC PROGRAMU









