2016-10-21 3 views
-3

UpdateПроблемы при преобразовании вложенного json/dict в формат кортежа?

Рассмотрим следующий dict. Как я могу извлечь 4-кортеж в соответствии с: lema, original_form, tag, и если и только если его настоящий id. До сих пор это то, что я пробовал:

def gettuples(data, level = 0): 
    if isinstance(data, dict): 
     if 'semtheme_list' in data: 
      print(data['semtheme_list'][0]) 
      yield data['semtheme_list'][0] 

     elif 'analysis_list' in data: 
      print(data['analysis_list'][0]) 
      yield data['analysis_list'][0] 

     for val in data.values(): 
      yield from gettuples(val) 

    elif isinstance(data, list): 
     for val in data: 
      yield from gettuples(val) 

с выше функции, я получаю следующее (*):

{'lemma': '*', 'tag': 'Z-----------', 'original_form': "Robert Downey Jr has topped Forbes magazine's annual list John Deere"} 
{'lemma': 'Robert Downey Jr', 'tag': 'GNUS3S--', 'original_form': 'Robert Downey Jr'} 
{'sense_id_list': [{'sense_id': '__12123288058840445720'}], 'lemma': 'Robert Downey Jr', 'tag': 'NPUU-N-', 'original_form': 'Robert Downey Jr'} 
{'lemma': 'top', 'tag': 'VI-S3PPA-N-N9', 'original_form': 'has topped'} 
{'lemma': 'John Deere', 'tag': 'GN-S3D--', 'original_form': "Forbes magazine's annual list John Deere"} 
{'lemma': 'magazine', 'tag': 'GN-S3---', 'original_form': 'Forbes magazine'} 
{'sense_id_list': [{'sense_id': 'db0f9829ff'}], 'lemma': 'Forbes', 'tag': 'NP-S-N-', 'original_form': 'Forbes'} 
{'type': 'Top>SocialSciences>Economy', 'id': 'ODTHEME_ECONOMY'} 

, который очень похож на 4-кортежа Ищу для (* *):

[[['Z-----------', "Robert Downey Jr has topped Forbes magazine's annual list John Deere", '*'], ['GNUS3S--', 'Robert Downey Jr', 'Robert Downey Jr'], ['NPUU-N-', 'Robert Downey Jr', 'Robert Downey Jr'], ['VI-S3PPA-N-N9', 'has topped', 'top'], ['GN-S3D--', "Forbes magazine's annual list John Deere", 'John Deere'], ['GN-S3---', 'Forbes magazine', 'magazine'], ['NP-S-N-', 'Forbes', 'Forbes'], ['NC-S-N5', 'magazine', 'magazine'], ['WN-', "'s", "'s"], ['GN-S3---', 'annual list John Deere', 'John Deere'], ['GN-S3---', 'annual list', 'list'], ['AP-N5', 'annual', 'annual'], ['NC-S-N5', 'list', 'list'], ['GN-S3Y--', 'John Deere', 'John Deere'], ['NP-S-N-', 'John Deere', 'John Deere']]] 

Но с entity_listid:

