Estoy leyendo este archivo de Excel Indicadores de energía de las Naciones Unidas usando el fragmento de código aquí:
def convert_energy(energy): if isinstance(energy, float): return energy*1000000 else: return energy def energy_df(): return pd.read_excel("Energy Indicators.xls", skiprows=17, skip_footer=38, usecols=[2,3,4,5], na_values=['...'], names=['Country', 'Energy Supply', 'Energy Supply per Capita', '% Renewable'], converters={1: convert_energy}).set_index('Country')
Esto da como resultado que la columna Suministro de energía tenga el tipo de objeto en lugar de flotar. ¿Por qué es el caso?
energy = energy_df() print(energy.dtypes) Energy Supply object Energy Supply per Capita float64 % Renewable float64
Vamos a eliminar el argumento de los converters
por un momento –
c = ['Energy Supply', 'Energy Supply per Capita', '% Renewable'] df = pd.read_excel("Energy Indicators.xls", skiprows=17, skip_footer=38, usecols=[2,3,4,5], na_values=['...'], names=c, index_col=[0]) df.index.name = 'Country'
df.head() Energy Supply Energy Supply per Capita % Renewable Country Afghanistan 321.0 10.0 78.669280 Albania 102.0 35.0 100.000000 Algeria 1959.0 51.0 0.551010 American Samoa NaN NaN 0.641026 Andorra 9.0 121.0 88.695650 df.dtypes Energy Supply float64 Energy Supply per Capita float64 % Renewable float64 dtype: object
Sus datos se cargan bien sin un convertidor. Hay un truco para entender por qué sucede esto.
Por defecto, los pandas
leerán en la columna e intentarán “interpretar” sus datos. Al especificar su propio convertidor, anula la conversión de pandas, por lo que esto no sucede.
pandas pasa valores enteros y de cadena a convert_energy
, por lo que la isinstance(energy, float)
nunca se evalúa como True
. En su lugar, else
corre, y estos valores se devuelven tal como están, de modo que su columna resultante es una mezcla de cadenas y enteros. Si coloca una print(type(energy))
dentro de su función, esto se vuelve obvio.
Como tiene mezclas de tipos, el tipo resultante es object
. Sin embargo, si no usa un convertidor, los pandas intentarán interpretar sus datos y los analizarán con éxito a números.
Así que, sólo haciendo …
df['Energy Supply'] *= 1000000
Sería más que suficiente.
Uno de los valores de la energía en su archivo de Excel es una cadena “…” y cuando está en su función de cobertura, simplemente devuelve la energía como si fuera un tipo de datos de cadena.
Por lo tanto, obtendrá una cadena devuelta junto con sus números que luego cambiará el tipo de letra de su columna a ‘objeto’.
Podrías probar algo como esto:
def convert_energy(energy): if energy == "...": return np.nan elif isinstance(energy, float): return float(energy*1000000) else: return float(energy) df = pd.read_excel('http://unstats.un.org/unsd/environment/excel_file_tables/2013/Energy%20Indicators.xls', skiprows=17, skip_footer=38, usecols=[2,3,4,5], na_values=['...'], names=['Country', 'Energy Supply', 'Energy Supply per Capita', '% Renewable'], converters={1: convert_energy}).set_index('Country') df.info()
Salida:
Index: 227 entries, Afghanistan to Zimbabwe Data columns (total 3 columns): Energy Supply 222 non-null float64 Energy Supply per Capita 222 non-null float64 % Renewable 227 non-null float64 dtypes: float64(3) memory usage: 6.2+ KB