L3: Analiza eksploracyjna zbioru danych¶
Exploratory data analysis (EDA)¶
Przed rozpoczęciem rozwiązywania problemu przy użyciu metod uczenia maszynowego, w szczególności przed rozpoczęciem budowania modelu, konieczne jest sprawdzenie, z jakimi danymi przyszło się nam mierzyć.
Wśród podstawowych kwestii, które powinniśmy sprawdzić, są:
ile mamy cech?
które spośród nich to cechy kategoryczne, a które numeryczne?
jakie wartości przyjmują poszczególne cechy?
czy wśród danych są brakujące wartości?
czy istnieje i jak wygląda etykieta? (w szczególności - czy mierzymy się z zadaniem klasyfikacji, regresji czy klasteryzacji?)
czy dane są zbalansowane względem danej wyjściowej?
Dla małych i prostych zbiorów do nauki (tzw. toy tasks), zazwyczaj wystarczające jest ręczne przejrzenie pliku z danymi, by potrafić odpowiedzieć na w/w pytania. Niemniej przy bardziej ambitnych zadaniach, z pomocą przychodzą narzędzia automatyzujące pracę.
Przykładowy zbiór danych¶
Przeanalizujmy klasyczny zbiór danych dotyczący wina (opublikowany przez Forina, M. et al, PARVUS - An Extendible Package for Data Exploration, Classification and Correlation. Institute of Pharmaceutical and Food Analysis and Technologies, Via Brigata Salerno, 16147 Genoa, Italy
, więcej informacji tutaj)
Zbiór zawiera właściwości fizykochemiczne różnych próbek wina pobranych z jednego z regionów słonecznej Italii, jednakże pochodzących od trzech różnych plantatorów. Założeniem problemu jest określenie, który z nich jest wytwórcą danej próbki.
W celu uczynienia przykładu ambitniejszym, zbiór został celowo zaszumiony - tj. usunięto losowo część wartości.
Zacznijmy od wczytania zbioru:
import pandas as pd
df = pd.read_csv('../docs/lab3/wine_with_nulls.csv', )
df.head()
alcohol | malic_acid | ash | alcalinity_of_ash | magnesium | total_phenols | flavanoids | nonflavanoid_phenols | proanthocyanins | color_intensity | hue | od280/od315_of_diluted_wines | proline | target | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 14.23 | 1.71 | 2.43 | 15.6 | 127.0 | 2.80 | 3.06 | 0.28 | 2.29 | 5.64 | 1.04 | 3.92 | 1065.0 | 0 |
1 | 13.20 | 1.78 | 2.14 | 11.2 | 100.0 | 2.65 | 2.76 | 0.26 | 1.28 | 4.38 | 1.05 | 3.40 | 1050.0 | 0 |
2 | 13.16 | 2.36 | 2.67 | 18.6 | 101.0 | NaN | 3.24 | 0.30 | 2.81 | 5.68 | 1.03 | 3.17 | 1185.0 | 0 |
3 | 14.37 | 1.95 | 2.50 | 16.8 | 113.0 | 3.85 | NaN | 0.24 | 2.18 | 7.80 | 0.86 | 3.45 | 1480.0 | 0 |
4 | 13.24 | 2.59 | NaN | 21.0 | 118.0 | 2.80 | 2.69 | 0.39 | 1.82 | 4.32 | 1.04 | 2.93 | 735.0 | 0 |
Na pierwszy rzut oka możemy stwierdzić, że wszystkie kolumny są numeryczne, ale ich wartości różnią się dość znacząco.
Podstawowe informacje o statystykach zbioru danych możemy uzyskać przy wbudowanej w Pandas metodzie describe()
df.describe()
alcohol | malic_acid | ash | alcalinity_of_ash | magnesium | total_phenols | flavanoids | nonflavanoid_phenols | proanthocyanins | color_intensity | hue | od280/od315_of_diluted_wines | proline | target | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 171.000000 | 170.000000 | 170.000000 | 167.000000 | 169.000000 | 171.000000 | 167.000000 | 171.000000 | 173.000000 | 170.000000 | 175.000000 | 170.000000 | 172.000000 | 178.000000 |
mean | 13.009357 | 2.318059 | 2.360000 | 19.404790 | 100.088757 | 2.291988 | 2.019760 | 0.365614 | 1.583295 | 5.009529 | 0.959920 | 2.615176 | 756.209302 | 0.938202 |
std | 0.819951 | 1.108406 | 0.275004 | 3.328986 | 14.490898 | 0.626310 | 1.006122 | 0.123074 | 0.572402 | 2.292621 | 0.228525 | 0.706861 | 315.609153 | 0.775035 |
min | 11.030000 | 0.740000 | 1.360000 | 10.600000 | 70.000000 | 0.980000 | 0.340000 | 0.130000 | 0.410000 | 1.280000 | 0.480000 | 1.270000 | 278.000000 | 0.000000 |
25% | 12.370000 | 1.575000 | 2.202500 | 17.150000 | 88.000000 | 1.730000 | 1.095000 | 0.270000 | 1.250000 | 3.220000 | 0.785000 | 1.970000 | 508.000000 | 0.000000 |
50% | 13.050000 | 1.850000 | 2.360000 | 19.400000 | 98.000000 | 2.350000 | 2.170000 | 0.340000 | 1.540000 | 4.640000 | 0.980000 | 2.780000 | 679.000000 | 1.000000 |
75% | 13.700000 | 3.030000 | 2.547500 | 21.500000 | 108.000000 | 2.800000 | 2.885000 | 0.445000 | 1.950000 | 6.122500 | 1.120000 | 3.177500 | 996.250000 | 2.000000 |
max | 14.830000 | 5.800000 | 3.230000 | 30.000000 | 162.000000 | 3.880000 | 5.080000 | 0.660000 | 3.580000 | 13.000000 | 1.710000 | 4.000000 | 1680.000000 | 2.000000 |
Wykresy z użyciem metod Pandas¶
Pandas udostępnia prosty interfejs rysowania wykresów Matplotlib bezpośrednio z DataFrame. Dzięki temu możemy prościej zwizualizowac wartości numeryczne i zaobserwować charakterystykę zbioru danych.
df = df[['alcohol', 'ash', 'total_phenols']]
df.plot()
<AxesSubplot:>

