Si no funciona el botó podeu copiar el següent enllaç
2 - La llibreria Pandas
Pandas
Pandas és la llibreria per excel·lència per a l’anàlisi de dades del llenguatge Python. El seu nom prové de “panel data” (terme economètric). Inspirada en les funcionalitats de fulls de càlcul i R, però amb el potencial d’aquest llenguatge de propòsit general.
Pandas inclou totes les funcionalitats necessàries per al procés d’anàlisi de dades: càrrega, filtrat, tractament, síntesi, agrupament, emmagatzematge i visualització. A més, s’integra amb la resta de llibreries de càlcul numèric com Numpy, visualització amb Matplotlib, aprenentatge automàtic amb scikit-learn, etc.
L’objectiu d’aquest curs introductori és adquirir capacitats bàsiques d’anàlisis de dades amb Pandas.
Referències:
Nota: Pandas és una llibreria que ja es troba instal·lada a Google Colab.
[4]:
import pandas as pd
Càrrega de dades i estructures bàsiques de Pandas.
A Pandas hi ha dos tipus de variables: dataframes i series.
A continuació llegirem el nostre primer dataframe, ho farem a partir d’un fitxer de dades que presenta una estructura tabular. Aquests fitxers amb extensió CSV (Comma Separated Value) són un dels formats més emprats.
[5]:
df_who = pd.read_csv("data/WHO.csv") #dataframe
print(type(df_who))
<class 'pandas.core.frame.DataFrame'>
[6]:
df_who
[6]:
Country | CountryID | Continent | Adolescent fertility rate (%) | Adult literacy rate (%) | Gross national income per capita (PPP international $) | Net primary school enrolment ratio female (%) | Net primary school enrolment ratio male (%) | Population (in thousands) total | Population annual growth rate (%) | ... | Total_CO2_emissions | Total_income | Total_reserves | Trade_balance_goods_and_services | Under_five_mortality_from_CME | Under_five_mortality_from_IHME | Under_five_mortality_rate | Urban_population | Urban_population_growth | Urban_population_pct_of_total | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Afghanistan | 1 | 1 | 151.0 | 28.0 | NaN | NaN | NaN | 26088.0 | 4.0 | ... | 692.50 | NaN | NaN | NaN | 257.00 | 231.9 | 257.00 | 5740436.0 | 5.44 | 22.9 |
1 | Albania | 2 | 2 | 27.0 | 98.7 | 6000.0 | 93.0 | 94.0 | 3172.0 | 0.6 | ... | 3499.12 | 4.790000e+09 | 78.14 | -2.040000e+09 | 18.47 | 15.5 | 18.47 | 1431793.9 | 2.21 | 45.4 |
2 | Algeria | 3 | 3 | 6.0 | 69.9 | 5940.0 | 94.0 | 96.0 | 33351.0 | 1.5 | ... | 137535.56 | 6.970000e+10 | 351.36 | 4.700000e+09 | 40.00 | 31.2 | 40.00 | 20800000.0 | 2.61 | 63.3 |
3 | Andorra | 4 | 2 | NaN | NaN | NaN | 83.0 | 83.0 | 74.0 | 1.0 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
4 | Angola | 5 | 3 | 146.0 | 67.4 | 3890.0 | 49.0 | 51.0 | 16557.0 | 2.8 | ... | 8991.46 | 1.490000e+10 | 27.13 | 9.140000e+09 | 164.10 | 242.5 | 164.10 | 8578749.0 | 4.14 | 53.3 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
197 | Vietnam | 198 | 6 | 25.0 | 90.3 | 2310.0 | 91.0 | 96.0 | 86206.0 | 1.4 | ... | 101826.23 | 4.480000e+10 | 47.11 | -1.940000e+09 | 20.20 | 23.4 | 20.20 | 21900000.0 | 2.90 | 26.4 |
198 | West Bank and Gaza | 199 | 1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | 655.86 | 3.780000e+09 | NaN | NaN | 28.00 | 25.8 | 28.00 | 2596216.0 | 3.33 | 71.6 |
199 | Yemen | 200 | 1 | 83.0 | 54.1 | 2090.0 | 65.0 | 85.0 | 21732.0 | 3.0 | ... | 20148.34 | 1.150000e+10 | 114.52 | 8.310000e+08 | 82.40 | 87.9 | 82.40 | 5759120.5 | 4.37 | 27.3 |
200 | Zambia | 201 | 3 | 161.0 | 68.0 | 1140.0 | 94.0 | 90.0 | 11696.0 | 1.9 | ... | 2366.94 | 4.090000e+09 | 10.41 | -4.470000e+08 | 175.30 | 163.8 | 175.30 | 4017411.0 | 1.95 | 35.0 |
201 | Zimbabwe | 202 | 3 | 101.0 | 89.5 | NaN | 88.0 | 87.0 | 13228.0 | 0.8 | ... | 11457.33 | 5.620000e+09 | 3.39 | -1.710000e+08 | 106.50 | 67.0 | 106.50 | 4709965.0 | 1.90 | 35.9 |
202 rows × 358 columns
A continuació veurem diferents maneres d’explorar un dataframe:
[7]:
# Estructura
print(df_who.shape) # files o mostres x columnes
(202, 358)
[8]:
df_who.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 202 entries, 0 to 201
Columns: 358 entries, Country to Urban_population_pct_of_total
dtypes: float64(355), int64(2), object(1)
memory usage: 565.1+ KB
[9]:
df_who.describe()
[9]:
CountryID | Continent | Adolescent fertility rate (%) | Adult literacy rate (%) | Gross national income per capita (PPP international $) | Net primary school enrolment ratio female (%) | Net primary school enrolment ratio male (%) | Population (in thousands) total | Population annual growth rate (%) | Population in urban areas (%) | ... | Total_CO2_emissions | Total_income | Total_reserves | Trade_balance_goods_and_services | Under_five_mortality_from_CME | Under_five_mortality_from_IHME | Under_five_mortality_rate | Urban_population | Urban_population_growth | Urban_population_pct_of_total | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 202.000000 | 202.000000 | 177.000000 | 131.000000 | 178.000000 | 179.000000 | 179.000000 | 1.930000e+02 | 193.000000 | 193.000000 | ... | 1.860000e+02 | 1.780000e+02 | 128.000000 | 1.710000e+02 | 181.000000 | 170.000000 | 181.000000 | 1.880000e+02 | 188.000000 | 188.000000 |
mean | 101.500000 | 3.579208 | 59.457627 | 78.871756 | 11250.112360 | 84.033520 | 85.698324 | 3.409805e+04 | 1.297927 | 54.911917 | ... | 1.483596e+05 | 2.015567e+11 | 57.253516 | 3.424012e+08 | 56.677624 | 54.356471 | 56.677624 | 1.665763e+07 | 2.165851 | 55.195213 |
std | 58.456537 | 1.808263 | 49.105286 | 20.415760 | 12586.753417 | 17.788047 | 15.451212 | 1.304957e+05 | 1.163864 | 23.554182 | ... | 6.133091e+05 | 9.400689e+11 | 138.669298 | 5.943043e+10 | 60.060929 | 61.160556 | 60.060929 | 5.094867e+07 | 1.596628 | 23.742122 |
min | 1.000000 | 1.000000 | 0.000000 | 23.600000 | 260.000000 | 6.000000 | 11.000000 | 2.000000e+00 | -2.500000 | 10.000000 | ... | 2.565000e+01 | 5.190000e+07 | 0.990000 | -7.140000e+11 | 2.900000 | 3.000000 | 2.900000 | 1.545600e+04 | -1.160000 | 10.000000 |
25% | 51.250000 | 2.000000 | 19.000000 | 68.400000 | 2112.500000 | 79.000000 | 79.500000 | 1.340000e+03 | 0.500000 | 36.000000 | ... | 1.672615e+03 | 3.317500e+09 | 16.292500 | -1.210000e+09 | 12.400000 | 8.475000 | 12.400000 | 9.171623e+05 | 1.105000 | 35.650000 |
50% | 101.500000 | 3.000000 | 46.000000 | 86.500000 | 6175.000000 | 90.000000 | 90.000000 | 6.762000e+03 | 1.300000 | 57.000000 | ... | 1.021157e+04 | 1.145000e+10 | 28.515000 | -2.240000e+08 | 29.980000 | 27.600000 | 29.980000 | 3.427661e+06 | 1.945000 | 57.300000 |
75% | 151.750000 | 5.000000 | 91.000000 | 95.300000 | 14502.500000 | 96.000000 | 96.000000 | 2.173200e+04 | 2.100000 | 73.000000 | ... | 6.549217e+04 | 8.680000e+10 | 55.310000 | 1.024000e+09 | 88.700000 | 82.900000 | 88.700000 | 9.837113e+06 | 3.252500 | 72.750000 |
max | 202.000000 | 7.000000 | 199.000000 | 99.800000 | 60870.000000 | 100.000000 | 100.000000 | 1.328474e+06 | 4.300000 | 100.000000 | ... | 5.776432e+06 | 1.100000e+13 | 1334.860000 | 1.390000e+11 | 267.000000 | 253.700000 | 267.000000 | 5.270000e+08 | 7.850000 | 100.000000 |
8 rows × 357 columns
[10]:
# Aquesta funció admet un paràmetre numèric, especifica el nombre de files
# Per defecte és 5
df_who.head()
[10]:
Country | CountryID | Continent | Adolescent fertility rate (%) | Adult literacy rate (%) | Gross national income per capita (PPP international $) | Net primary school enrolment ratio female (%) | Net primary school enrolment ratio male (%) | Population (in thousands) total | Population annual growth rate (%) | ... | Total_CO2_emissions | Total_income | Total_reserves | Trade_balance_goods_and_services | Under_five_mortality_from_CME | Under_five_mortality_from_IHME | Under_five_mortality_rate | Urban_population | Urban_population_growth | Urban_population_pct_of_total | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Afghanistan | 1 | 1 | 151.0 | 28.0 | NaN | NaN | NaN | 26088.0 | 4.0 | ... | 692.50 | NaN | NaN | NaN | 257.00 | 231.9 | 257.00 | 5740436.0 | 5.44 | 22.9 |
1 | Albania | 2 | 2 | 27.0 | 98.7 | 6000.0 | 93.0 | 94.0 | 3172.0 | 0.6 | ... | 3499.12 | 4.790000e+09 | 78.14 | -2.040000e+09 | 18.47 | 15.5 | 18.47 | 1431793.9 | 2.21 | 45.4 |
2 | Algeria | 3 | 3 | 6.0 | 69.9 | 5940.0 | 94.0 | 96.0 | 33351.0 | 1.5 | ... | 137535.56 | 6.970000e+10 | 351.36 | 4.700000e+09 | 40.00 | 31.2 | 40.00 | 20800000.0 | 2.61 | 63.3 |
3 | Andorra | 4 | 2 | NaN | NaN | NaN | 83.0 | 83.0 | 74.0 | 1.0 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
4 | Angola | 5 | 3 | 146.0 | 67.4 | 3890.0 | 49.0 | 51.0 | 16557.0 | 2.8 | ... | 8991.46 | 1.490000e+10 | 27.13 | 9.140000e+09 | 164.10 | 242.5 | 164.10 | 8578749.0 | 4.14 | 53.3 |
5 rows × 358 columns
[11]:
# Aquesta funció admet un paràmetre numèric, especifica el nombre de files
# Per defecte és 5
df_who.tail()
[11]:
Country | CountryID | Continent | Adolescent fertility rate (%) | Adult literacy rate (%) | Gross national income per capita (PPP international $) | Net primary school enrolment ratio female (%) | Net primary school enrolment ratio male (%) | Population (in thousands) total | Population annual growth rate (%) | ... | Total_CO2_emissions | Total_income | Total_reserves | Trade_balance_goods_and_services | Under_five_mortality_from_CME | Under_five_mortality_from_IHME | Under_five_mortality_rate | Urban_population | Urban_population_growth | Urban_population_pct_of_total | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
197 | Vietnam | 198 | 6 | 25.0 | 90.3 | 2310.0 | 91.0 | 96.0 | 86206.0 | 1.4 | ... | 101826.23 | 4.480000e+10 | 47.11 | -1.940000e+09 | 20.2 | 23.4 | 20.2 | 21900000.0 | 2.90 | 26.4 |
198 | West Bank and Gaza | 199 | 1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | 655.86 | 3.780000e+09 | NaN | NaN | 28.0 | 25.8 | 28.0 | 2596216.0 | 3.33 | 71.6 |
199 | Yemen | 200 | 1 | 83.0 | 54.1 | 2090.0 | 65.0 | 85.0 | 21732.0 | 3.0 | ... | 20148.34 | 1.150000e+10 | 114.52 | 8.310000e+08 | 82.4 | 87.9 | 82.4 | 5759120.5 | 4.37 | 27.3 |
200 | Zambia | 201 | 3 | 161.0 | 68.0 | 1140.0 | 94.0 | 90.0 | 11696.0 | 1.9 | ... | 2366.94 | 4.090000e+09 | 10.41 | -4.470000e+08 | 175.3 | 163.8 | 175.3 | 4017411.0 | 1.95 | 35.0 |
201 | Zimbabwe | 202 | 3 | 101.0 | 89.5 | NaN | 88.0 | 87.0 | 13228.0 | 0.8 | ... | 11457.33 | 5.620000e+09 | 3.39 | -1.710000e+08 | 106.5 | 67.0 | 106.5 | 4709965.0 | 1.90 | 35.9 |
5 rows × 358 columns
[12]:
df_who.columns #Ens mostra les columnes del dataframe, es pot indexar com una llista
[12]:
Index(['Country', 'CountryID', 'Continent', 'Adolescent fertility rate (%)',
'Adult literacy rate (%)',
'Gross national income per capita (PPP international $)',
'Net primary school enrolment ratio female (%)',
'Net primary school enrolment ratio male (%)',
'Population (in thousands) total', 'Population annual growth rate (%)',
...
'Total_CO2_emissions', 'Total_income', 'Total_reserves',
'Trade_balance_goods_and_services', 'Under_five_mortality_from_CME',
'Under_five_mortality_from_IHME', 'Under_five_mortality_rate',
'Urban_population', 'Urban_population_growth',
'Urban_population_pct_of_total'],
dtype='object', length=358)
Carrega de dades (II)
Els fitxers csv poden tenir informació de maneres no són estàndard: per exemple tenir separadors que no siguin ‘,’ o formats de codificació del text no oberts.
Podem saber més informació de les possibilitats que ens ofereix la funció read_csv si mirem la seva documentació
Anem a veure que passa quan agafem dades d’una administració pública: enllaç
[13]:
df_gastos = pd.read_csv("data/presupuesto_gastos_2023.csv")
---------------------------------------------------------------------------
ParserError Traceback (most recent call last)
<ipython-input-13-111e56b22917> in <module>
----> 1 df_gastos = pd.read_csv("data/presupuesto_gastos_2023.csv")
~\miniconda3\envs\fee\lib\site-packages\pandas\io\parsers.py in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, dialect, error_bad_lines, warn_bad_lines, delim_whitespace, low_memory, memory_map, float_precision)
686 )
687
--> 688 return _read(filepath_or_buffer, kwds)
689
690
~\miniconda3\envs\fee\lib\site-packages\pandas\io\parsers.py in _read(filepath_or_buffer, kwds)
458
459 try:
--> 460 data = parser.read(nrows)
461 finally:
462 parser.close()
~\miniconda3\envs\fee\lib\site-packages\pandas\io\parsers.py in read(self, nrows)
1196 def read(self, nrows=None):
1197 nrows = _validate_integer("nrows", nrows)
-> 1198 ret = self._engine.read(nrows)
1199
1200 # May alter columns / col_dict
~\miniconda3\envs\fee\lib\site-packages\pandas\io\parsers.py in read(self, nrows)
2155 def read(self, nrows=None):
2156 try:
-> 2157 data = self._reader.read(nrows)
2158 except StopIteration:
2159 if self._first_chunk:
pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader.read()
pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader._read_low_memory()
pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader._read_rows()
pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader._tokenize_rows()
pandas\_libs\parsers.pyx in pandas._libs.parsers.raise_parser_error()
ParserError: Error tokenizing data. C error: Expected 2 fields in line 8, saw 4
[ ]:
df_gastos = pd.read_csv("data/presupuesto_gastos_2023.csv", delimiter=";")
Codificació de caràcters
És un sistema que assigna un valor numèric (codi) a cada caràcter utilitzat en un conjunt de caràcters o alfabet. Aquesta codificació permet representar text i caràcters no només en la forma llegible per als humans, sinó també en una forma que pugui ser emmagatzemada i processada per un ordinador.
Existeixen moltes codificacions diferents, cada una d’elles amb un conjunt de caràcters i una assignació de codis específica. Alguns exemples inclouen:
ASCII (American Standard Code for Information Interchange): Una de les codificacions més antigues i bàsiques, que utilitza 7 bits per a representar 128 caràcters, com l’alfabet anglès, números i alguns símbols.
UTF-8 (Unicode Transformation Format - 8 bits): Una codificació Unicode ampliament utilitzada que utilitza 8 bits (1 byte) per a representar una àmplia gamma de caràcters de molts idiomes diferents. És compatible amb ASCII.
UTF-16 (Unicode Transformation Format - 16 bits): Una altra codificació Unicode que utilitza 16 bits (2 bytes) per a representar caràcters Unicode. Pot representar un conjunt encara més gran de caràcters.
ISO-8859-1 (Latin-1): Una codificació àmpliament utilitzada per a representar caràcters llatins, com els utilitzats en molts idiomes europeus.
var = "camión"
var = "lul·lià"
var = "Ζεύς"
var = "ประเทศไทย"
var = "日本語で"
Codificacions: - Llistat codificacions - UTF-8
[ ]:
# cp1250 | windows-1250 | Central and Eastern Europe
# Mètode bàsic: "Prova i error" !!!
df_gastos = pd.read_csv("data/presupuesto_gastos_2023.csv", delimiter=";", encoding="cp1250")
[ ]:
df_gastos.head()
Guardant un dataframe
Durant aquest curs aprendrem a modificar els dataframes, afegirem i eliminarem columnes i també modificarem les que ja tenim. Per tant ens serà molt interessant poder crear un fitxer a partir del que tenim en el nostre programa.
[ ]:
df_gastos.to_csv('data/tmp_file.csv', encoding='utf-8') # guardant un dataframe en un fitxer, especificant el format
[ ]:
df_tmp = pd.read_csv("data/tmp_file.csv") # test codificació i separador
Carrega de dades (III)
Pandas pot carregar diferents formats de fitxers (csv, json, excel, etc.) els diferents formats tenen les dades organitzades de diferent manera.
En el següent enllaç podem veure més informació.
[ ]:
url = "https://es.wikipedia.org/wiki/Anexo:Comunidades_y_ciudades_aut%C3%B3nomas_de_Espa%C3%B1a"
comunidades_esp = pd.io.html.read_html(url)
comunidades_esp # Alerta! Encara no és un dataframe! En una web pots trobar més "taules"
[ ]:
print(type(comunidades_esp[0]))
df_comunidades_esp = comunidades_esp[0]
[ ]:
df_comunidades_esp.head() # funciona perfectament??
Activitat
En aquesta activitat practicarem la càrrega de dades en diferents formats. Al món real les dades no sempre tenen una estructura i un format com ens agradaríem.
L’objectiu és que analitzeu i descriviu com ha funcionat la càrrega d’aquestes dades amb les originals mitjançant l’ús de funcions de pandas i de les vostres pròpies observacions : - Quina dimensió tenen les dades reals i carregades? - Quines columnes? - El concepte de columna com atribut o característica i el concepte de fila com a mostra està present en l’estructura de les dades? - Coincideixen amb la informació del fitxer?
A) Municipios y fenómeno demográfico de les Illes Balears
Font: Descarregueu el fitxer en format csv. enllaç.
Extra: També podeu provar de carregar en format json.
Fitxer: També el trobareu a: “data/municipis.csv”
[ ]:
import pandas as pd
#TODO
B) Speculation Watch List
Font: enllaç
Fitxer: També el trobareu a: “data/Speculation_Watch_List.csv”
[ ]:
import pandas as pd
#TODO
C) Europe Inflation monthly data (annual rate of change)
Font: enllaç
Fitxer: També el podeu trobar a: “data/prc_hicp_manr__custom_3761882_spreadsheet.xlsx”
Nota:
Com podem agafar una pàgina concreta del full de càlcul? documentació
Per aquesta activitat necessitem instal·lar una llibreria específica: executa la següent cel·la
[ ]:
%pip install openpyxl
[ ]:
import pandas as pd
#TODO
D) Taula de Naixements
Font: enllaç
[ ]:
import pandas as pd
#TODO
E) Nights spent at tourist accommodation establishments by residents/non-residents - monthly data
Font: enllaç
Fitxer: També el podeu trobar a: “data/tin00171_linear.csv.gz”
Nota: Els fitxers comprimits amb format .gz podem obrir-se directament com si fossin fitxers de dades amb pandas, i en aquest cas és un fitxer del tipus CSV. És a dir, no cal descomprimir.
[ ]:
import pandas as pd
#TODO
Isaac Lera and Gabriel Moya Universitat de les Illes Balears isaac.lera@uib.edu, gabriel.moya@uib.edu