Capítulo 3 - Explicación
  
Previamente… Módulo 3 - Capítulo 2
Conversión del tipo de datos
Para poder hacer cualquier tipo de procesado, debes convertir las columnas a valores numéricos.
La conversion puede poner NaN a todos los valores no numéricos para que el paso anterior no sea necesario.
Input [22]:
data = data[data.columns].apply(pd.to_numeric, errors='coerce')
 data.info()
Output [22]:
<class 'pandas.core.frame.DataFrame'>
 Index: 537 entries, European Union to Bosnia and Herzegovina
 Data columns (total 29 columns):
 1991    232 non-null float64
 1992    258 non-null float64
 1993    232 non-null float64
 1994    258 non-null float64
 1995    361 non-null float64
 1996    382 non-null float64
 1997    355 non-null float64
 1998    354 non-null float64
 1999    384 non-null float64
 2000    354 non-null float64
 2001    396 non-null float64
 2002    364 non-null float64
 2003    402 non-null float64
 2004    311 non-null float64
 2005    151 non-null float64
 2006    61 non-null float64
 2007    328 non-null float64
 2008    352 non-null float64
 2009    347 non-null float64
 2010    357 non-null float64
 2011    352 non-null float64
 2012    354 non-null float64
 2013    355 non-null float64
 2014    347 non-null float64
 2015    355 non-null float64
 2016    356 non-null float64
 2017    361 non-null float64
 2018    361 non-null float64
 2019    20 non-null float64
 dtypes: float64(29)
 memory usage: 125.9+ KB
Input [23]:
data.describe(include = 'all')
Output [23]:

Estandarización de los contenidos.
Después de analizar los datos vemos que la columna NUTS tiene los nombres de los NUTS pero no los códigos.
El siguiente paso es estandarizar los contenidos de esa columna reemplazando las etiquetas con los códigos.
Para este propósito, tenemos un archivo que contiene las etiquetas.
Input [24]:
file = 'datos/nuts.xlsx'
 nuts = pd.read_excel(file, index_col=0)
 nuts.head(5)
Output [24]:

Ya que la información se organiza de manera similar, podemos cambiar un índice por otro.
Input [25]:
data.index = nuts.index
 data.head(5)

Eliminando valores inválidos.
Dependiendo del problema puedes saber que los valores de las celdas deben estar entre un determinado rango. Por tanto, cualquier valor fuera de este rango no es válido y tiene que ser ajustado (min, max o NaN).
En el ejemplo discutido, los valores pueden ser solo positivos. Sin embargo, hay algunos valores negativos en la tabla.
· dataframe.lt() muestral el número de valores más bajos que los indicados
Input [26]:
data.lt(0).sum()
Output [26]:
1991    3
 1992    3
 1993    3
 1994    3
 1995    0
 1996    0
 1997    0
 1998    0
 1999    0
 2000    0
 2001    0
 2002    0
 2003    0
 2004    0
 2005    0
 2006    0
 2007    0
 2008    0
 2009    0
 2010    0
 2011    0
 2012    0
 2013    0
 2014    0
 2015    0
 2016    0
 2017    0
 2018    0
 2019    0
 dtype: int64
Estos valores se pueden poner como 0 o cambiarlos a NaN
Input [27]:
data[data < 0] = np.nan
Visualización de datos nulos
Podemos ver cuantos de los 537 valores no numéricos tiene cada columna.
Dependiendo del problema a resolver puede ser necesario eliminar filas o columnas con NaN para tener datos completos.
· dataframe.isna() muestral los valores nulos del conjunto de datos
Input [28]:
data.isna().sum()
Output [28]:
1991    308
 1992    282
 1993    308
 1994    282
 1995    176
 1996    155
 1997    182
 1998    183
 1999    153
 2000    183
 2001    141
 2002    173
 2003    135
 2004    226
 2005    386
 2006    476
 2007    209
 2008    185
 2009    190
 2010    180
 2011    185
 2012    183
 2013    182
 2014    190
 2015    182
 2016    181
 2017    176
 2018    176
 2019    517
 dtype: int64