df.plot(subplots=True, figsize=(10, 5))
array([<AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>], dtype=object)

df.plot(kind='bar', subplots=True, figsize=(10, 5))
array([<AxesSubplot:title={'center':'alcohol'}>,
<AxesSubplot:title={'center':'ash'}>,
<AxesSubplot:title={'center':'total_phenols'}>], dtype=object)

from pandas.plotting import scatter_matrix
scatter_matrix(
df,
alpha=0.5,
figsize=(10, 10),
diagonal="kde"
)
array([[<AxesSubplot:xlabel='alcohol', ylabel='alcohol'>,
<AxesSubplot:xlabel='ash', ylabel='alcohol'>,
<AxesSubplot:xlabel='total_phenols', ylabel='alcohol'>],
[<AxesSubplot:xlabel='alcohol', ylabel='ash'>,
<AxesSubplot:xlabel='ash', ylabel='ash'>,
<AxesSubplot:xlabel='total_phenols', ylabel='ash'>],
[<AxesSubplot:xlabel='alcohol', ylabel='total_phenols'>,
<AxesSubplot:xlabel='ash', ylabel='total_phenols'>,
<AxesSubplot:xlabel='total_phenols', ylabel='total_phenols'>]],
dtype=object)

See also
Więcej o możliwościach Pandas w kontekście generowania wykresów - w dokumentacji
Pandas Profiling¶
Jest to biblioteka automatycznie analizująca zbiór danych i generujaca interaktywny raport. Alternatywnie, raport można zapisać w formacie .html
Instalacja przebiega standardowo:
pip install pandas-profiling
Użycie biblioteki jest niezwykle proste:
from pandas_profiling import ProfileReport
df = pd.read_csv('../docs/lab3/wine_with_nulls.csv', )
profile = ProfileReport(df)
profile.to_notebook_iframe()