pandas数据框从excel命名的范围

有没有一种简单的方法来从一个命名的范围在Excel中的pandas数据框。 read_excel被devise为读取工作簿中的整个工作表。

引用Microsoft Office帮助页面 :

一个[命名的范围]是一个有意义的简写,使得它更易于理解单元格引用,常量,公式或表格的目的,每一个都可能很难一眼就明白。

命名范围还经常用于电子表格中,以便于通过ODBC访问数据,并且在同一工作表中有多个数据范围时特别有用。 要通过ODBC连接到Excel,只需select适当的Excel驱动程序并发送SQL语句,例如:

SELECT * FROM namedRange 

Pandas中的有用命令可能是read_sql。

在Windows中,此解决scheme需要alignment/精简已安装的Excel的软件版本(32位或64位),ODBC驱动程序和从中打开ODBC连接的软件包。 例如,安装的Excel 32位版本将需要32位ODBC驱动程序,通常是32位的Python安装。 注意:后面一点对于Python的情况还是有待证实的(我是Python的初学者),但是我绝对可以证实从SAS,SPSS或Stata启动的ODBC连接的这一点。

以前的要求是一个非常明显的缺点,并且实际上是赞成任何完全不涉及ODBC的解决scheme。 也就是说,如果read_Excel提供了这样一个工具,那将会很好。 在这种情况下,值得注意的是,SAS,SPSS和Stata目前不允许直接访问各自Excelfilter中的命名范围 – 所以也许这个缺乏function的客观原因是…

您可以使用底层的xlrd软件包来执行此操作。

xlrd软件包附带一个包含xlrdnameAPIdemo.pyexamples目录,如此处所述 。

简而言之,命名范围print_area尝试:

 book = xlrd.open_workbook('examples/namesdemo.xls') name_obj = book.name_map['print_area'][0] print name_obj.__dict__ 

你会看到name_obj有一个条目:

 'result': Operand(kind=oREF, value=[Ref3D(coords=(2, 3, 0, 4, 0, 14))], text=u'Sheet3!$A$1:$N$4') 

你可以按照这个例子来解释,尽pipe它看起来并不简单 – 例如。 范围可能相对与否,取决于result.kind的值。

此外,当我试图用这个阅读我自己的电子表格(在Mac上创build)时,我发现resultNone ; 相反, name_obj唯一的ref是:

 'formula_text': u'Sheet1!$B$6:$E$11' 

所以在一般情况下可能有一种方法可以使这项工作,但它看起来会需要一些试验和错误。

或者,如果您可以格式化电子表格而不是命名范围,那么您的表紧跟在唯一标题( key )之后的行之后,并且以空白行结束,这里是一个函数,用于查找要发送的正确参数到pd.read_excel

 def table_position(path, sheet_name, key): """ Find the start and end rows of a table in an Excel spreadsheet based on the first occurence of key text on the sheet, and down to the first blank line. Returns (col, start_row, end_row, skip_footer) where: col is the column number containing the key text, start_row is the row after this, end_row is the row number of the next blank line, skip_footer is how many rows from the end of the sheet this is. You can then read in the table with: x = pd.read_excel(path, sheet_name, skiprows=start, skip_footer=skip_footer, header=0) x = x.dropna(axis=1, how='all') """ import xlrd book = xlrd.open_workbook(path) sheet = book.sheet_by_name(sheet_name) # find the first occurrence of the key, and the next line break (col, start, end) = (-1, -1, sheet.nrows) for rownum in xrange(sheet.nrows): if col<0: # look for key to start the table off try: test_col = next(c for c in xrange(sheet.ncols) if sheet.cell(rownum, c).value==key) except StopIteration: pass else: col, start = test_col, rownum+1 # row after key text is the start else: # test for blank line as end of table if not [True for cell in sheet.row(rownum) if cell.value]: end = rownum break skip_footer = sheet.nrows - end return (col, start, end, skip_footer) 

如果你使用pd.read_excel实现这个function,那么你正在读取数据文件两次,这很愚蠢,但是你明白了。

你可以使用read_excel来完成这个任务 ,它提供了:

 skiprows : list-like Rows to skip at the beginning (0-indexed) skip_footer : int, default 0 Rows at the end to skip (0-indexed) parse_cols : int or list, default None If None then parse all columns, If int then indicates last column to be parsed If list of ints then indicates list of column numbers to be parsed If string then indicates comma separated list of column names and column ranges (eg “A:E” or “A,C,E:F”) 

这意味着如果你知道列名和行号(大概你所谓的“命名范围”是什么意思?),你可以只select该部分来制作DataFrame。

也许有一天pandas会支持这个本地的。 在那之前,我使用了一个辅助函数:

 import pandas as pd import openpyxl def data_frame_from_xlsx(xlsx_file, range_name): """ Get a single rectangular region from the specified file. range_name can be a standard Excel reference ('Sheet1!A2:B7') or refer to a named region ('my_cells').""" wb = openpyxl.load_workbook(xlsx_file, data_only=True, read_only=True) if '!' in range_name: # passed a worksheet!cell reference ws_name, reg = range_name.split('!') if ws_name.startswith("'") and ws_name.endswith("'"): # optionally strip single quotes around sheet name ws_name = ws_name[1:-1] region = wb[ws_name][reg] else: # passed a named range; find the cells in the workbook full_range = wb.get_named_range(range_name) if full_range is None: raise ValueError( 'Range "{}" not found in workbook "{}".'.format(range_name, xlsx_file) ) # convert to list (openpyxl 2.3 returns a list but 2.4+ returns a generator) destinations = list(full_range.destinations) if len(destinations) > 1: raise ValueError( 'Range "{}" in workbook "{}" contains more than one region.' .format(range_name, xlsx_file) ) ws, reg = destinations[0] # convert to worksheet object (openpyxl 2.3 returns a worksheet object # but 2.4+ returns the name of a worksheet) if isinstance(ws, str): ws = wb[ws] region = ws[reg] df = pd.DataFrame([cell.value for cell in row] for row in region) return df 

下面是我使用openpyxl复制[[]]范围的方法:

 wb = load_workbook(filename=xlPath) ws, range= next(wb.defined_names["rangename"].destinations) materials = [[cell.value for cell in row] for row in wb[ws][range]]