如何从excel中的命名范围读入pandas数据帧? read_excel旨在读取工作簿中的整个工作表。
答案 0 :(得分:2)
引用Microsoft Office help pages!:
[命名范围]是一种有意义的简写,可以更容易理解单元格引用,常量,公式或表格的用途,乍一看可能很难理解。“
在电子表格中经常使用命名范围以便于通过ODBC访问数据,并且在同一工作表中有多个数据范围时特别有用。要通过ODBC连接到Excel,只需选择适当的Excel driver并发送一条SQL语句,例如:
SELECT *
FROM namedRange
Pandas中的有用命令可能是read_sql。
在Windows中,此解决方案要求您对齐/简化已安装的Excel软件版本(32位或64位),ODBC驱动程序以及用于打开ODBC连接的软件包。例如,安装的Excel 32位版本将需要32位ODBC驱动程序,通常需要32位Python安装。 注意:对于Python案例(我是Python的初学者),后一点仍有待确认,但我可以肯定地确认从SAS,SPSS或Stata启动的ODBC连接的这一点。
之前的要求是一个非常显着的缺点,实际上支持任何不涉及ODBC的解决方案。也就是说,如果read_Excel提供了这样的便利,那就太好了。在这种情况下,值得注意的是,SAS,SPSS和Stata目前不允许在各自的Excel过滤器中直接访问命名区域 - 因此可能存在缺乏此功能的客观原因。
答案 1 :(得分:2)
也许有一天大熊猫会原生支持这个。在那之前,我使用辅助函数:
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
答案 2 :(得分:1)
您可以使用基础xlrd
包来执行此操作。
xlrd
包附带一个examples
目录,其中包含xlrdnameAPIdemo.py
,记录为here。
简而言之,对于命名范围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')
你可以按照例子来解释,虽然看起来并不简单 - 例如。范围可以是相对的,也可以不是,取决于值result.kind
。
此外,当我尝试使用它来阅读我自己的电子表格(在Mac上创建)时,我发现result
为None
;相反,name_obj
范围内的唯一参考是:
'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
执行此操作,那么您正在读取数据文件两次,这很愚蠢,但您明白了。
答案 3 :(得分:0)
以下是我使用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]]
答案 4 :(得分:0)
好了,已经有一段时间了,但是我绝对建议给xlwings投一枪。
答案 5 :(得分:-1)
您可以使用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 (e.g. “A:E” or “A,C,E:F”)
这意味着如果您知道列名和行号(可能是“命名范围”的意思?),您可以只选择该部分来制作数据框。