2016-06-01 1 views
1

Пытается извлечь Total Cash and Cash Эквивалентные значения из сложного и беспорядочного списка словарей. Ниже приводится сокращенная версия структуры.Извлечь Значения из сильно вложенного списка словарей с двойными ключевыми парами значений

Я пробовал: карты, Dataframe.from_dict & .from_records. Попытка избежать использования RE.

Я в тупике.

[{u'Fields': [], 
 
    u'ReportDate': u'2 June 2016', 
 
    u'ReportID': u'BalanceSheet', 
 
    u'ReportName': u'Balance Sheet', 
 
    u'ReportTitles': [u'Balance Sheet', 
 
        u'Test Company', 
 
        u'As at 30 June 2016'], 
 
    u'ReportType': u'BalanceSheet', 
 
    u'Rows': [{u'Cells': [{u'Value': u''}, 
 
         {u'Value': u'30 Jun 2016'}, 
 
         {u'Value': u'30 Jun 2015'}], 
 
      u'RowType': u'Header'}, 
 
      {u'RowType': u'Section', u'Rows': [], u'Title': u'Assets'}, 
 
      {u'RowType': u'Section', 
 
      u'Rows': [{u'Cells': [{u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'c0bxx922-cc31-4d53-b060-cbf23511`2533'}], 
 
            u'Value': u'Test Bank 1'}, 
 
            {u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'c1b4xx22-cc31-4d53-b060-cb45282533'}], 
 
            u'Value': u'5555.20'}, 
 
            {u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'c2b44922-cc31-4d53-b060-cbf4532582533'}], 
 
            u'Value': u'5555.20'}], 
 
         u'RowType': u'Row'}, 
 
         {u'Cells': [{u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'290c7c3c-a712-4ads6f-9a2f-3d5258aad5a9e'}], 
 
            u'Value': u'Test Bank 2'}, 
 
            {u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'490c7c32-axxxdf6f-9a2f-3db682a3ad5a9e'}], 
 
            u'Value': u'55555.20'}, 
 
            {u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'490xxc3c-a71-adsf6f-9a2f-3d3aad5a9e'}], 
 
            u'Value': u'55555.20'}], 
 
         u'RowType': u'Row'}, 
 
         {u'Cells': [{u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'c6d4da40-f0df1b0-8f7d-xx45b1405'}], 
 
            u'Value': u'Test Bank 3'}, 
 
            {u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'c6d4da4fg-df-41b0-8f7d-54xx345b1405'}], 
 
            u'Value': u'5555.20'}, 
 
            {u'Attributes': [{u'Id': u'account', 
 
                u'Value': u'c6d4dafgss-9-41b0-8f7d-60xx5b1405'}], 
 
            u'Value': u'5555.20'}], 
 
         u'RowType': u'Row'}, 
 
        {u'Cells': [{u'Value': u'Total Cash and Cash Equivalents'}, 
 
           {u'Value': u'5555555.20'}, 
 
           {u'Value': u'5555555.20'}], 
 
        u'RowType': u'SummaryRow'}], 
 
      u'Title': u'Cash and Cash Equivalents'}, 
 
     {u'RowType': u'Section',

+1

Почему бы не использовать 'json'? – ZWiki

+0

Я застрял с этим выходом с сожалением. –

+0

Что такое дублирующие пары ключей? –

ответ

1

Если вы знаете, что данные будут иметь точно формат сверху, и вы на самом деле просто нужны эти два значения, вы можете получить к нему доступ непосредственно (при условии, data ваша выше структура):

print data[0]['Rows'][2]['Rows'][3]['Cells'][1]['Value'] 
print data[0]['Rows'][2]['Rows'][3]['Cells'][2]['Value'] 

Однако это связано с ошибкой, как при написании правильного выражения, так и в отношении изменений порядка списков (которые могут быть не определены в вашем формате). Поскольку за данными существует семантическая структура, вы можете перевести необработанные данные обратно в легкодоступный объект. Возможно, вы захотите изменить некоторые детали, но это хорошая отправная точка:

from collections import Mapping 
import pandas as pd 

class Report(Mapping): 
    def __init__(self, data): 
     self.sections = OrderedDict() 
     for row in data.pop('Rows'): 
      getattr(self, 'make_%s' % row['RowType'])(row) 
     self.__dict__.update(data) 

    def make_Header(self, row): 
     self.header = [c['Value'] for c in row['Cells']] 

    def make_Section(self, sec): 
     def make_row(row): 
      cells = [c['Value'] for c in row['Cells']] 
      return pd.Series(map(float, cells[1:]), name=cells[0]) 

     self.sections[sec['Title']] = pd.DataFrame(make_row(r) for r in sec['Rows']) 

    def __getitem__(self, item): 
     return self.sections[item] 

    def __len__(self): 
     return len(self.sections) 

    def __iter__(self): 
     return iter(self.sections) 


report = Report(data[0]) 
print report.ReportName 
print report['Cash and Cash Equivalents'] 
+0

Спасибо! Я был готов вытащить волосы. –

+0

В python3 вам нужно будет вызвать соответствующее пространство имен, например. collections.Mapping. –

+0

Вы имеете в виду collection.abc.Mapping. Btw. вы согласились бы с приведенным ответом в качестве решения? –