介绍用pandas读取Excel文件并将数据转换为DataFrame很容易。但是,现实世界中的Excel文件通常结构不佳,在数据分散在工作表中的情况下,您可能需要自定义数据的读取方式。本文将讨论如何使用pandas和openpyxl读取这些类型的Excel文件,并将数据干净利落地转换为适合进一步分析的DataFrame。问题pandas的read_excel函数可以很好地读取Excel工作表。但是,如果数据不是从单元格A1开始的连续表格,则结果可能不是您所期望的。例如,当您尝试使用read_excel(src_file)读取下面的示例电子表格时。你会得到类似下面的东西。这些结果包括很多未命名的列、行内标题标签和一些我们不需要的额外列。Pandas解决方案对于这个数据集,最简单的解决方案是使用read_excel()的header和usecols参数。特别是usecols参数对于控制要包含的列非常有用。如果您想按照示例进行操作,这些文件位于github上。https://github.com/chris1610/pbpython/blob/master/data/shipping_tables.xlsx以下是仅读取我们需要的数据的替代方法。importpandasasppdfrompathlibimportPathsrc_file=Path.cwd()/'shipping_tables.xlsx'df=pd.read_excel(src_file,header=1,usecols='B:F')生成一个只包含我们需要的数据的DataFrame。在此示例中,我们有意排除了Notes和Date列。usecols可以接受Excel范围,例如B:F,并且只读入这些列。标题参数需要一个定义标题列的整数。这个值是从0开始索引的,所以我们传入1,即使这是Excel的第2行。在某些情况下,我们可能希望将列定义为数字列表。在这个例子中,我们可以定义为一个整数列表。df=pd.read_excel(src_file,header=1,usecols=[1,2,3,4,5])如果你想为大型数据集遵循某种数字模式(即每3列或什至列),这种方法可能有用。pandas的usecols也可以接受列名列表。此代码将创建一个等效的DataFrame。#定义一个更复杂的函数:defcolumn_check(x):if'unnamed'inx.lower():returnFalseif'priority'inx.lower():returnFalseif'order'inx.lower():returnTruereturnTruedf=pd.read_excel(src_file,header=1,usecols=column_check)要记住的关键概念是该函数将按名称解析每一列,并且必须为每一列返回True或False。那些计算结果为True的列将被包括在内。另一种使用可调用函数的方法是包含一个lambda表达式。下面是一个示例,其中我们只想包含已定义列的列表。我们通过将名称转换为小写来规范化,以便于比较。cols_to_use=['item_type','orderid','orderdate','state','priority']df=pd.read_excel(src_file,header=1,usecols=lambdax:x.lower()incols_to_use)可调用函数为我们处理现实世界中凌乱的Excel文件提供了很大的灵活性。范围和表格在某些情况下,Excel中的数据可能更加模糊。在这个例子中,我们有一个名为ship_cost的表,我们想要读取它。如果您必须处理此类文件,那么使用我们目前讨论过的pandas选项来阅读可能是一个挑战。在这种情况下,我们可以直接使用openpyxl来解析文件并将数据转换为pandasDataFrame。数据在Excel工作表中这一事实可以使该过程更容易一些。下面介绍如何使用openpyxl读取Excel文件。fromopenpyxlimportload_workbookimportpandasasppdfrompathlibimportPathsrc_file=src_file=Path.cwd()/'shipping_tables.xlsx'wb=load_workbook(filename=src_file)这将加载整个工作簿。如果我们想查看所有工作表。wb.sheetnames['sales','shipping_rates']以访问特定的工作表。sheet=wb['shipping_rates']查看所有命名表的列表。sheet.tables.keys()dict_keys(['ship_cost'])这个键对应于我们在Excel中分配给表格的名称。现在我们访问表格以获得与Excel等效的范围。lookup_table=sheet.tables['ship_cost']lookup_table.ref'C8:E16'这样就可以了。我们现在知道要加载的数据范围。最后一步是将此范围转换为pandasDataFrame。下面是一个简短的代码片段,用于遍历每一行并转换为DataFrame。#访问表中的数据rangedata=sheet[lookup_table.ref]rows_list=[]#遍历每一行,获取单元格中的值forrowindata:#获取每行所有列的列表cols=[]forcolinrow:cols.append(col.value)rows_list.append(cols)#从rows_list创建一个pandasdataframe。#第一行是列名df=pd.DataFrame(data=rows_list[1:],index=None,columns=rows_list[0])下面是生成的数据框。现在我们有一个干净的表,可以用于进一步的计算。总结在理想情况下,我们使用的数据应该有一种简单和一致的格式。在本文的示例中,我们可以轻松删除行和列以使其更符合格式。但是,有时这样做不可行或不可取。好消息是pandas和openpyxl为我们提供了读取Excel数据所需的所有工具。
