Python pandas: how to specify data types when reading an Excel file?

I am importing an excel file into a pandas dataframe with the pandas.read_excel() function.

One of the columns is the primary key of the table: it's all numbers, but it's stored as text (the little green triangle in the top left of the Excel cells confirms this).

However, when I import the file into a pandas dataframe, the column gets imported as a float. This means that, for example, '0614' becomes 614.

Is there a way to specify the datatype when importing a column? I understand this is possible when importing CSV files but couldn't find anything in the syntax of read_excel().

The only solution I can think of is to add an arbitrary letter at the beginning of the text (converting '0614' into 'A0614') in Excel, to make sure the column is imported as text, and then chopping off the 'A' in python, so I can match it to other tables I am importing from SQL.

221528 次浏览

您只需指定转换器。我创建了一个 Excel 电子表格,其结构如下:

names   ages
bob     05
tom     4
suzy    3

其中“ ages”列格式化为字符串。要加载:

import pandas as pd


df = pd.read_excel('Book1.xlsx',sheetname='Sheet1',header=0,converters={'names':str,'ages':str})
>>> df
names ages
0   bob   05
1   tom   4
2   suzy  3

Read _ excel ()函数有一个转换器参数,您可以在其中将函数应用于某些列中的输入。您可以使用它们作为字符串保留它们。 文件 :

用于转换某些列中的值的函数集。键可以是整数或列标签,值是接受一个输入参数的函数,即 Excel 单元格内容,并返回转换后的内容。

示例代码:

pandas.read_excel(my_file, converters = {my_str_column: str})

v0.20.0开始,read_excel()函数中的 dtype关键字参数可以用来指定需要应用到列的数据类型,就像 read_csv()的情况一样。

在同一列名上同时使用 convertersdtype参数将导致后者被隐藏,而前者获得优先权。


1)为了让它不解释 dtypes,而是像之前文件中那样传递所有列的内容,我们可以将这个参数设置为 strobject,这样我们就不会弄乱我们的数据。(其中一种情况是数字的前导零,否则就会丢失)

pd.read_excel('file_name.xlsx', dtype=str)            # (or) dtype=object

2)它甚至支持一个 dict 映射,其中 keys构成列名,而 values是需要设置的各自的数据类型,特别是当你想改变所有列的一个子集的 dtype时。

# Assuming data types for `a` and `b` columns to be altered
pd.read_excel('file_name.xlsx', dtype={'a': np.float64, 'b': np.int32})

如果你不知道数据框中列的数量和名称,那么这个方法可以很方便:

column_list = []
df_column = pd.read_excel(file_name, 'Sheet1').columns
for i in df_column:
column_list.append(i)
converter = {col: str for col in column_list}
df_actual = pd.read_excel(file_name, converters=converter)

其中 column _ list 是列名的列表。

如果您的键具有固定数目的数字,则 应该可能将其存储为文本而不是数字数据。您可以使用 converters参数或 read_excel进行此操作。

或者,如果这不起作用,只需要在将数据读入数据框架后操作它:

df['key_zfill'] = df['key'].astype(str).str.zfill(4)


names   key key_zfill
0   abc     5      0005
1   def  4962      4962
2   ghi   300      0300
3   jkl    14      0014
4   mno    20      0020

如果您不知道列名,并且希望为所有列指定 STR数据类型:

table = pd.read_excel("path_to_filename")
cols = table.columns
conv = dict(zip(cols ,[str] * len(cols)))
table = pd.read_excel("path_to_filename", converters=conv)

如果您能够正确地读取 Excel 文件,并且只有整数值没有显示。您可以这样指定。

df = pd.read_excel('my.xlsx',sheetname='Sheet1', engine="openpyxl", dtype=str)

这将把你的整数值变成一个字符串并显示在数据框中

convertersdtype并不总是有帮助。特别是对于日期/时间和持续时间(理想情况下是两者的混合...) ,后处理是必要的。在这种情况下,可以选择将 Excel 文件的内容读取到内置类型,并从该类型创建 DataFrame。

这里是一个 示例文件。“持续时间”列包含 HH: MM: SS 中的持续时间值和无效值“-”。

excel_sample

如果小时数小于24,则 Excel 将条目格式化为时间,否则格式化为持续时间。我们希望在 DataFrame 中为整个列输入 dtype timedelta。但 pandas搞砸了进口:

import pandas as pd
df = pd.read_excel("path-to-file")


df.duration
# 0               12:30:00
# 1    1900-01-01 00:30:00
# 2                      -
# 3    1900-01-01 23:55:01
# Name: duration, dtype: object


[type(i) for i in df.duration]
# [datetime.time, datetime.datetime, str, datetime.datetime]

现在我们有了 datetime.datetime 和 datetime.time 对象,以及 这很难来获取持续时间(timedelta) !您可以直接使用 converter来完成,但是这并不会降低难度。

Here, I found it to be actually easier to use the excel loader engine directly:

from openpyxl import load_workbook
wb = load_workbook('path-to-file')


sheet = wb['Tests'] # adjust sheet name, this is for the demo file
data = list(sheet.values) # a list of tuples, one tuple for each row
df = pd.DataFrame(data[1:], columns=data[0]) # first tuple is column names


df['duration']
# 0           12:30:00
# 1     1 day, 0:30:00
# 2                  -
# 3    1 day, 23:55:01
# Name: duration, dtype: object


[type(i) for i in df['duration']]
# [datetime.time, datetime.timedelta, str, datetime.timedelta]

So now we already have some timedelta objects! The conversion of the others to timedelta can be done as simple as

df['duration'] = pd.to_timedelta(df.duration.astype(str), errors='coerce')
df['duration']
# 0   0 days 12:30:00
# 1   1 days 00:30:00
# 2               NaT
# 3   1 days 23:55:01
# Name: duration, dtype: timedelta64[ns]