使用带有转换器的read_excel将Excel文件读入Pandas DataFrame会生成对象类型的数字列

时间:2017-12-30 17:33:40

标签: python excel pandas dataframe

我正在使用此处的代码段阅读此Excel文件United Nations Energy Indicators

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')

这导致 Energy Supply 列具有对象类型而不是float。为什么会这样?

energy = energy_df()
print(energy.dtypes)

Energy Supply                object
Energy Supply per Capita    float64
% Renewable                 float64

3 个答案:

答案 0 :(得分:3)

让我们暂时删除converters参数 -

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

没有转换器,您的数据加载就好了。有一个技巧可以理解为什么会发生这种情况。

默认情况下,pandas会在列中读取并尝试"解释"你的数据。通过指定您自己的转换器,您可以覆盖pandas转换,因此不会发生这种情况。

pandas将整数和字符串值传递给convert_energy,因此isinstance(energy, float)永远不会被评估为True。相反,else运行,并且这些值按原样返回,因此您的结果列是字符串和整数的混合。如果你在函数中添加print(type(energy)),这就变得很明显了。

由于您有多种类型,因此结果类型为object。但是,如果您不使用转换器,pandas将尝试解释您的数据,并将成功将其解析为数字。

所以,只是做 -

df['Energy Supply'] *= 1000000

绰绰有余。

答案 1 :(得分:1)

excel文件中的一个能量值是一个字符串“...”,当你在你的变换器函数中时,如果它是一个字符串数据类型,你只需返回能量。

因此,您将获得一个与您的数字一起返回的字符串,然后将您的dtype更改为'object。

您可以尝试这样的事情:

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()

输出:

<class 'pandas.core.frame.DataFrame'>
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

答案 2 :(得分:0)

尝试使用isinstance(energy, int)而不是isinstance(energy, float)

像这样->

def convert_energy(energy):
    if isinstance(energy, int):
         return float(energy*10^6)