El uso de read_excel con convertidores para leer el archivo de Excel en Pandas DataFrame da como resultado una columna numérica de tipo de objeto

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