2014-09-27 20 views
9

Có ai có đề xuất về cách tốt nhất để mở dữ liệu xml trên trang web bên dưới để đặt nó trong một khung dữ liệu (tôi thích làm việc với gấu trúc) trong python không? Các tập tin là vào "Data - XML ​​(sdmx/zip)" liên kết trên trang web này:Cách mở tệp XML này để tạo dataframe bằng Python?

http://www.federalreserve.gov/pubs/feds/2006/200628/200628abs.html

Tôi đã thử bằng cách sử dụng sau đây bằng cách sao chép từ http://timhomelab.blogspot.com/2014/01/how-to-read-xml-file-into-dataframe.html, và có vẻ như tôi nhận được gần:

from lxml import objectify 
import pandas as pd 

path = 'feds200628.xml' 
xml = objectify.parse(open(path)) 
root = xml.getroot() 
root.getchildren()[0].getchildren() 
df = pd.DataFrame(columns=('id', 'name')) 

for i in range(0,4): 
    obj = root.getchildren()[i].getchildren() 
    row = dict(zip(['id', 'name'], [obj[0].text, obj[1].text])) 
    row_s = pd.Series(row) 
    row_s.name = i 
    df = df.append(row_s) 

Tuy nhiên, tôi không biết đủ về xml để có được phần còn lại của con đường.

Bất kỳ trợ giúp nào cũng tuyệt vời - Tôi thậm chí không cần nó ở trong một khung dữ liệu, tôi chỉ cần tìm ra cách phân tích nội dung này bằng python bằng cách nào đó.

+0

