<jupyter_start><jupyter_text>Koeficijent korelacije >U ovoj svesci ćemo se baviti merama korelacije između dva niza uparenih skupova numeričkih podataka. Sve te mere su nekakvi koeficijenti korelacije. Mi ćemo ovde na primeru koristiti koeficijent koji se obično podrazumeva – Pirsonov koeficijent korelacije. Primer na kome ćemo videti kako se u Pajtonu traže, računaju i tumače korelacije je timska statistika košarkaške NBA lige preuzeta sa sajta [Basketball Reference](https://www.basketball-reference.com/teams/PHI/2021.html). Pošto se statistika procenta šuta, broja skokova i asistencija već dugo objavljuje, taj skup podatka je dostupan za analizu i prilično jednostavan za tumačenje. Kroz analizu u ovoj svesci naći ćemo koje to godišnje statistike najbolje koreliraju sa brojem pobeda koje je jedan tim ostvario.  Podatke potrebne za ovu analizu imate snimljene kao CSV fajlove u folderu __data__. Prvi je statistika svih NBA timova za dvadesetak kategorija u sezoni 2020/21. Drugi je statistika koju su protiv njih imali njihovi protivnici u ovoj sezoni. Treći fajl sadrži imena timova i broj pobeda koje su zabeležili u sezoni. U četvrtom fajlu je opis korišćenih oznaka.<jupyter_code>import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
timovi=pd.read_csv("data/NBA21_teams.csv")
protivnici=pd.read_csv("data/NBA21_opponents.csv")
pobede=pd.read_csv("data/Broj_pobeda.csv")
oznake=pd.read_csv("data/key.csv")<jupyter_output><empty_output><jupyter_text>Ovde ćemo samo pogledati zaglavlje tabale __timovi__ da bismo videli koje sve kategorije imamo. Izgleda da kategorija ima više nego što može da se prikaže na ovoj strani. Tri tačke (...) u tabeli nam govore da su tu neke kolone ostane neprikazane zbog manjka prostora.<jupyter_code>timovi.head()<jupyter_output><empty_output><jupyter_text>Iste kategorije podataka imamo i za njihove protivnike. Odatle možemo da vidimo, na primer, da su timovi koji su igrali protiv <NAME> postigli ukupno 2730 koševa iz igre (FG).<jupyter_code>protivnici<jupyter_output><empty_output><jupyter_text>Ono što takođe vidimo je da imamo nepotrebni red u u kom su prosečni podaci za sve timove. Taj podatak nam ne treba pa ćemo taj red obrisati pomoću funkcije `drop()`. To je u obe tabele 31. red koji u Pajtonu ima indeks 30.<jupyter_code>timovi.drop(30,inplace=True)
protivnici.drop(30,inplace=True)<jupyter_output><empty_output><jupyter_text>Bilo bi dobro da sad ove dve tabele spojimo u jednu. Kako nije zgodno da se nazivi kolona dupliraju (jednom imamo FG% kao procenat šuta samog tima, a drugi put kao procenat šuta njihovih protivnika), promenićemo imena polovini promenljivih. Svim promenjivim koje se odnose na statistiku protivnika ćemo dodati "Opp_" u naziv.<jupyter_code>protivnici.columns="Opp_"+protivnici.columns
protivnici.columns<jupyter_output><empty_output><jupyter_text>Sada je ostalo da spojimo tabele. Iz nekog razloga redosled timova nije isti u obe tabele pa ćemo morati da povezujemo podatke vodeći računa o tome kom timu pripadaju. Funkcije `merge()` će to znati da uradi ako joj kažemo da treba povezati podatke za __Team__ iz prve i __Opp_Team__ iz druge tabele. Tu zbirnu tabelu ćemo nazvati __tabela__.<jupyter_code>tabela=timovi.merge(protivnici,left_on="Team",right_on="Opp_Team")
tabela<jupyter_output><empty_output><jupyter_text>Primetite da pored naziva nekih timova u tabeli __tabela__ stoji zvezdica. Šta god to značilo, to nam ovde smeta da povežemo podatke sa tabelom __pobede__ u kojoj nazivi timova nemaju zvezdicu. Pomoću funkcije `str.replace()` ćemo zameniti znak zvezdica praznim stringom.<jupyter_code>tabela['Team']=tabela['Team'].str.replace('*','',regex=False)<jupyter_output><empty_output><jupyter_text>Sada možemo da povežemo statistike sa brojem pobeda. To praktično znači da ćemo tabeli dodati kolonu u kojoj piše koliko je koji tim ostvario pobeda.<jupyter_code>tabela=tabela.merge(pobede,on='Team')
tabela
tabela.columns<jupyter_output><empty_output><jupyter_text>Imamo 51 kolonu što je mnogo za prikazivanje na ekranu. Bilo bi dobro da neke nepotrebne izbrišemo. Za početak treba izbrisati tekstualne podatke, rang i broj odigranih utakmica (pošto su svi morali da odigraju isti broj utakmica u sezoni).<jupyter_code>tabela.drop(['Rk','G','Opp_Rk','Opp_Team','Opp_G'],axis=1,inplace=True)
tabela<jupyter_output><empty_output><jupyter_text>Ni sada nije mnogo bolje, ali su barem sve vrednosti numeričke pa ćemo moći da izračunamo koreficijent korelacije. Usvari, biće sve numeričke kada naziv tima izmestimo iz tabele i pretvorimo ga u indeksnu kolonu.<jupyter_code>tabela.index=tabela['Team']
tabela.drop('Team',axis=1,inplace=True)<jupyter_output><empty_output><jupyter_text>To je sad ta tabela koji treba da analiziramo.<jupyter_code>tabela<jupyter_output><empty_output><jupyter_text>Koeficijent korelacije se uvek računa za dva uparena niza brojeva. To ovde konkretno znači da svakom timu pridružujemo dve vrednosti, npr. broj odigranih minuta (MP) i broj pobeda (W). Onda treba da vidimo postoji li zavisnost između tih podataka.Kreatori Pajtona su pri pisanju funkcija tabele pretpostavili nizovima, tako da moramo dva niza da pretvorimo u pomoćnu tabelu kako bismo pozvali funkciju koja računa koeficijent korelacije.<jupyter_code>tabela[['FG','W']]<jupyter_output><empty_output><jupyter_text>Ovo bismo mogli da predstavimo grafički kako bismo "videli" zavisnost pre nego što je svedemo samo na jedan broj, koeficijent korelacije. Za razumevanje korelacije poželjno je da uvek pogledamo grafikon jer nam on mnogo više govori od koeficijenta. Kod automatske obrade, naravno, više se oslanjamo na koeficijente.<jupyter_code>plt.scatter(tabela['FG'],tabela['W'])
tabela['FG'].corr(tabela['W'])<jupyter_output><empty_output><jupyter_text>Očekivano, postoji značajna korelacija između broja koševa postignutih iz igre i broja pobeda. Ko više koševa daje, češće pobeđuje. Ipak, ta veza nije sasvim pouzdana. Ne možemo reći da je veći broj koševa garancija pobede. Vidimo da ima timova koji imaju 3100 pogodaka i svega 30-35 pobeda, dok neki drugi sa 3000 pogodaka ostvaruju 50 pobeda.  Na sličan način kao za broj koševa, možemo da izračunamo koeeficijent korelacije sa brojem pobeda i za sve ostale promenljive. Te rezultate ćemo staviti u niz __kk__.<jupyter_code>kk=[tabela[i].corr(tabela['W']) for i in tabela.columns]
kk<jupyter_output><empty_output><jupyter_text>Biće nam lakše da prikažemo rezultate ako ih umesto u listu stavimo u _DataFrame_ gde će nazivi promenljivih biti imena redova.<jupyter_code>kk = pd.DataFrame (kk, columns = ['Koeficijent korelacije'])
kk.index=tabela.columns
kk<jupyter_output><empty_output><jupyter_text>Da bi rezultati bili pregledniji, sortiraćemo ih u opadajućem redosledu i prikazati grafički.<jupyter_code>kk=kk.sort_values('Koeficijent korelacije', ascending=False)
kk
f, ax = plt.subplots(figsize = (10,15))
sns.set_theme(style="whitegrid")
sns.barplot(y=kk.index,x=kk['Koeficijent korelacije'],orient="h")<jupyter_output><empty_output><jupyter_text>Najveći koeficijent korelacije, logično, broj pobeda ima sam sa sobom (1.00). Sledeći na listi je procenat trojki (3P%, 0.79), dok je na trećem mestu procenat šuta iz igre (FG%, 0.75). Posle toga imamo sve slabiju zavisnost. Vidimo da broj blokada (BLK) nema praktično nikakve veze sa brojem pobeda nekog tima (BLK, 0.01). Ipak, postoje i značajne negativne zavisnosti. Najveći negativni koeficijent korelacije sa brojem pobeda ima broj blokada protivničkog tima (Opp_BLK, -0.74). To znači da tim koji primi mnogo blokada, nema mnogo izgleda za pobedu. Na sličan način, možemo da utvrdimo i tumačimo i druge statistike tima. To ostavljamo za samostalan rad.<jupyter_code>plt.scatter(tabela['Opp_BLK'],tabela['W'])<jupyter_output><empty_output><jupyter_text>Kada bismo na osnovu svih dostupnih statistika koristeći linearni model pravili predikciju uspešnosti tima, broj promenljivih bi sa 45 trebalo smanjiti na nekoliko najznačajnijih koje su međusobno nezavisne. Korelacija svake promenljive sa brojem pobeda nam daje koliko su određene promenljive značajne, ali za meru nezavisnosti moramo da odredimo korelaciju svake promenljive sa svakom drugom. Pomoću funkcije `corr()` dobijamo tabelu korelacija (tkor) između podataka datih u kolonama originalne tabele (tabela)._Naravno, pravljenje modela za predikciju ne treba raditi na osnovu agregiranih podataka (srednje vrednosti za celu sezonu) nego na osnovu podataka za svaku pojedinačnu utakmicu. Tek tada bi se videlo koja je statistika koliko važna._<jupyter_code>tkor = tabela.corr()
plt.subplots(figsize=(15,10))
sns.heatmap(tkor, xticklabels=tkor.columns, yticklabels=tkor.columns, annot=False, cmap=sns.diverging_palette(220, 20, as_cmap=True))<jupyter_output><empty_output><jupyter_text>Polja sa intezivno crvenom bojom najviše koreliraju međusobno, bela praktično ne koreliraju, dok intenzivno plava predstavljaju jaku negativnu korelaciju. Na pretodnoj slici možemo da primetimo crvenu dijagonalu gde svaka promenljiva savršeno korelira sa samom sobom. Osim toga ima oblasti od 2-3 polja koja prilično dobro koreliraju međusobno. To su, na primer, 3P i 3PA ili FT i FTA, što je logično -- veći broj pogadaka zahteva veći broj šuteva. Ovakve promenljive daju redundantne informacije i bilo bi dobro da iz tog skupa uzmemo samo jednu, onnu koja ima najveću korelaciju. Ovde nećemo ulaziti u odabir promenljivih (_feature selection_) jer je tema složenija od prostog posmatranja koeficijenata korelacije. Uostalom, najbolji izbor promenjljivih za različite modele predikcije ne mora da bude isti. Završićemo samo jednim ad-hoc izborom najinformativnijih promenjlivih koje međusobno nisu previše povezane. To je ono što bi trebalo da se pojavljuje kao statistika u poluvremenu ili za vreme tajm-auta.<jupyter_code>mala=tabela[['3P%','2P%','DRB','Opp_AST','Opp_DRB','Opp_FG%','Opp_BLK','W']]
mala.corr()
mkor = mala.corr()
plt.subplots(figsize=(15,10))
sns.heatmap(mkor, xticklabels=mkor.columns, yticklabels=mkor.columns, annot=True, cmap=sns.diverging_palette(220, 20, as_cmap=True))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.06929024583663759, 'fraction_numerical': 0.008921490880253766, 'mean_word_length': 6.545998504113688, 'pattern_counts': {'":': 0, '<': 78, '<?xml version=': 0, '>': 79, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '251077', 'license': 'MIT', 'n_tokens_mistral': 4306, 'n_tokens_neox': 4186, 'n_words': 1170, 'path': 'notebooks/7 Koeficijent korelacije.ipynb', 'repo_name': 'sverbic/skriptna-obrada-podataka', 'size': '10095'}