entity_list: [{ form: "John Deere", official_form: "Deere & Company", id: "d5250a54a8", sementity: { class: "instance", fiction: "nonfiction", id: "ODENTITY_INDUSTRIAL_COMPANY", type: "Top>Organization>Company>IndustrialCompany" 
} 

Затем, когда я печатаю:

result = [['lema:',obj['lemma'], 'original_form', obj['original_form'], 'tag:',obj['tag']] for obj in gettuples(json_data)] 

print(result) 

И я получаю эту ошибку:

File "/Users/user/PycharmProjects/Tests/test.py", line 51, in pos_tag2 
    result = [['lema:',obj['lemma'], 'original_form', obj['original_form'], 'tag:',obj['tag']] for obj in gettuples(json_data)] 
    File "/Users/user/PycharmProjects/Tests/test.py", line 51, in <listcomp> 
    result = [['lema:',obj['lemma'], 'original_form', obj['original_form'], 'tag:',obj['tag']] for obj in gettuples(json_data)] 
KeyError: 'lemma' 

Итак, мои вопросы: как я могу получить формат 4-кортежа, как (**), из (*)? или какой другой подход следует придерживаться, чтобы извлечь 4-кортеж, соответствующий lema, original_form, tag, и если и только если его присутствует id ?.

Update 2

Кроме того, другое дело, что я попытался было с json_normalize:

В:

from pandas.io.json import json_normalize 
df = json_normalize(request, ['token_list',['token_list']]) 
df = pd.DataFrame(df) 
df 

Out:

affected_by_negation analysis_list endp form id inip quote_level  separation style token_list type 
0 no [{'lemma': '*', 'tag': 'Z-----------', 'origin... 4 Deere 6 0 0 _ {'isTitle': 'no', 'isItalics': 'no', 'isUnderl... [{'form': 'Deere', 'analysis_list': [{'lemma':... phrase 

Тогда:

df_clean = df.drop(df.columns[[0, 2,4, 5, 6, 7, 8, 10]], axis=1) 
df_clean 
list(df_clean.itertuples(index=False)) 

Out:

[Pandas(analysis_list=[{'lemma': '*', 'tag': 'Z-----------', 'original_form': 'Deere'}], form='Deere', token_list=[{'form': 'Deere', 'analysis_list': [{'lemma': 'Edere', 'tag': 'GN-S3---', 'original_form': 'Deere'}, {'lemma': 'deer', 'tag': 'GN-S3---', 'original_form': 'Deere'}, {'lemma': 'Edere', 'tag': 'GN-P3---', 'original_form': 'Deere'}, {'lemma': 'deer', 'tag': 'GN-P3---', 'original_form': 'Deere'}, {'lemma': 'Edere', 'tag': 'GNFU3---', 'original_form': 'Deere'}], 'head': '1', 'separation': '_', 'affected_by_negation': 'no', 'endp': '4', 'type': 'phrase', 'style': {'isTitle': 'no', 'isItalics': 'no', 'isUnderlined': 'no', 'isBold': 'no'}, 'id': '5', 'inip': '0', 'token_list': [{'form': 'Deere', 'affected_by_negation': 'no', 'sense_list': [{'id': '228eaef205', 'info': 'sementity/[email protected][email protected][email protected]=Top>LivingThing>Animal>Vertebrate>Mammal\tsemld_list=sumo:Mammal\tsemtheme_list/[email protected]=Top>NaturalSciences>Zoology', 'form': 'deer'}, {'id': 'e7c6da7489', 'info': 'sementity/[email protected][email protected][email protected]=Top>Person>FirstName\tsemld_list=sumo:FirstName', 'form': 'Edere'}], 'separation': '_', 'style': {'isTitle': 'no', 'isItalics': 'no', 'isUnderlined': 'no', 'isBold': 'no'}, 'id': '1', 'inip': '0', 'topic_list': {'entity_list': [{'semld_list': ['sumo:FirstName'], 'form': 'Edere', 'sementity': {'id': 'ODENTITY_FIRST_NAME', 'class': 'instance', 'fiction': 'nonfiction', 'type': 'Top>Person>FirstName'}, 'id': 'e7c6da7489'}], 'concept_list': [{'semld_list': ['sumo:Mammal'], 'form': 'deer', 'semtheme_list': [{'id': 'ODTHEME_ZOOLOGY', 'type': 'Top>NaturalSciences>Zoology'}], 'sementity': {'id': 'ODENTITY_MAMMAL', 'class': 'class', 'fiction': 'nonfiction', 'type': 'Top>LivingThing>Animal>Vertebrate>Mammal'}, 'id': '228eaef205'}]}, 'analysis_list': [{'lemma': 'Edere', 'sense_id_list': [{'sense_id': 'e7c6da7489'}], 'tag': 'NPFS-N-', 'original_form': 'Edere', 'check_info': {'form_list': [{'form': 'Edere'}], 'tag': '6'}}, {'lemma': 'deer', 'sense_id_list': [{'sense_id': '228eaef205'}], 'tag': 'NC-S-N2', 'original_form': 'deer', 'check_info': {'form_list': [{'form': 'deer'}], 'tag': '6'}}, {'lemma': 'deer', 'sense_id_list': [{'sense_id': '228eaef205'}], 'tag': 'NC-P-N2', 'original_form': 'deer', 'check_info': {'form_list': [{'form': 'deer'}], 'tag': '6'}}], 'quote_level': '0', 'endp': '4'}], 'quote_level': '0'}])] 

Тем не менее, у меня возникли проблемы с доступом к конкретным значениям списков. Другое возможное решение может быть с пандами ... любая идея, как это сделать, ребята ?.

+1

Так что вы хотите четыре конкретные клавиши? –

+0

Спасибо за помощь @PadraicCunningham за конкретные ключи со значениями. –

+1

Значит, все они содержатся где-то в значениях 'analysis_list'? –

ответ

1

Следующий код должен делать то, что вы ищете. Это не самый элегантный подход, но, надеюсь, это понятно.

import yaml 
from pprint import pprint 

with open('json_dict.json', 'rU') as f: 
    data = yaml.load(f) 

results = [] 
sementity_map = {} 

def extract_analysis(l): 
    for d in l: 
     out = { 
      'lemma': d['lemma'], 
      'original_form': d['original_form'], 
      'tag': d['tag'] 
     } 

     if 'sense_id_list' in d: 
      out['id'] = d['sense_id_list'][0]['sense_id'] 

     results.append(out) 

def extract_entities(l): 
    for d in l: 
     if 'sementity' in d and 'id' in d['sementity']: 
      sementity_map[ d['id'] ] = d['sementity']['id'] 


def find_analysis_and_entities(d): 
    if type(d) != dict: # Added for non-dict values 
     return # Fail 

    for k, v in d.items(): 
     if type(v) == list: 
      if k == 'analysis_list': 
       extract_analysis(v) 
      elif k == 'entity_list': 
       extract_entities(v) 
      else: 
       for do in v: 
        find_analysis_and_entities(do) 
     else: 
      find_analysis_and_entities(v) 

def apply_entities(e, m): 
    for d in e: 
     if 'id' in d: 
      if d['id'] in sementity_map: 
       d['id'] = sementity_map[ d['id'] ] 
      else: 
       del d['id'] 

find_analysis_and_entities(data) 
apply_entities(results, sementity_map)     

pprint(results) 

Для семантических идентификаторов мы сохраняем отдельный словарь карт и применяем его после начального поиска. Первая находка используется для построения как результатов с голыми идентификаторами, так и карты семантической сущности.

Часть проблемы (я думаю) проистекает из того факта, что вы не можете быть уверены, что нашли/передали соответствующий семантический идентификатор объекта, прежде чем находите позицию, в которой он должен применяться (использование dicts не Помогите).

Здесь мы применяем только сопоставление идентификаторов, если они найдены, в противном случае мы отбрасываем это поле id. Например, как a0a1a5401f, так и __12123288058840445720 не указаны в блоке entity_list и поэтому удалены с results.

Выход из выше вашего примера входного файла:

[{'lemma': 'Robert Downey Jr', 
    'original_form': 'Robert Downey Jr', 
    'tag': 'NPUU-N-'}, 
{'lemma': 'Robert Downey Jr', 
    'original_form': 'Robert Downey Jr', 
    'tag': 'GNUS3S--'}, 
{'lemma': 'top', 'original_form': 'has topped', 'tag': 'VI-S3PPA-N-N9'}, 
{'id': 'ODENTITY_MAGAZINE', 
    'lemma': 'Forbes', 
    'original_form': 'Forbes', 
    'tag': 'NP-S-N-'}, 
{'lemma': 'magazine', 'original_form': 'magazine', 'tag': 'NC-S-N5'}, 
{'lemma': 'magazine', 'original_form': 'Forbes magazine', 'tag': 'GN-S3---'}, 
{'lemma': "'s", 'original_form': "'s", 'tag': 'WN-'}, 
{'lemma': 'annual', 'original_form': 'annual', 'tag': 'AP-N5'}, 
{'lemma': 'list', 'original_form': 'list', 'tag': 'NC-S-N5'}, 
{'lemma': 'list', 'original_form': 'annual list', 'tag': 'GN-S3---'}, 
{'id': 'ODENTITY_INDUSTRIAL_COMPANY', 
    'lemma': 'John Deere', 
    'original_form': 'John Deere', 
    'tag': 'NP-S-N-'}, 
{'lemma': 'John Deere', 'original_form': 'John Deere', 'tag': 'GN-S3Y--'}, 
{'lemma': 'John Deere', 
    'original_form': 'annual list John Deere', 
    'tag': 'GN-S3---'}, 
{'lemma': 'John Deere', 
    'original_form': "Forbes magazine's annual list John Deere", 
    'tag': 'GN-S3D--'}, 
{'lemma': '*', 
    'original_form': "Robert Downey Jr has topped Forbes magazine's annual list " 
        'John Deere', 
    'tag': 'Z-----------'}] 
+0

Я действительно пробовал другой подход ... Я обновил вопрос, проблема в том, что я получаю: 'RecursionError: максимальная глубина рекурсии '. –

+1

Получаете ли вы эту ошибку в приведенном примере или другом файле? – mfitzp

+0

Спасибо за помощь. Однако я не получаю 'id' от' sementity'. В этом случае это метка объекта, [this] (http://pastebin.com/Xaw4LwXj) - это текущий вывод. Для этого случая ожидаемые метки объектов: 'id: ODENTITY_INDUSTRIAL_COMPANY' и' id: "ODENTITY_MAGAZINE", –