Có thể trùng lặp [Làm cách nào để mở tệp Excel bằng Python?] (Http://stackoverflow.com/questions/3239207/how-can-i-open-an-excel-file-in-python) – poolie

Trả lời

6

Tôi sẽ xuất XLS formatted file sang tệp CSV (sử dụng chương trình có sẵn miễn phí như Gnumeric hoặc LibreOffice, hoặc nếu bạn có nó, Excel), sau đó đọc tệp CSV thành gấu trúc. Tôi biết đây không phải là câu trả lời chính xác cho câu hỏi cuối cùng của bạn, nhưng phân tích cú pháp XML là một giải pháp quá phức tạp đối với những gì bạn đang cố gắng làm.

Về phân tích XML trong Python, thư viện lxml là thư viện yêu thích của tôi để sử dụng. Tôi tìm thấy bằng cách sử dụng ngôn ngữ truy vấn XPath cùng với một trình phân tích cú pháp lxml để là tuyến đường tốt nhất.

8

XML là cấu trúc giống cây, trong khi khung dữ liệu Pandas là cấu trúc giống bảng 2D. Vì vậy, không có cách tự động để chuyển đổi giữa hai. Bạn phải hiểu cấu trúc XML và biết cách bạn muốn ánh xạ dữ liệu của nó vào một bảng 2D. Vì vậy, mọi vấn đề XML-to-DataFrame là khác nhau.

XML của bạn có 2 DataSets, mỗi tệp chứa một số Series. Mỗi Series chứa một số yếu tố Obs.

Mỗi chuỗi có thuộc tính NAME và mỗi thuộc tính có thuộc tính OBS_STATUS, TIME_PERIOD và OBS_VALUE. Vì vậy, có lẽ nó sẽ là hợp lý để tạo ra một bảng với các cột NAME, OBS_STATUS, TIME_PERIOD và OBS_VALUE.

Tôi thấy việc kéo dữ liệu mong muốn ra khỏi XML phức tạp một chút, điều này khiến tôi nghi ngờ rằng tôi đã tìm ra cách tốt nhất để làm điều đó. Nhưng đây là một cách (PS ý tưởng bắt đầu với các dữ liệu XLS bảng giống như 2D Thomas Maloney nên cách đơn giản hơn.):

import lxml.etree as ET 
import pandas as pd 

path = 'feds200628.xml' 

def fast_iter(context, func, *args, **kwargs): 
    """ 
    http://lxml.de/parsing.html#modifying-the-tree 
    Based on Liza Daly's fast_iter 
    http://www.ibm.com/developerworks/xml/library/x-hiperfparse/ 
    See also http://effbot.org/zone/element-iterparse.htm 
    http://stackoverflow.com/a/7171543/190597 (unutbu) 
    """ 
    for event, elem in context: 
     func(elem, *args, **kwargs) 
     # It's safe to call clear() here because no descendants will be 
     # accessed 
     elem.clear() 
     # Also eliminate now-empty references from the root node to elem 
     for ancestor in elem.xpath('ancestor-or-self::*'): 
      while ancestor.getprevious() is not None: 
       del ancestor.getparent()[0] 
    del context 

data = list() 
obs_keys = ['OBS_STATUS', 'TIME_PERIOD', 'OBS_VALUE'] 
columns = ['NAME'] + obs_keys 

def process_obs(elem, name): 
    dct = elem.attrib 
    # print(dct) 
    data.append([name] + [dct[key] for key in obs_keys]) 

def process_series(elem): 
    dct = elem.attrib 
    # print(dct) 
    context = ET.iterwalk(
     elem, events=('end',), 
     tag='{http://www.federalreserve.gov/structure/compact/common}Obs' 
     ) 
    fast_iter(context, process_obs, dct['SERIES_NAME']) 

def process_dataset(elem): 
    nsmap = elem.nsmap 
    # print(nsmap) 
    context = ET.iterwalk(
     elem, events=('end',), 
     tag='{{{prefix}}}Series'.format(prefix=elem.nsmap['kf']) 
     ) 
    fast_iter(context, process_series) 

with open(path, 'rb') as f: 
    context = ET.iterparse(
     f, events=('end',), 
     tag='{http://www.federalreserve.gov/structure/compact/common}DataSet' 
     ) 
    fast_iter(context, process_dataset) 
    df = pd.DataFrame(data, columns=columns) 

sản lượng

  NAME OBS_STATUS TIME_PERIOD OBS_VALUE 
0  SVENY01   A 1961-06-14  2.9825 
1  SVENY01   A 1961-06-15  2.9941 
2  SVENY01   A 1961-06-16  3.0012 
3  SVENY01   A 1961-06-19  2.9949 
4  SVENY01   A 1961-06-20  2.9833 
5  SVENY01   A 1961-06-21  2.9993 
6  SVENY01   A 1961-06-22  2.9837 
... 
1029410  TAU2   A 2014-09-19 3.72896779 
1029411  TAU2   A 2014-09-22 3.12836171 
1029412  TAU2   A 2014-09-23 3.20146575 
1029413  TAU2   A 2014-09-24 3.29972110 
-1

Mã này nó hoạt động chuyển đổi để DF loại tập tin XML Excel:

import pandas as pd 
from xml.sax import ContentHandler, parse 

# Reference https://goo.gl/KaOBG3 
class ExcelHandler(ContentHandler): 
    def __init__(self): 
     self.chars = [ ] 
     self.cells = [ ] 
     self.rows = [ ] 
     self.tables = [ ] 
    def characters(self, content): 
     self.chars.append(content) 
    def startElement(self, name, atts): 
     if name=="Cell": 
      self.chars = [ ] 
     elif name=="Row": 
      self.cells=[ ] 
     elif name=="Table": 
      self.rows = [ ] 
    def endElement(self, name): 
     if name=="Cell": 
      self.cells.append(''.join(self.chars)) 
     elif name=="Row": 
      self.rows.append(self.cells) 
     elif name=="Table": 
      self.tables.append(self.rows) 

excelHandler = ExcelHandler() 
parse('feds200628.xls', excelHandler) 
df1 = pd.DataFrame(excelHandler.tables[0][10:], columns=excelHandler.tables[0][9]) 
print df1.head() 

tôi không thể đưa ra bình luận (uy tín thấp), nhưng câu trả lời của câu hỏi này về "How to open Excel XML file programmatically" (với trăn và gấu trúc) cần làm việc.

+0

Điều này không cung cấp câu trả lời cho câu hỏi. Để phê bình hoặc yêu cầu làm rõ từ tác giả, để lại nhận xét bên dưới bài đăng của họ - bạn luôn có thể nhận xét về bài đăng của riêng bạn và sau khi bạn có đủ [danh tiếng] (http://stackoverflow.com/help/whats-reputation), bạn sẽ có thể [nhận xét về bài đăng bất kỳ] (http://stackoverflow.com/help/privileges/comment). – UmNyobe

+0

@UmNyobe Ok, tôi đã thêm mã. Tôi chỉ thay đổi tên tệp và số hàng mà dữ liệu bắt đầu. – jrovegno

Các vấn đề liên quan