Pandas

Questo tutorial con i relativi dataset è preso dalla pagina https://www.learndatasci.com/tutorials/python-pandas-tutorial-complete-introduction-for-beginners/, a cui rimando per eventuali approfondimenti.

Introduzione - Librerie

Una libreria, in python come in molti altri linguaggi, è un blocco composto da uno o più file che contengono variabili, funzioni o classi utili, spesso riferite ad un argomento. Una delle piu comuni è la libreria math, che contiene diverse funzioni o costanti matematiche non automaticamente presenti in python. Il motivo per cui tutte queste istruzioni non sono presenti normalmente in python è che lo appesantirebbero inutilmente, ma non appena uno ne ha bisogno può comunque recuperarle facilmente.

Ci sono diverse sintassi per importare una libreria:

In [22]:
import math
print(math.e)
2.718281828459045
In [7]:
whos
Variable   Type      Data/Info
------------------------------
math       module    <module 'math' from '/hom<...>37m-x86_64-linux-gnu.so'>

Come vedete, con import NomeLibreria si importa la libreria, che viene poi utilizzata con la sintassi NomeLibreria.funzione o variabile o classe.

Possiamo anche usare delle abbreviazioni:

In [23]:
del math
import math as mt
print(mt.e)
2.718281828459045

Da ora in poi la libreria non si chiamerà math ma mt. Spesso non abbiamo bisogno di un'intera libreria, ma solo di alcune funzioni. Dobbiamo allora usare un'altra sintassi:

In [24]:
del mt
from math import e, log
print(e)
print(log(e))
2.718281828459045
1.0
In [26]:
mt.e
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-26-aa8dc4cb6044> in <module>
----> 1 mt.e

NameError: name 'mt' is not defined

Come vedete in questo secondo caso non dobbiamo più richiamare nomelibreria.funzione, ma basta il nome della funzione. Se si importano diverse librerie bisogna fare attenzione ad evitare le ambiguità. Possiamo, con questa seconda sintassi, ottenere anche il risultato della precedente importando tutto con *:

In [27]:
from math import *
print(e)
2.718281828459045

Per l'utilizzo che ne faremo noi, non incontreremo mai problemi di import e conflitti. Chi fosse interessato ad approfondire può trovare ulteriori informazioni al link https://realpython.com/absolute-vs-relative-python-imports/ o sulle guide ufficiali (che però spesso sono un po' macchinose e tecniche su questi argomenti).

Pandas

Le pandas, dall'inglese panel data, sono delle librerie molto utilizzate in data science. Servono principalmente ad organizzare e 'pulire' i dati (campi formattati male, record incompleti ecc.), e ci permettono di farne una prima analisi: possiamo ad esempio calcolare la media di un valore o filtrare sui vari campi. È una specie di excel di python.

Installazione e import

Per importare le pandas diamo il comando

In [30]:
import pandas as pd

Se ricevete un errore perchè non le avete ancora installate potete, da terminale, digitare:

conda install pandas

o

pip3 install pandas

oppure eseguire la seguente riga:

In [ ]:
!pip3 install pandas

Il ! farà eseguire questa riga al terminale.

Componenti base: Series e DataFrames

I componenti principali delle pandas sono le Series e i DataFrame.

Una Series è sostanzialmente una colonna, e un DataFrame una tabella fatta di series.

Il modo più semplice di creare un DataFrame è attraverso un dizionario:

In [33]:
data = {
    'apples': [3, 2, 0, 1], 
    'oranges': [0, 3, 7, 2]
}
In [34]:
purchases = pd.DataFrame(data)

purchases
Out[34]:
apples oranges
0 3 0
1 2 3
2 0 7
3 1 2

Ogni coppia (chiave,valore) è stata trasformata in (nome colonna, colonna). I dati sono stati indicizzati con i numeri da 0 a 3 (la prima colonna a sinistra) ma possiamo anche definire una nostra indicizzazione con l'opzione index:

