添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Python pandas:如何在读取Excel文件时指定数据类型?

112 人关注

我正在用 pandas.read_excel() 函数将一个excel文件导入一个pandas数据框架。

其中一列是表格的主键:它都是数字,但它被存储为文本(Excel单元格左上方的绿色小三角形证实了这一点)。

然而,当我把文件导入pandas数据框架时,该列被导入为浮点。这意味着,例如,'0614'变成了614。

有什么方法可以在导入列时指定数据类型?我知道在导入CSV文件时可以这样做,但在 read_excel() 的语法中找不到任何东西。

我能想到的唯一解决方案是在Excel中在文本的开头添加一个任意的字母(将'0614'转换为'A0614'),以确保该列被导入为文本,然后在python中砍掉'A',这样我就能与我从SQL导入的其他表格相匹配。

python
pandas
dataframe
Pythonista anonymous
Pythonista anonymous
发布于 2015-09-16
8 个回答
tnknepp
tnknepp
发布于 2022-01-28
已采纳
0 人赞同

你只需指定转换器。 我创建了一个excel电子表格,结构如下。

names   ages
bob     05
tom     4
suzy    3

其中 "年龄 "列的格式为字符串。 要加载。

import pandas as pd
df = pd.read_excel('Book1.xlsx',sheetname='Sheet1',header=0,converters={'names':str,'ages':str})
       names ages
   0   bob   05
   1   tom   4
   2   suzy  3
    
我的理解是'转换器'指定了一个应用于该列的函数。显然我错了--谢谢你指出这一点,这非常有用!"。
我在哪里可以找到允许的转换器函数的列表? 我在这里看到了 str ,但估计还有 int 和其他一些--在源文件的任何地方有一个链接,列举了可能的转换函数?
我也没有找到一个清单。 由于 "转换器 "接受函数,我怀疑你的想象力是极限,只是让你保持在 "转换器 "功能的范围内(即它被设计为使用只需要一个输入变量的函数!)。
奇怪的是,当我在 converters dict中把一个列名设置为 str ,然后打印 df.dtypes 时,该列的类型被设置为 object 而不是 str 。有什么想法吗?这很重要吗?
@mhyousefi 这并不重要(至少在表面上)。 当把列类型设置为字符串时,Pandas把它们称为对象。 见HYRY的回答 here
Nickil Maveli
Nickil Maveli
发布于 2022-01-28
0 人赞同

v0.20.0 开始, dtype 的关键字参数在 read_excel() 函数可以用来指定需要应用于列的数据类型,就像它存在于 read_csv() 案。

在同一列名上同时使用 converters dtype 参数会导致后者被阴影化,而前者获得优先权。

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

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})
    
这应该是公认的答案,因为 "转换器 "似乎是在将数据读成不同类型后再进行转换。这导致了信息损失("001 "将被读作int("001")="1",然后被转换为str。但是 "001"!="1")。至少在我的例子中是这样的,如果我错了请纠正我。
Yes, this is the more intuitive solution for me
在尝试了许多可能性之后,这个方法对我来说是有效的。非常感谢您!
Tango
Tango
发布于 2022-01-28
0 人赞同

如果你不知道数据框架中列的数量和名称,那么这个方法就会很方便。

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是你的列名列表。

Just wonder if df = df.astype(str) would not be better (simpler).
为什么要先创建一个列表?也许使用更有效。 替换代码0】,然后是 df = pd.read_excel(fn,sheet_name='sheet1',converters=conv)
Nix G-D
Nix G-D
发布于 2022-01-28
0 人赞同

read_excel()函数有一个转换器参数,你可以对某些列的输入应用函数。 你可以用它来把它们保持为字符串。

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

示例代码。

pandas.read_excel(my_file, converters = {my_str_column: str})
    
如果我们不知道工作表中存在的列数,是否有办法在阅读时将其应用于每一列?
Got the solution: converters = {col: str for col in column_list} df = pd.read_excel('some_excelfile.xls', converters=converters)
rrs
你可以通过索引来做,还是需要名称? 例如,我在读我的文件时没有标题。
@rrs,你可以直接用一个整数作为键,而不是列名。
Rajat Tyagi
Rajat Tyagi
发布于 2022-01-28
0 人赞同

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

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

这应该会把你的整数值变成字符串并显示在数据框中。

HazimoRa3d
HazimoRa3d
发布于 2022-01-28
0 人赞同

如果你不知道列的名称,而你想指定 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)
    
另外,在第一个 nrows=1 的调用中添加 read_excel 可能是有用的,以避免只为获得标题而读取整个Excel表格。
jpp
jpp
发布于 2022-01-28
0 人赞同

如果你的钥匙有一个固定的数字,你可以 should 可能存储为文本而不是数字数据。你可以为此使用 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
    
FObersteiner
FObersteiner
发布于 2022-01-28
0 人赞同

替换代码0】或 dtype 并不总是有用。特别是对于日期/时间和持续时间(最好是两者的混合......),必须进行后处理。在这种情况下,把Excel文件的内容读成一个内置的类型并从中创建DataFrame可以是一种选择。

这里有一个 示例文件 ."持续时间 "列包含以HH:MM:SS为单位的持续时间值和无效值"-"。

如果小时数小于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对象,并且it's difficult来获得持续时间(timedelta)!你可以直接用converter来做,但这并不能降低其难度。

在这里,我发现直接使用excel加载器引擎实际上更容易。

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]

所以现在我们已经有了一些timedelta对象!将其他对象转换为timedelta,可以像这样简单地完成

df['duration'] = pd.to_timedelta(df.duration.astype(str), errors='coerce')
df['duration']
# 0   0 days 12:30:00