questo notebook è utile come riferimento -cassetta degli attrezzi- per le attività formative del DataLifeLab e per le esercitazioni in classe del corso di Open Notebook Science del dell'Università di Firenze
variabile = "qualsiasi cosa in python è un oggetto"
variabile
'qualsiasi cosa in python è un oggetto'
print(variabile)
qualsiasi cosa in python è un oggetto
type(variabile)
str
# interi
1
1
# numeri con virgola (float)
1.4
1.4
# operazioni
1 + 1
2
1 * 3
3
1 / 2
0.5
2 ** 4
16
# modulo o resto
4 % 2
0
5 % 2
1
(2 + 3) * (5 + 5)
50
'testo compreso fra apostrofi'
'testo compreso fra apostrofi'
"virgolette"
'virgolette'
" testo che contiene apostrofi ' "
" testo che contiene apostrofi ' "
[1,2,3]
[1, 2, 3]
['ciao',1,[1,2]]
['ciao', 1, [1, 2]]
la_mia_lista = ['a','b','c']
la_mia_lista.append('d')
la_mia_lista
['a', 'b', 'c', 'd']
la_mia_lista[0]
'a'
la_mia_lista[1]
'b'
la_mia_lista[1:]
['b', 'c', 'd']
la_mia_lista[:1]
['a']
la_mia_lista[0] = "modifico l'elemento zero"
la_mia_lista
["modifico l'elemento zero", 'b', 'c', 'd']
lista_nested = [1,2,3,[4,5,['secondo livello del terzo elemento']]]
lista_nested
[1, 2, 3, [4, 5, ['secondo livello del terzo elemento']]]
lista_nested[3]
[4, 5, ['secondo livello del terzo elemento']]
lista_nested[3][2]
['secondo livello del terzo elemento']
d = {'chiave1':'elemento1','chiave2':'elemento2'}
d
{'chiave1': 'elemento1', 'chiave2': 'elemento2'}
d['chiave1']
'elemento1'
d.keys()
dict_keys(['chiave1', 'chiave2'])
True
True
False
False
## Turple
t = (1,2,3)
t[0]
1
# t[0] = 'NEW'
# TypeError: 'tuple' object does not support item assignment
## Sets
{1,2,3}
{1, 2, 3}
{1,2,3,1,2,1,2,3,3,3,3,2,2,2,1,1,2}
{1, 2, 3}
1 > 2
False
1 < 2
True
1 >= 1
True
1 <= 4
True
1 == 1
True
'hi' == 'bye'
False
(1 > 2) and (2 < 3)
False
(1 > 2) or (2 < 3)
True
(1 == 2) or (2 == 3) or (4 == 4)
True
#Gestione eccezioni
if 1 < 2:
print('bene!')
bene!
if 1 < 2:
print('bene')
else:
print('altrimenti')
bene
if 1 > 2:
print('bene')
else:
print('altrimenti')
altrimenti
if 1 == 2:
print('primo')
elif 3 == 3:
print('intermedio')
else:
print('ultimo')
intermedio
try:
print("10")
except:
print("fai qualcosa in caso di errore")
10
#print(int("mamma"))
#ValueError: invalid literal for int() with base 10: 'mamma'
try:
print(int("mamma"))
except:
print("fai qualcosa in caso di errore")
fai qualcosa in caso di errore
seq = [1,2,3,4,5]
for item in seq:
print(item)
1 2 3 4 5
for item in seq:
print('Bene!')
Bene! Bene! Bene! Bene! Bene!
for nome_a_caso in seq:
print(nome_a_caso+nome_a_caso)
2 4 6 8 10
## Ciclo while
i = 1
while i < 10:
print('i is: {}'.format(i))
i = i+1
i is: 1 i is: 2 i is: 3 i is: 4 i is: 5 i is: 6 i is: 7 i is: 8 i is: 9
## range()
range(10)
range(0, 10)
for i in range(5):
print(i)
0 1 2 3 4
list(range(5))
[0, 1, 2, 3, 4]
st = 'Marco saluta il Mondo'
# lista di metodi e attributi
dir(st)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
st.lower()
'marco saluta il mondo'
st.upper()
'MARCO SALUTA IL MONDO'
st.split()
['Marco', 'saluta', 'il', 'Mondo']
post = 'si parla di scienza! #DataLifeLab'
post.split('#')
['si parla di scienza! ', 'DataLifeLab']
post.split('#')[1]
'DataLifeLab'
d
{'chiave1': 'elemento1', 'chiave2': 'elemento2'}
d.keys()
dict_keys(['chiave1', 'chiave2'])
d.items()
dict_items([('chiave1', 'elemento1'), ('chiave2', 'elemento2')])
'x' in [1,2,3]
False
'x' in ['x','y','z']
True
# aprire un file di testo in sola lettura
# il file si trova nella cartella Esercizio_1 all'interno della cartella esercizi e il nome del file è albert.txt
with open("./esercizi/Esercizio_1/albert.txt" , "r") as miofile:
contenuto_mio_file = miofile.read()
print(contenuto_mio_file)
## deve essere raccolta ogni informazione ed inserita in un dizionario python Albert Einstein è stato un fisico e filosofo tedesco naturalizzato svizzero e statunitense. Oltre a essere uno dei più celebri fisici della storia della scienza, che mutò in maniera radicale il paradigma ... Wikipedia Nascita: 14 marzo 1879, Ulma, Germania Decesso: 18 aprile 1955, Princeton, New Jersey, Stati Uniti Altezza: 1,75 m Figli: Eduard Einstein, Hans Albert Einstein, Lieserl Einstein Coniuge: Elsa Einstein (s. 1919–1936), Mileva Marić (s. 1903–1919)
# aprire un file di testo in scrittura
# il file si trova nella cartella Esercizio_2 all'interno della cartella esercizi e il nome del file è Luigino.txt
contenuto = '''
Luigino è stato uno dei più grandi artisti lirici della storia di San Marino
Nascita: 14 marzo 1945, San Marino, San Marino.
Decesso: 18 aprile 2015, San Marino, San Marino.
Altezza: 1,75 m
Peso: 205 KG
'''
with open("./esercizi/Esercizio_2/Luigino.txt", "w") as miofile:
contenuto_mio_file = miofile.write(contenuto)
def mia_funzione(parametro='default'):
"""
documentazione della funzione va qui.
"""
return(parametro)
mia_funzione
<function __main__.mia_funzione(parametro='default')>
mia_funzione()
'default'
mia_funzione("marco")
'marco'
def area_triangolo(base, altezza):
return base * altezza / 2
area_triangolo(10,15)
75.0
## Espressioni Lambda
def la_variabile_per_2(var):
return var*2
la_variabile_per_2(10)
20
a = lambda var: var*2
a(10)
20
import numpy as np
import pandas as pd
#costruzione di un dataframe
df = pd.DataFrame({'col1':[1,2,3,4],'col2':[444,800,1200,444],'col3':['abc','abc','ghi','xyz']})
df
col1 | col2 | col3 | |
---|---|---|---|
0 | 1 | 444 | abc |
1 | 2 | 800 | abc |
2 | 3 | 1200 | ghi |
3 | 4 | 444 | xyz |
## filtrare i dati con **loc**
# filtrare passando i valori di indice e colonna
df.loc[3,"col3"]
'xyz'
df.loc[2,["col2", "col3"]]
col2 1200 col3 ghi Name: 2, dtype: object
df.loc[[2,1],["col2", "col3"]]
col2 | col3 | |
---|---|---|
2 | 1200 | ghi |
1 | 800 | abc |
(df['col2']==444) # filtrare passando un vettore boleano
0 True 1 False 2 False 3 True Name: col2, dtype: bool
df.loc[(df['col1']>3) & (df['col2']==444), :]
col1 | col2 | col3 | |
---|---|---|---|
3 | 4 | 444 | xyz |
#oppure
filtro1 = df['col1']>2
filtro2 = df['col2']==444
df.loc[filtro1 & filtro2, :]
col1 | col2 | col3 | |
---|---|---|---|
3 | 4 | 444 | xyz |
df.loc[(df['col1']>2) | (df['col2']==444), :]
col1 | col2 | col3 | |
---|---|---|---|
0 | 1 | 444 | abc |
2 | 3 | 1200 | ghi |
3 | 4 | 444 | xyz |
# assegnazione di valori
#assegnazione ad un intera riga
df.loc[(df['col1']>2) & (df['col2']==444), :] = 10
df
col1 | col2 | col3 | |
---|---|---|---|
0 | 1 | 444 | abc |
1 | 2 | 800 | abc |
2 | 3 | 1200 | ghi |
3 | 10 | 10 | 10 |
#filtro tramite isin
#si passa una lista di valori su cui effettuare il filtro
df[df["col3"].isin(["ghi", "abc"])]
col1 | col2 | col3 | |
---|---|---|---|
0 | 1 | 444 | abc |
1 | 2 | 800 | abc |
2 | 3 | 1200 | ghi |
#certe volte può essere utile filtrare "stile battaglia navale", passando per il numero di riga e di colonna
# questo si può fare con iloc
df.iloc[0:1,1:3] #prendo la seconda e terza colonna e la prima riga (indipendentemente dal valore del'indice)
col2 | col3 | |
---|---|---|
0 | 444 | abc |
## Operazioni fra colonne e righe
# creazione di una nuova colonna
nuova_colonna = df["col1"] + df["col2"]
df["nuova_colonna"] = nuova_colonna
df
col1 | col2 | col3 | nuova_colonna | |
---|---|---|---|---|
0 | 1 | 444 | abc | 445 |
1 | 2 | 800 | abc | 802 |
2 | 3 | 1200 | ghi | 1203 |
3 | 10 | 10 | 10 | 20 |
#sommare interi con stringa porta ad errore
#df["col1"] + df["col3"]
#TypeError: unsupported operand type(s) for +: 'int' and 'str'
df[["col1", "col2", "nuova_colonna"]].div(df["nuova_colonna"], axis = 0) * 100
col1 | col2 | nuova_colonna | |
---|---|---|---|
0 | 0.224719 | 99.775281 | 100.0 |
1 | 0.249377 | 99.750623 | 100.0 |
2 | 0.249377 | 99.750623 | 100.0 |
3 | 50.000000 | 50.000000 | 100.0 |
#per approfondire https://pandas.pydata.org/pandas-docs/stable/api.html#id4
altezze = pd.DataFrame({'Nome':["Marco","Luigi","Nino","Ugo", "Marino" ],'Altezza':[175,173,178,182,160]})
pesi = pd.DataFrame({'Nome':["Marco","Luigi","Vittorio","Ugo", "Marino" ],'Peso':[75,70,100,97,50]})
#concatenazione verticale
# https://pandas.pydata.org/pandas-docs/stable/generated/pandas.concat.html
pd.concat([altezze, pesi])
Altezza | Nome | Peso | |
---|---|---|---|
0 | 175.0 | Marco | NaN |
1 | 173.0 | Luigi | NaN |
2 | 178.0 | Nino | NaN |
3 | 182.0 | Ugo | NaN |
4 | 160.0 | Marino | NaN |
0 | NaN | Marco | 75.0 |
1 | NaN | Luigi | 70.0 |
2 | NaN | Vittorio | 100.0 |
3 | NaN | Ugo | 97.0 |
4 | NaN | Marino | 50.0 |
#concatenazione orizzonate
pd.concat([altezze, pesi], axis = 1)
## i dati sono disallineati
Altezza | Nome | Nome | Peso | |
---|---|---|---|---|
0 | 175 | Marco | Marco | 75 |
1 | 173 | Luigi | Luigi | 70 |
2 | 178 | Nino | Vittorio | 100 |
3 | 182 | Ugo | Ugo | 97 |
4 | 160 | Marino | Marino | 50 |
# join dei dati
# https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.merge.html
pd.merge(altezze, pesi, how = "outer", left_on = "Nome", right_on = "Nome")
Altezza | Nome | Peso | |
---|---|---|---|
0 | 175.0 | Marco | 75.0 |
1 | 173.0 | Luigi | 70.0 |
2 | 178.0 | Nino | NaN |
3 | 182.0 | Ugo | 97.0 |
4 | 160.0 | Marino | 50.0 |
5 | NaN | Vittorio | 100.0 |
# aggiunto Gabriele e la sua altezza
altezze = altezze.append([{"Nome": "Gabriele", "Altezza": 213}], )
pd.merge(altezze, pesi, how = "right", left_on = "Nome", right_on = "Nome")
Altezza | Nome | Peso | |
---|---|---|---|
0 | 175.0 | Marco | 75 |
1 | 173.0 | Luigi | 70 |
2 | 182.0 | Ugo | 97 |
3 | 160.0 | Marino | 50 |
4 | NaN | Vittorio | 100 |
pd.merge(altezze, pesi, how = "left", left_on = "Nome", right_on = "Nome")
Altezza | Nome | Peso | |
---|---|---|---|
0 | 175 | Marco | 75.0 |
1 | 173 | Luigi | 70.0 |
2 | 178 | Nino | NaN |
3 | 182 | Ugo | 97.0 |
4 | 160 | Marino | 50.0 |
5 | 213 | Gabriele | NaN |
# da formato wide a long
# https://pandas.pydata.org/pandas-docs/stable/generated/pandas.melt.html
wide = pd.merge(altezze, pesi, how = "left", left_on = "Nome", right_on = "Nome")
#calcolo un indice di massa corporea
wide["Imc"] = wide["Peso"] / (wide["Altezza"] / 100) ** 2
wide
Altezza | Nome | Peso | Imc | |
---|---|---|---|---|
0 | 175 | Marco | 75.0 | 24.489796 |
1 | 173 | Luigi | 70.0 | 23.388687 |
2 | 178 | Nino | NaN | NaN |
3 | 182 | Ugo | 97.0 | 29.283903 |
4 | 160 | Marino | 50.0 | 19.531250 |
5 | 213 | Gabriele | NaN | NaN |
long = pd.melt(wide, id_vars = "Nome",
value_vars=['Altezza', 'Peso', "Imc"],
var_name='Variabile',
value_name= "Valori")
long
Nome | Variabile | Valori | |
---|---|---|---|
0 | Marco | Altezza | 175.000000 |
1 | Luigi | Altezza | 173.000000 |
2 | Nino | Altezza | 178.000000 |
3 | Ugo | Altezza | 182.000000 |
4 | Marino | Altezza | 160.000000 |
5 | Gabriele | Altezza | 213.000000 |
6 | Marco | Peso | 75.000000 |
7 | Luigi | Peso | 70.000000 |
8 | Nino | Peso | NaN |
9 | Ugo | Peso | 97.000000 |
10 | Marino | Peso | 50.000000 |
11 | Gabriele | Peso | NaN |
12 | Marco | Imc | 24.489796 |
13 | Luigi | Imc | 23.388687 |
14 | Nino | Imc | NaN |
15 | Ugo | Imc | 29.283903 |
16 | Marino | Imc | 19.531250 |
17 | Gabriele | Imc | NaN |
# tabella pivot
# https://pandas.pydata.org/pandas-docs/stable/generated/pandas.pivot_table.html
pd.pivot_table(long, values = "Valori",
index = "Variabile",
aggfunc = np.mean)
Valori | |
---|---|
Variabile | |
Altezza | 180.166667 |
Imc | 24.173409 |
Peso | 73.000000 |
#operazioni di riga e di cella
wide.loc[:, ["Altezza", "Peso"]].apply(np.mean, axis = 0) # asse 0, vuol dire esegue l'operazione per colonna, asse 1 vuol dire per riga
Altezza 180.166667 Peso 73.000000 dtype: float64
# operazione lambda
def recode_altezza(altezza):
if altezza >= 185:
return "Alto"
elif altezza < 185 and altezza > 165:
return "Medio"
else:
return "Basso"
wide["Altezza"].apply(recode_altezza)
0 Medio 1 Medio 2 Medio 3 Medio 4 Basso 5 Alto Name: Altezza, dtype: object
wide.loc[:, ["Altezza", "Peso"]].applymap(lambda cella: str(cella) + "_ciao")
Altezza | Peso | |
---|---|---|
0 | 175_ciao | 75.0_ciao |
1 | 173_ciao | 70.0_ciao |
2 | 178_ciao | nan_ciao |
3 | 182_ciao | 97.0_ciao |
4 | 160_ciao | 50.0_ciao |
5 | 213_ciao | nan_ciao |
#Da long a wide
long.pivot(index='Nome', columns='Variabile', values='Valori')
Variabile | Altezza | Imc | Peso |
---|---|---|---|
Nome | |||
Gabriele | 213.0 | NaN | NaN |
Luigi | 173.0 | 23.388687 | 70.0 |
Marco | 175.0 | 24.489796 | 75.0 |
Marino | 160.0 | 19.531250 | 50.0 |
Nino | 178.0 | NaN | NaN |
Ugo | 182.0 | 29.283903 | 97.0 |
#Creare un file excel
long.to_excel("excel_di_exempio.xlsx")
#Leggere un file excel
pd.read_excel("excel_di_exempio.xlsx")
Nome | Variabile | Valori | |
---|---|---|---|
0 | Marco | Altezza | 175.000000 |
1 | Luigi | Altezza | 173.000000 |
2 | Nino | Altezza | 178.000000 |
3 | Ugo | Altezza | 182.000000 |
4 | Marino | Altezza | 160.000000 |
5 | Gabriele | Altezza | 213.000000 |
6 | Marco | Peso | 75.000000 |
7 | Luigi | Peso | 70.000000 |
8 | Nino | Peso | NaN |
9 | Ugo | Peso | 97.000000 |
10 | Marino | Peso | 50.000000 |
11 | Gabriele | Peso | NaN |
12 | Marco | Imc | 24.489796 |
13 | Luigi | Imc | 23.388687 |
14 | Nino | Imc | NaN |
15 | Ugo | Imc | 29.283903 |
16 | Marino | Imc | 19.531250 |
17 | Gabriele | Imc | NaN |
# Creare un file excel con più tab
writer = pd.ExcelWriter('excel_di_esempio2.xlsx')
long.loc[long["Variabile"] == "Altezza"].to_excel(writer,'Altezza')
long.loc[long["Variabile"] == "Peso"].to_excel(writer,'Peso')
long.loc[long["Variabile"] == "Imc"].to_excel(writer,'Imc')
writer.save()
# Leggere un file excel con più tab
tab_multiple = pd.read_excel('excel_di_esempio2.xlsx', sheetname = None)
tab_multiple
OrderedDict([('Altezza', Nome Variabile Valori 0 Marco Altezza 175 1 Luigi Altezza 173 2 Nino Altezza 178 3 Ugo Altezza 182 4 Marino Altezza 160 5 Gabriele Altezza 213), ('Peso', Nome Variabile Valori 6 Marco Peso 75.0 7 Luigi Peso 70.0 8 Nino Peso NaN 9 Ugo Peso 97.0 10 Marino Peso 50.0 11 Gabriele Peso NaN), ('Imc', Nome Variabile Valori 12 Marco Imc 24.489796 13 Luigi Imc 23.388687 14 Nino Imc NaN 15 Ugo Imc 29.283903 16 Marino Imc 19.531250 17 Gabriele Imc NaN)])
# accedere ad una tab
tab_multiple["Altezza"]
Nome | Variabile | Valori | |
---|---|---|---|
0 | Marco | Altezza | 175 |
1 | Luigi | Altezza | 173 |
2 | Nino | Altezza | 178 |
3 | Ugo | Altezza | 182 |
4 | Marino | Altezza | 160 |
5 | Gabriele | Altezza | 213 |
wide.describe()
Altezza | Peso | Imc | |
---|---|---|---|
count | 6.000000 | 4.000000 | 4.000000 |
mean | 180.166667 | 73.000000 | 24.173409 |
std | 17.724747 | 19.304576 | 4.015913 |
min | 160.000000 | 50.000000 | 19.531250 |
25% | 173.500000 | 65.000000 | 22.424327 |
50% | 176.500000 | 72.500000 | 23.939241 |
75% | 181.000000 | 80.500000 | 25.688323 |
max | 213.000000 | 97.000000 | 29.283903 |
# media
wide["Altezza"].mean()
180.16666666666666
# deviazione standard # indice di dispersione
wide["Altezza"].std()
17.72474729486056
# correlazione
wide.corr()
Altezza | Peso | Imc | |
---|---|---|---|
Altezza | 1.000000 | 0.975857 | 0.966893 |
Peso | 0.975857 | 1.000000 | 0.999277 |
Imc | 0.966893 | 0.999277 | 1.000000 |
# iterazione con lambda per eseguire operazioni complesse fra colonne
wide.apply(lambda x: (x['Altezza'] / x["Peso"]) , axis=1)
0 2.333333 1 2.471429 2 NaN 3 1.876289 4 3.200000 5 NaN dtype: float64
# iterazione classica sui dati di un dataframe di pandas
#Può essere molto utile quando si deve eseguire calcoli che è difficile rappresentare in lambda e si vuole adoperare (difetto principale: richiede maggiore tempo di esecuzione)
for i, v in wide.items(): # qui prendo indice e valori
print(i, v)
Altezza 0 175 1 173 2 178 3 182 4 160 5 213 Name: Altezza, dtype: int64 Nome 0 Marco 1 Luigi 2 Nino 3 Ugo 4 Marino 5 Gabriele Name: Nome, dtype: object Peso 0 75.0 1 70.0 2 NaN 3 97.0 4 50.0 5 NaN Name: Peso, dtype: float64 Imc 0 24.489796 1 23.388687 2 NaN 3 29.283903 4 19.531250 5 NaN Name: Imc, dtype: float64
# iterazione classica sui dati di una serie di pandas
for i, v in wide["Altezza"].items(): # qui prendo indice e valori
print(i, v)
0 175 1 173 2 178 3 182 4 160 5 213
serie_dati = {"Italia": {2010: 35, 2011: 30, 2012: 25}, "Spagna": {2010: 25, 2011: 27, 2012: 34}}
df_serie_dati = pd.DataFrame(serie_dati)
df_serie_dati
Italia | Spagna | |
---|---|---|
2010 | 35 | 25 |
2011 | 30 | 27 |
2012 | 25 | 34 |
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
df_serie_dati.plot(kind = "line", grid = True, rot=45, figsize = (10,5))
<matplotlib.axes._subplots.AxesSubplot at 0x7fba1c796fd0>
df_serie_dati.index = pd.to_datetime(df_serie_dati.index, format="%Y")
df_serie_dati
Italia | Spagna | |
---|---|---|
2010-01-01 | 35 | 25 |
2011-01-01 | 30 | 27 |
2012-01-01 | 25 | 34 |
df_serie_dati.plot(kind = "line", grid = True, rot=45, figsize = (10,5))
<matplotlib.axes._subplots.AxesSubplot at 0x7fba1483ee10>
Altezza = tab_multiple["Altezza"]
Altezza
Nome | Variabile | Valori | |
---|---|---|---|
0 | Marco | Altezza | 175 |
1 | Luigi | Altezza | 173 |
2 | Nino | Altezza | 178 |
3 | Ugo | Altezza | 182 |
4 | Marino | Altezza | 160 |
5 | Gabriele | Altezza | 213 |
Altezza.plot(y= "Valori", kind = "box", grid = True, rot=45, figsize = (10,5))
<matplotlib.axes._subplots.AxesSubplot at 0x7fba147cd860>
Altezza.plot(x="Nome", y= "Valori", kind = "bar", grid = True, rot=45, figsize = (10,5))
<matplotlib.axes._subplots.AxesSubplot at 0x7fba147b4518>
ax = Altezza.plot(x="Nome", y= "Valori", kind = "bar", grid = True, rot=45, figsize = (10,5))
ax.set_ylabel('Infant mort. rate')
ax.set_xlabel('Country')
for riga in range(Altezza.shape[0]):
ax.annotate(Altezza["Valori"][riga],
(Altezza.index[riga], Altezza["Valori"][riga]),
xytext=(15, 15),
textcoords='offset points',
arrowprops=dict(arrowstyle='-|>'))
plt.show()