In [35]:
purchases = pd.DataFrame(data, index=['June', 'Robert', 'Lily', 'David'])

purchases
Out[35]:
apples oranges
June 3 0
Robert 2 3
Lily 0 7
David 1 2

Adesso possiamo accedere ai dati che riguardano un singolo indice (ad esempio gli acquisti di June) con il comando loc:

In [36]:
purchases.loc['June']
Out[36]:
apples     3
oranges    0
Name: June, dtype: int64

La sintassi è simile a quella dei dizionari, dove tra parentesi quadre va l'indice.

Leggere dati

Nella maggior parte dei casi, comunque, non dovremo essere noi a creare dati, ma avremo grossi file da inserire in un DataFrame. Vediamo come farlo con i file .csv (sostanzialmente dei file di testo che rappresentano tabelle dove le righe sono separate dall'andare a capo e le colonne da virgole o punti e virgola; è il formato standard per trasferire grossi dataset). La stessa cosa si applica sostanzialmente nello stesso modo a file excel (che possono essere importati direttamente, oppure excel permette di esportare csv), json (formato dei dati web), o diversi tipi di database (in python si usa spesso sqlitedb).

Apriamo il file 'purchases.csv', contenente gli stessi dati di sopra.

In [37]:
df = pd.read_csv('purchases.csv')

df
Out[37]:
Unnamed: 0 apples oranges
0 June 3 0
1 Robert 2 3
2 Lily 0 7
3 David 1 2

Come vedete la colonna 0 del nostro file non ha un nome, viene quindi salvata come Unnamed; l'indice invece è come sempre assegnato in automatico con numeri da 0 a 3. Noi però vogliamo che la colonna 0 sia letta come indice (in questo caso siamo fortunati, spesso i dataset non hanno questo tipo di indicizzazione quindi non ha senso cercarla):

In [39]:
df = pd.read_csv('purchases.csv', index_col=0)

df
Out[39]:
apples oranges
June 3 0
Robert 2 3
Lily 0 7
David 1 2

Possiamo facilmente fare l'operazione opposta con il comando to_csv:

In [41]:
df.to_csv('new_purchases.csv')

Operazioni con i DataFrame

Vediamo ora le principali operazioni che si possono fare con un DataFrame. Utilizzeremo il dataset IMDB-Movie-Data.csv, che trovate sul sito insieme alla lezione.

In [42]:
movies_df = pd.read_csv("IMDB-Movie-Data.csv", index_col="Title")

In questo caso usiamo la colonna 'title' come indice.

Per vedere le prime righe del dataset usiamo la funzione .head().

In [46]:
movies_df.head(3)
Out[46]:
Rank Genre Description Director Actors Year Runtime (Minutes) Rating Votes Revenue (Millions) Metascore
Title
Guardians of the Galaxy 1 Action,Adventure,Sci-Fi A group of intergalactic criminals are forced ... James Gunn Chris Pratt, Vin Diesel, Bradley Cooper, Zoe S... 2014 121 8.1 757074 333.13 76.0
Prometheus 2 Adventure,Mystery,Sci-Fi Following clues to the origin of mankind, a te... Ridley Scott Noomi Rapace, Logan Marshall-Green, Michael Fa... 2012 124 7.0 485820 126.46 65.0
Split 3 Horror,Thriller Three girls are kidnapped by a man with a diag... M. Night Shyamalan James McAvoy, Anya Taylor-Joy, Haley Lu Richar... 2016 117 7.3 157606 138.12 62.0

.head(n) accetta un numero come input, e restituisce le prime n righe del nostro dataset. Se non mettiamo niente restituirà le prime 5. Allo stesso modo si comporta la funzione .tail(), che restituisce le ultime righe.

In [47]:
movies_df.tail()
Out[47]:
Rank Genre Description Director Actors Year Runtime (Minutes) Rating Votes Revenue (Millions) Metascore
Title
Secret in Their Eyes 996 Crime,Drama,Mystery A tight-knit team of rising investigators, alo... Billy Ray Chiwetel Ejiofor, Nicole Kidman, Julia Roberts... 2015 111 6.2 27585 NaN 45.0
Hostel: Part II 997 Horror Three American college students studying abroa... Eli Roth Lauren German, Heather Matarazzo, Bijou Philli... 2007 94 5.5 73152 17.54 46.0
Step Up 2: The Streets 998 Drama,Music,Romance Romantic sparks occur between two dance studen... Jon M. Chu Robert Hoffman, Briana Evigan, Cassie Ventura,... 2008 98 6.2 70699 58.01 50.0
Search Party 999 Adventure,Comedy A pair of friends embark on a mission to reuni... Scot Armstrong Adam Pally, T.J. Miller, Thomas Middleditch,Sh... 2014 93 5.6 4881 NaN 22.0
Nine Lives 1000 Comedy,Family,Fantasy A stuffy businessman finds himself trapped ins... Barry Sonnenfeld Kevin Spacey, Jennifer Garner, Robbie Amell,Ch... 2016 87 5.3 12435 19.64 11.0

Questo ci serve per farci un'idea. Potete vedere come title sia più in basso degli altri nomi, ad indicare che si tratta dell'indice. Un'altra funzione utile è .info(), che ci riassume le caratteristiche del dataset:

In [48]:
movies_df.info()
<class 'pandas.core.frame.DataFrame'>
Index: 1000 entries, Guardians of the Galaxy to Nine Lives
Data columns (total 11 columns):
 #   Column              Non-Null Count  Dtype  
---  ------              --------------  -----  
 0   Rank                1000 non-null   int64  
 1   Genre               1000 non-null   object 
 2   Description         1000 non-null   object 
 3   Director            1000 non-null   object 
 4   Actors              1000 non-null   object 
 5   Year                1000 non-null   int64  
 6   Runtime (Minutes)   1000 non-null   int64  
 7   Rating              1000 non-null   float64
 8   Votes               1000 non-null   int64  
 9   Revenue (Millions)  872 non-null    float64
 10  Metascore           936 non-null    float64
dtypes: float64(3), int64(4), object(4)
memory usage: 93.8+ KB

Vediamo, ad esempio, che metascore e revenue hanno dei campi vuoti. Un altro comando utile è il comando .shape(), che ci indica la dimensione del dataset.

In [49]:
movies_df.shape
Out[49]:
(1000, 11)

Abbiamo poi un modo comodo di rimuovere i duplicati. Questo dataset non ne ha, quindi creiamone artificialmente:

In [50]:
temp_df = movies_df.append(movies_df)

temp_df.shape
Out[50]:
(2000, 11)

La funzione .append(), a differenza delle liste, non modifica il dataset originale ma ne ritorna uno nuovo. Il nostro temp_df ora ha 2000 righe, corrispondenti a due volte quello originale.

In [51]:
temp_df = temp_df.drop_duplicates()

temp_df.shape
Out[51]:
(1000, 11)

Come vedete, drop_duplicatest() ha cancellato le righe doppie. Anche questa funzione ritorna un nuovo DataFrame, anche se con l'opzione inplace=True possiamo modificare quello iniziale. Un'altra opzione utile è la keep, che permette di tenere alcuni duplicati.

Con il comando .columns otteniamo le colonne del nostro dataset:

In [52]:
movies_df.columns
Out[52]:
Index(['Rank', 'Genre', 'Description', 'Director', 'Actors', 'Year',
       'Runtime (Minutes)', 'Rating', 'Votes', 'Revenue (Millions)',
       'Metascore'],
      dtype='object')

I nomi delle colonne possono essere modificati sia con il comando .rename(), che con l'accesso diretto:

In [53]:
movies_df.rename(columns={
        'Runtime (Minutes)': 'Runtime', 
        'Revenue (Millions)': 'Revenue_millions'
    }, inplace=True)


movies_df.columns
Out[53]:
Index(['Rank', 'Genre', 'Description', 'Director', 'Actors', 'Year', 'Runtime',
       'Rating', 'Votes', 'Revenue_millions', 'Metascore'],
      dtype='object')
In [55]:
movies_df.columns = ['rank', 'genre', 'description', 'director', 'actors', 'year', 'runtime', 
                     'rating', 'votes', 'revenue_millions', 'metascore']


movies_df.columns
Out[55]:
Index(['rank', 'genre', 'description', 'director', 'actors', 'year', 'runtime',
       'rating', 'votes', 'revenue_millions', 'metascore'],
      dtype='object')
In [56]:
movies_df.columns = [col.lower() for col in movies_df]

movies_df.columns
Out[56]:
Index(['rank', 'genre', 'description', 'director', 'actors', 'year', 'runtime',
       'rating', 'votes', 'revenue_millions', 'metascore'],
      dtype='object')

Abbiamo a disposizione anche il comando isnull(), che restituisce un nuovo DataFrame in cui tutti i campi sono True se erano vuoti e False se invece erano pieni. Facendo la somma per colonne (con sum()) possiamo vedere quanti campi sono vuoti all'inizio.

In [61]:
movies_df.isnull().head()
Out[61]:
rank genre description director actors year runtime rating votes revenue_millions metascore
Title
Guardians of the Galaxy False False False False False False False False False False False
Prometheus False False False False False False False False False False False
Split False False False False False False False False False False False
Sing False False False False False False False False False False False
Suicide Squad False False False False False False False False False False False
In [62]:
movies_df.isnull().sum()
Out[62]:
rank                  0
genre                 0
description           0
director              0
actors                0
year                  0
runtime               0
rating                0
votes                 0
revenue_millions    128
metascore            64
dtype: int64

Le righe con valori nulli possono essere cancellati con dropna(), che restituisce un nuovo DF senza modificare l'originale. Questa opzione però è spesso sconsigliata, e va valutata bene a seconda dei dati:

In [63]:
movies_df.dropna().size
Out[63]:
9218

Con il seguente codice, che sarà più chiaro tra poco, possiamo ad esempio riempire i campi vuoti con la media della colonna:

In [65]:
revenue = movies_df['revenue_millions']
revenue_mean = revenue.mean()
revenue.fillna(revenue_mean, inplace=True)
movies_df.isnull().sum()
Out[65]:
rank                 0
genre                0
description          0
director             0
actors               0
year                 0
runtime              0
rating               0
votes                0
revenue_millions     0
metascore           64
dtype: int64

revenue è la nostra colonna, revenue_mean la media dei suoi valori, e fillna() è la funzione che si occupa di riempire i vuoti, il primo parametro è il valore che ci va dentro, il secondo indica di modificare il dataset originale.

Con la funzione describe otteniamo alcuni elementari dati statistici sul DF:

In [66]:
movies_df.describe()
Out[66]:
rank year runtime rating votes revenue_millions metascore
count 1000.000000 1000.000000 1000.000000 1000.000000 1.000000e+03 1000.000000 936.000000
mean 500.500000 2012.783000 113.172000 6.723200 1.698083e+05 82.956376 58.985043
std 288.819436 3.205962 18.810908 0.945429 1.887626e+05 96.412043 17.194757
min 1.000000 2006.000000 66.000000 1.900000 6.100000e+01 0.000000 11.000000
25% 250.750000 2010.000000 100.000000 6.200000 3.630900e+04 17.442500 47.000000
50% 500.500000 2014.000000 111.000000 6.800000 1.107990e+05 60.375000 59.500000
75% 750.250000 2016.000000 123.000000 7.400000 2.399098e+05 99.177500 72.000000
max 1000.000000 2016.000000 191.000000 9.000000 1.791916e+06 936.630000 100.000000

Possiamo applicare questa funzione anche ad una sola colonna:

In [67]:
movies_df['genre'].describe()
Out[67]:
count                        1000
unique                        207
top       Action,Adventure,Sci-Fi
freq                           50
Name: genre, dtype: object

mentre value_counts() ci restituisce quante volte compaiono i più frequenti nomi in quella colonna.

In [68]:
movies_df['genre'].value_counts().head(10)
Out[68]:
Action,Adventure,Sci-Fi       50
Drama                         48
Comedy,Drama,Romance          35
Comedy                        32
Drama,Romance                 31
Animation,Adventure,Comedy    27
Comedy,Drama                  27
Action,Adventure,Fantasy      27
Comedy,Romance                26
Crime,Drama,Thriller          24
Name: genre, dtype: int64

Un altro interessante metodo è .corr(), che restituisce la correlazione incrociata tra variabili numeriche;

In [69]:
movies_df.corr()
Out[69]:
rank year runtime rating votes revenue_millions metascore
rank 1.000000 -0.261605 -0.221739 -0.219555 -0.283876 -0.252996 -0.191869
year -0.261605 1.000000 -0.164900 -0.211219 -0.411904 -0.117562 -0.079305
runtime -0.221739 -0.164900 1.000000 0.392214 0.407062 0.247834 0.211978
rating -0.219555 -0.211219 0.392214 1.000000 0.511537 0.189527 0.631897
votes -0.283876 -0.411904 0.407062 0.511537 1.000000 0.607941 0.325684
revenue_millions -0.252996 -0.117562 0.247834 0.189527 0.607941 1.000000 0.133328
metascore -0.191869 -0.079305 0.211978 0.631897 0.325684 0.133328 1.000000

Per approfondire questi aspetti potete andare al link Essential Statistics for Data Science.

Estrazione e selezione dei dati

Per colonna

In [125]:
genre_col = movies_df['genre']

type(genre_col)
Out[125]:
pandas.core.series.Series

Possiamo accedere ad una colonna, come abbiamo già visto, indicando il suo nome tra parentesi quadre dopo il nome del DF. Questo restituisce una Series. Se invece di un nome usiamo una lista otteniamo un sotto-dataframe con solo le colonne indicate:

In [70]:
subset = movies_df[['genre', 'rating']]

subset.head()
Out[70]:
genre rating
Title
Guardians of the Galaxy Action,Adventure,Sci-Fi 8.1
Prometheus Adventure,Mystery,Sci-Fi 7.0
Split Horror,Thriller 7.3
Sing Animation,Comedy,Family 7.2
Suicide Squad Action,Adventure,Fantasy 6.2
In [71]:
genre_col = movies_df[['genre']]

type(genre_col)
Out[71]:
pandas.core.frame.DataFrame

Ovviamente possiamo usare una lista di un elemento per ottenere un dataframe di una sola colonna.

Per righe

Per le righe abbiamo due opzioni:

  • .loc - estrae la riga con l'indice richiesto
  • .iloc- estrae la riga con l'indice numerico richiesto
In [72]:
prom = movies_df.loc["Prometheus"]

prom
Out[72]:
rank                                                                2
genre                                        Adventure,Mystery,Sci-Fi
description         Following clues to the origin of mankind, a te...
director                                                 Ridley Scott
actors              Noomi Rapace, Logan Marshall-Green, Michael Fa...
year                                                             2012
runtime                                                           124
rating                                                              7
votes                                                          485820
revenue_millions                                               126.46
metascore                                                          65
Name: Prometheus, dtype: object
In [74]:
prom = movies_df.iloc[1]
prom
Out[74]:
rank                                                                2
genre                                        Adventure,Mystery,Sci-Fi
description         Following clues to the origin of mankind, a te...
director                                                 Ridley Scott
actors              Noomi Rapace, Logan Marshall-Green, Michael Fa...
year                                                             2012
runtime                                                           124
rating                                                              7
votes                                                          485820
revenue_millions                                               126.46
metascore                                                          65
Name: Prometheus, dtype: object

loc e iloc si comportano come le liste per quanto riguarda lo slicing:

In [75]:
movie_subset = movies_df.loc['Prometheus':'Sing']

movie_subset = movies_df.iloc[1:4]

movie_subset
Out[75]:
rank genre description director actors year runtime rating votes revenue_millions metascore
Title
Prometheus 2 Adventure,Mystery,Sci-Fi Following clues to the origin of mankind, a te... Ridley Scott Noomi Rapace, Logan Marshall-Green, Michael Fa... 2012 124 7.0 485820 126.46 65.0
Split 3 Horror,Thriller Three girls are kidnapped by a man with a diag... M. Night Shyamalan James McAvoy, Anya Taylor-Joy, Haley Lu Richar... 2016 117 7.3 157606 138.12 62.0
Sing 4 Animation,Comedy,Family In a city of humanoid animals, a hustling thea... Christophe Lourdelet Matthew McConaughey,Reese Witherspoon, Seth Ma... 2016 108 7.2 60545 270.32 59.0

Selezione Condizionale

Una sintassi un po' strana ma fondamentale ci permette anche di selezionare righe in base ad una condizione. Applicando un'operazione booleana ad un df otteniamo un nuovo df con True al posto delle righe che la soddisfano, False nelle altre (come con isnull()).

In [76]:
condition = (movies_df['director'] == "Ridley Scott")

condition.head()
Out[76]:
Title
Guardians of the Galaxy    False
Prometheus                  True
Split                      False
Sing                       False
Suicide Squad              False
Name: director, dtype: bool

Se passiamo questo 'DataFrame Booleano' al posto di un indice, otteniamo un df filtrato dalla nostra condizione:

In [80]:
movies_df[movies_df['rating'] >= 8.6].head(3)
Out[80]:
rank genre description director actors year runtime rating votes revenue_millions metascore
Title
Interstellar 37 Adventure,Drama,Sci-Fi A team of explorers travel through a wormhole ... Christopher Nolan Matthew McConaughey, Anne Hathaway, Jessica Ch... 2014 169 8.6 1047747 187.99 74.0
The Dark Knight 55 Action,Crime,Drama When the menace known as the Joker wreaks havo... Christopher Nolan Christian Bale, Heath Ledger, Aaron Eckhart,Mi... 2008 152 9.0 1791916 533.32 82.0
Inception 81 Action,Adventure,Sci-Fi A thief, who steals corporate secrets through ... Christopher Nolan Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen... 2010 148 8.8 1583625 292.57 74.0

In questo caso però, le congiunzioni or e and sono sostituite da | e &:

In [82]:
movies_df[(movies_df['director'] == 'Christopher Nolan') | (movies_df['director'] == 'Ridley Scott')].head()
Out[82]:
rank genre description director actors year runtime rating votes revenue_millions metascore
Title
Prometheus 2 Adventure,Mystery,Sci-Fi Following clues to the origin of mankind, a te... Ridley Scott Noomi Rapace, Logan Marshall-Green, Michael Fa... 2012 124 7.0 485820 126.46 65.0
Interstellar 37 Adventure,Drama,Sci-Fi A team of explorers travel through a wormhole ... Christopher Nolan Matthew McConaughey, Anne Hathaway, Jessica Ch... 2014 169 8.6 1047747 187.99 74.0
The Dark Knight 55 Action,Crime,Drama When the menace known as the Joker wreaks havo... Christopher Nolan Christian Bale, Heath Ledger, Aaron Eckhart,Mi... 2008 152 9.0 1791916 533.32 82.0
The Prestige 65 Drama,Mystery,Sci-Fi Two stage magicians engage in competitive one-... Christopher Nolan Christian Bale, Hugh Jackman, Scarlett Johanss... 2006 130 8.5 913152 53.08 66.0
Inception 81 Action,Adventure,Sci-Fi A thief, who steals corporate secrets through ... Christopher Nolan Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen... 2010 148 8.8 1583625 292.57 74.0

mentre la condizione in diventa isin()

In [83]:
movies_df[movies_df['director'].isin(['Christopher Nolan', 'Ridley Scott'])].head()
Out[83]:
rank genre description director actors year runtime rating votes revenue_millions metascore
Title
Prometheus 2 Adventure,Mystery,Sci-Fi Following clues to the origin of mankind, a te... Ridley Scott Noomi Rapace, Logan Marshall-Green, Michael Fa... 2012 124 7.0 485820 126.46 65.0
Interstellar 37 Adventure,Drama,Sci-Fi A team of explorers travel through a wormhole ... Christopher Nolan Matthew McConaughey, Anne Hathaway, Jessica Ch... 2014 169 8.6 1047747 187.99 74.0
The Dark Knight 55 Action,Crime,Drama When the menace known as the Joker wreaks havo... Christopher Nolan Christian Bale, Heath Ledger, Aaron Eckhart,Mi... 2008 152 9.0 1791916 533.32 82.0
The Prestige 65 Drama,Mystery,Sci-Fi Two stage magicians engage in competitive one-... Christopher Nolan Christian Bale, Hugh Jackman, Scarlett Johanss... 2006 130 8.5 913152 53.08 66.0
Inception 81 Action,Adventure,Sci-Fi A thief, who steals corporate secrets through ... Christopher Nolan Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen... 2010 148 8.8 1583625 292.57 74.0

Possiamo poi applicare una funzione ad una determinata colonna (ad esempio per crearne una nuova), con la sintassi apply():

In [84]:
movies_df["rating_category"] = movies_df["rating"].apply(lambda x: 'good' if x >= 8.0 else 'bad')

movies_df.head(2)
Out[84]:
rank genre description director actors year runtime rating votes revenue_millions metascore rating_category
Title
Guardians of the Galaxy 1 Action,Adventure,Sci-Fi A group of intergalactic criminals are forced ... James Gunn Chris Pratt, Vin Diesel, Bradley Cooper, Zoe S... 2014 121 8.1 757074 333.13 76.0 good
Prometheus 2 Adventure,Mystery,Sci-Fi Following clues to the origin of mankind, a te... Ridley Scott Noomi Rapace, Logan Marshall-Green, Michael Fa... 2012 124 7.0 485820 126.46 65.0 bad

In questo caso creiamo la nuova riga "rating category", che vale good se il film ha più di 8 come voto, e bad altrimenti.

Approfondimenti

In questa introduzione ci siamo occupati degli aspetti fondamentali delle Pandas. Questa libreria è alla base di quasi tutta la data science moderna, e contiene diversi potenti strumenti. Per chi volesse approfondire, ci sono molti validi tutorial sul sito ufficiale. Per vedere invece cosa la gente seria fa con pandas e altre cose, fate un salto sul sito Kaggle: troverete notebook di data science e machine learning di alto livello (ovviamente non siamo ancora in grado di capire quasi tutto quello che c'è, però vi può dare un'idea delle potenzialità di questi strumenti. A questo link trovate una guida specifica su come rimpiazzare excel con le pandas, per chi fosse particolarmente abituato ad usarlo.

Un altro aspetto delle pandas, che apprezzeremo meglio nelle prossime settimane, è che questa libreria è costruita per integrarsi perfettamente con i principali strumenti di analisi dati presenti nello sci-kit di python (pyplot, sklearn...)

Esercizi

Provate a:

  • Selezionare solo i film prodotti tra il 2010 e il 2015 con un voto superiore all'8
  • Creare una nuova colonna che indichi un film come 'lungo' se dura più di due ore, 'corto' se dura meno