Eliminar datos nulos
En caso de que necesitemos limpiar más datos y eliminar columnas que contengan algunos datos nulos, en este caso tendríamos que eliminar 2019, ya que los datos no están terminados. Así, tenemos que eliminar las columnas que no nos son útiles.
· dataframe.dropna() te permite eliminar columnas con datos nulos.
Input [29]:
data2 = data.dropna()
 data2.describe()
Output [29]:

Se puede ver que en la colección de datos, hay columnas no completas.
Inteporlación de datos nulos.
Si los análisis a realizar no permiten hacer nulos los datos o eliminarlos ya que muchas filas se eliminarían, una alternativa es interpolar los valores.
Input [30]:
data = data.interpolate(axis=1, limit_direction='both')
 data.head()

Rellenar columnas vacias
La interpolación es imprecise con columnas con pocos datos, ya que apenas hay datos e información para deducir los valores que faltan. Un ejemplo es la primera fila de la tabla, donde solo hay 1 dato para la Unión Europea, por lo que la interpolación rellena todas las casillas con ese valor.
Otro problema son las filas completamente vacías. Aquí la interpolación no puede hacer nada. Una solución si necesitan tener valores es poner todas esas filas con valores 0.
dataframe.fillna() te permite cambiar un valor NaN a otro valor
Escribir archivos de datos
PARA APRENDER MÁS….
The formats supported in the Pandas library and how to write in them is described in: https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html
Format  | Read  | Write  | 
csv  | pd.read_csv()  | pac.to_csv()  | 
json  | pd.read_json()  | pac.to_json()  | 
excel  | pd.read_excel()  | pac.to_excel()  | 
hdf  | pd.read_hdf()  | pac.to_hdf()  | 
sql  | pd.read_sql()  | pac.to_sql()  | 
...  | ...  | ...  | 
 Cada operación de grabación en diferente formato necesita ajustar diferentes parametros.
Pandas nos permite guardar los datros en formato Excel con dataframe.to_excel().
Los parametros más relevantes son:
·          io = The file location 
· sheet_name = The sheet to be written
·          index = If an index column should be put in the file
 
 
Input [32]:
data.to_excel('datos/animalEurostatNuts2_DataSheet_corrected.xlsx', sheet_name='Data')
El archivo usado como ejemplo contiene múltiples hojas que pueden ser procesadas de la misma manera ya que tienen la misma estructura.
Para automatizar el proceso, puedes leer todas las hojas y aplicar el proceso a cada una de ellas y guardar el resultado en un ahoja diferente del archivo de salida.
Primero, tenemos que definir una función que, dado un marco de datos, aplica el proceso de limpieza de datos entero.
Después, la función llama al proceso para cada hoja
Input [33]:
import pandas as pd
 import numpy as np
 
 nuts = pd.read_excel('datos/nuts.xlsx', index_col=0)
 
 #function for Data cleaning
 def cleanData(data):
     #we eliminate leftover columns
     indices = [i for i, s in enumerate(data.columns) if 'Flags' in s]
     colToDelete=data.columns[np.array(indices)]
     data = data.drop(columns=colToDelete)
     #we change the header and first column
     data.index = nuts.index
     #we change data type and remove no numbers
     data = data[data.columns].apply(pd.to_numeric, errors='coerce')
     #we eliminate duplicate rows
     data = data.loc[~data.index.duplicated(keep='first')]
     #we delete negative values
     data[data < 0] = np.nan
     #we interpolate null values
     data = data.interpolate(axis=1, limit_direction='both')
     #we add zeros to the empty rows
     data = data.fillna(0)
     return data
Input [34]:
reader = pd.ExcelFile('datos/animalEurostatNuts2.xlsx')
 writer = pd.ExcelWriter('datos/animalEurostatNuts2_corrected.xlsx')
 for sheet in reader.sheet_names:
     data = pd.read_excel(reader, sheet_name=sheet, skiprows=9, skipfooter=13, index_col=0)
     data = cleanData(data)
     data.to_excel(writer, sheet_name=sheet)
 writer.save()
 print('Done')
Output [34]:
Done
Continua… Módulo 3 – Capítulo 4