Как создать фрейм данных только из частей JSON? - PullRequest
0 голосов
/ 12 января 2019

В Python 3 у меня есть программа для доступа к API бразильских сенаторов Билла. Я собираюсь читать в JSON, а затем преобразовать в фрейм данных в пандах. Я так и сделал:

import requests
import pandas as pd

headers = {"Accept" : "application/json"}

proposals = []
url = 'http://legis.senado.leg.br/dadosabertos/materia/pesquisa/lista?ano=2010'

try:
    r = requests.get(url, headers=headers)
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc) 
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)  
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)

content = r.json()

for item in content["PesquisaBasicaMateria"]["Materias"]["Materia"]:
    dicionario = {"AnoMateria": str(item['IdentificacaoMateria']['AnoMateria']), 
                      "CodigoMateria": str(item['IdentificacaoMateria']['CodigoMateria']), 
                      "DescricaoIdentificacaoMateria": item['IdentificacaoMateria']['DescricaoIdentificacaoMateria'], 
                      "DescricaoObjetivoProcesso": item["DescricaoObjetivoProcesso"] if "DescricaoObjetivoProcesso" in item else None,
                      "DescricaoSubtipoMateria": item['IdentificacaoMateria']['DescricaoSubtipoMateria'], 
                      "IndicadorTramitando": item['IdentificacaoMateria']['IndicadorTramitando'], 
                      "NomeCasaIdentificacaoMateria": item['IdentificacaoMateria']['NomeCasaIdentificacaoMateria'], 
                      "NumeroMateria": str(item['IdentificacaoMateria']['NumeroMateria']), 
                      "ApelidoMateria": item['DadosBasicosMateria']['ApelidoMateria'] if 'ApelidoMateria' in item else None, 
                      "DataApresentacao": item['DadosBasicosMateria']['DataApresentacao'], 
                      "DataLeitura": item['DadosBasicosMateria']['DataLeitura'] if 'DataLeitura' in item else None,
                      "EmentaMateria": item['DadosBasicosMateria']['EmentaMateria'] if 'EmentaMateria' in item else None,
                      "ExplicacaoEmentaMateria": item['DadosBasicosMateria']['ExplicacaoEmentaMateria'] if 'ExplicacaoEmentaMateria' in item else None,
                      "IndicadorComplementar": item['DadosBasicosMateria']['IndicadorComplementar'] if 'IndicadorComplementar' in item else None,
                      "NaturezaMateria": item['DadosBasicosMateria']['NaturezaMateria'] if 'NaturezaMateria' in item else None,
                      "NomeAutor": item['AutoresPrincipais']['AutorPrincipal']['NomeAutor'] if 'NomeAutor' in item else None,
                      "SiglaTipoAutor": item['AutoresPrincipais']['AutorPrincipal']['SiglaTipoAutor'] if 'SiglaTipoAutor' in item else None,
                      "IndicadorOutrosAutores": item['AutoresPrincipais']['AutorPrincipal']['IndicadorOutrosAutores'] if 'IndicadorOutrosAutores' in item else None,
                      "CodigoParlamentar": str(item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['CodigoParlamentar']) if 'CodigoParlamentar' in item else None,
                      "NomeParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['NomeParlamentar'] if 'NomeParlamentar' in item else None,
                      "NomeCompletoParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['NomeCompletoParlamentar'] if 'NomeCompletoParlamentar' in item else None,
                      "UrlFotoParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['UrlFotoParlamentar'] if 'UrlFotoParlamentar' in item else None,
                      "UfParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['UfParlamentar'] if 'UfParlamentar' in item else None,
                      "DataSituacao": item['SituacaoAtual']['Autuacoes']['Autuacao']['Situacao']['DataSituacao'] if 'DataSituacao' in item else None,
                      "DescricaoSituacao": item['SituacaoAtual']['Autuacoes']['Autuacao']['Situacao']['DescricaoSituacao'] if 'DescricaoSituacao' in item else None
                      }
    proposals.append(dicionario)

df_projetos_api = pd.DataFrame(proposals)
df_projetos_api.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4216 entries, 0 to 4215
Data columns (total 25 columns):
AnoMateria                       4216 non-null object
ApelidoMateria                   0 non-null object
CodigoMateria                    4216 non-null object
CodigoParlamentar                0 non-null object
DataApresentacao                 4216 non-null object
DataLeitura                      0 non-null object
DataSituacao                     0 non-null object
DescricaoIdentificacaoMateria    4216 non-null object
DescricaoObjetivoProcesso        0 non-null object
DescricaoSituacao                0 non-null object
DescricaoSubtipoMateria          4216 non-null object
EmentaMateria                    0 non-null object
ExplicacaoEmentaMateria          0 non-null object
IndicadorComplementar            0 non-null object
IndicadorOutrosAutores           0 non-null object
IndicadorTramitando              4216 non-null object
NaturezaMateria                  0 non-null object
NomeAutor                        0 non-null object
NomeCasaIdentificacaoMateria     4216 non-null object
NomeCompletoParlamentar          0 non-null object
NomeParlamentar                  0 non-null object
NumeroMateria                    4216 non-null object
SiglaTipoAutor                   0 non-null object
UfParlamentar                    0 non-null object
UrlFotoParlamentar               0 non-null object
dtypes: object(25)
memory usage: 411.8+ KB

Это сработало, но у меня было две проблемы, которые я осознал позже:

1 - Фреймы данных "AutoresPrincipais_df" и "situacaoAtual_df" имеют подслои, различающиеся количеством ключей / столбцов

Примеры:

'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Eunício Oliveira',
       'SiglaTipoAutor': 'SENADOR',
       'UfAutor': 'CE',
       'IndicadorOutrosAutores': 'Não',
       'IdentificacaoParlamentar': {'CodigoParlamentar': '612',
        'NomeParlamentar': 'Eunício Oliveira',
        'NomeCompletoParlamentar': 'Eunício Lopes de Oliveira',
        'SexoParlamentar': 'Masculino',
        'FormaTratamento': 'Senador',
        'UrlFotoParlamentar': 'http://www.senado.leg.br/senadores/img/fotos-oficiais/senador612.jpg',
        'UrlPaginaParlamentar': 'http://www25.senado.leg.br/web/senadores/senador/-/perfil/612',
        'SiglaPartidoParlamentar': 'MDB',
        'UfParlamentar': 'CE'}}},

или

'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Ministério da Fazenda',
       'SiglaTipoAutor': 'MINISTERIO',
       'IndicadorOutrosAutores': 'Não'}},

Примеры situacaoAtual_df

'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
        'Situacao': {'DataSituacao': '2018-06-28',
         'CodigoSituacao': '107',
         'SiglaSituacao': 'CONHECIDA',
         'DescricaoSituacao': 'CONHECIDA.'},
        'Local': {'DataLocal': '2018-06-28',
         'CodigoLocal': '438',
         'SiglaCasaLocal': 'SF',
         'NomeCasaLocal': 'Senado Federal',
         'SiglaLocal': 'COARQ',
         'NomeLocal': 'Coordenação de Arquivo'}}}}},

или

'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
        'Situacao': {'DataSituacao': '2018-06-06',
         'CodigoSituacao': '25',
         'SiglaSituacao': 'APRVD',
         'DescricaoSituacao': 'APROVADA'},
        'Local': {'DataLocal': '2018-06-07',
         'CodigoLocal': '440',
         'SiglaCasaLocal': 'SF',
         'NomeCasaLocal': 'Senado Federal',
         'SiglaLocal': 'SEXPE',
         'NomeLocal': 'Secretaria de Expediente'}}}}},

2 - четыре кадра данных не имеют единого ключа для последующего объединения. Это означает, что мне нужно создать фрейм данных в порядке появления групп «IdentificacaoMateria», «DadosBasicosMateria», «AutoresPrincipais» и «situacaoAtual». Каждая группа этого в JSON - это строка в фрейме данных

Вот выдержка из начальных строк JSON

{'PesquisaBasicaMateria': {'@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
  '@xsi:noNamespaceSchemaLocation': 'http://legis.senado.gov.br/dadosabertos/dados/PesquisaBasicaMateriav5.xsd',
  'Metadados': {'Versao': '16/01/2019 12:38:14',
   'VersaoServico': '5',
   'DataVersaoServico': '2017-02-01',
   'DescricaoDataSet': 'Efetua a pesquisa de matérias, com a criação de um filtro através dos parâmetros que podem ser informados.\n      Se não informar parâmetro algum, não retorna conteúdo.'},
  'Materias': {'Materia': [{'IdentificacaoMateria': {'CodigoMateria': '132317',
      'SiglaCasaIdentificacaoMateria': 'SF',
      'NomeCasaIdentificacaoMateria': 'Senado Federal',
      'SiglaSubtipoMateria': 'ACE',
      'DescricaoSubtipoMateria': 'AVISO DA COMISSÃO DE EDUCAÇÃO',
      'NumeroMateria': '00001',
      'AnoMateria': '2018',
      'DescricaoIdentificacaoMateria': 'ACE 1/2018',
      'IndicadorTramitando': 'Não'},
     'DadosBasicosMateria': {'EmentaMateria': 'Avalia as medidas adotadas pelo Governo Federal e pelas prefeituras municipais para implementar as estratégias do Plano Nacional de Educação no que concerne à sua Meta 1 (educação infantil), bem como as medidas adotadas pelos entes federativos para promover o funcionamento de creches e pré-escolas construídas com recursos federais por meio do Proinfância.',
      'IndicadorComplementar': 'Não',
      'DataApresentacao': '2018-02-23',
      'NaturezaMateria': {'CodigoNatureza': '304',
       'NomeNatureza': 'DECISAO_TCU',
       'DescricaoNatureza': 'Decisão do Tribunal de Contas da União'}},
     'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Tribunal de Contas da União',
       'SiglaTipoAutor': 'TRIBUNAL_CONTAS_UNIAO',
       'IndicadorOutrosAutores': 'Não'}},
     'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
        'Situacao': {'DataSituacao': '2018-03-07',
         'CodigoSituacao': '107',
         'SiglaSituacao': 'CONHECIDA',
         'DescricaoSituacao': 'CONHECIDA.'},
        'Local': {'DataLocal': '2018-03-07',
         'CodigoLocal': '47',
         'SiglaCasaLocal': 'SF',
         'NomeCasaLocal': 'Senado Federal',
         'SiglaLocal': 'CE',
         'NomeLocal': 'Comissão de Educação, Cultura e Esporte'}}}}},
    {'IdentificacaoMateria': {'CodigoMateria': '133324',
      'SiglaCasaIdentificacaoMateria': 'SF',
      'NomeCasaIdentificacaoMateria': 'Senado Federal',
      'SiglaSubtipoMateria': 'ACE',
      'DescricaoSubtipoMateria': 'AVISO DA COMISSÃO DE EDUCAÇÃO',
      'NumeroMateria': '00002',
      'AnoMateria': '2018',
      'DescricaoIdentificacaoMateria': 'ACE 2/2018',
      'IndicadorTramitando': 'Não'},
     'DadosBasicosMateria': {'EmentaMateria': 'Analisa a regularidade do usufruto da isenção de contribuição para a seguridade social das entidades beneficentes de assistência social, com atuação preponderante na área de educação.',
      'IndicadorComplementar': 'Não',
      'DataApresentacao': '2018-05-18',
      'NaturezaMateria': {'CodigoNatureza': '304',
       'NomeNatureza': 'DECISAO_TCU',
       'DescricaoNatureza': 'Decisão do Tribunal de Contas da União'}},
     'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Tribunal de Contas da União',
       'SiglaTipoAutor': 'TRIBUNAL_CONTAS_UNIAO',
       'IndicadorOutrosAutores': 'Não'}},
     'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
        'Situacao': {'DataSituacao': '2018-07-10',
         'CodigoSituacao': '107',
         'SiglaSituacao': 'CONHECIDA',
         'DescricaoSituacao': 'CONHECIDA.'},
        'Local': {'DataLocal': '2018-07-10',
         'CodigoLocal': '47',
         'SiglaCasaLocal': 'SF',
         'NomeCasaLocal': 'Senado Federal',
         'SiglaLocal': 'CE',
         'NomeLocal': 'Comissão de Educação, Cultura e Esporte'}}}}},
    {'IdentificacaoMateria': {'CodigoMateria': '133655',
      'SiglaCasaIdentificacaoMateria': 'SF',
      'NomeCasaIdentificacaoMateria': 'Senado Federal',
      'SiglaSubtipoMateria': 'ACE',
      'DescricaoSubtipoMateria': 'AVISO DA COMISSÃO DE EDUCAÇÃO',
      'NumeroMateria': '00003',
      'AnoMateria': '2018',
      'DescricaoIdentificacaoMateria': 'ACE 3/2018',
      'IndicadorTramitando': 'Não'},
     'DadosBasicosMateria': {'EmentaMateria': 'Avalia a atuação do Ministério da Educação nos processos de regulação, supervisão e avaliação da educação superior, tendo como uma de suas referências a estratégia 12.19 do Plano Nacional de Educação.',
      'IndicadorComplementar': 'Não',
      'DataApresentacao': '2018-06-14',
      'NaturezaMateria': {'CodigoNatureza': '304',
       'NomeNatureza': 'DECISAO_TCU',
       'DescricaoNatureza': 'Decisão do Tribunal de Contas da União'}},
     'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Tribunal de Contas da União',
       'SiglaTipoAutor': 'TRIBUNAL_CONTAS_UNIAO',
       'IndicadorOutrosAutores': 'Não'}},
     'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
        'Situacao': {'DataSituacao': '2018-12-21',
         'CodigoSituacao': '28',
         'SiglaSituacao': 'ARQVD',
         'DescricaoSituacao': 'ARQUIVADA AO FINAL DA LEGISLATURA'},
        'Local': {'DataLocal': '2018-12-21',
         'CodigoLocal': '438',
         'SiglaCasaLocal': 'SF',
         'NomeCasaLocal': 'Senado Federal',
         'SiglaLocal': 'COARQ',
         'NomeLocal': 'Coordenação de Arquivo'}}}}},

...

Затем в Materia повторяются ключи «IdentificacaoMateria», «DadosBasicosMateria», «AutoresPrincipais» и «situacaoAtual», причем каждое повторение представляет собой строку кадра данных

Итак, я хочу создать фрейм данных, в котором каждая строка состоит из столбцов, которые находятся в «IdentificacaoMateria», «DadosBasicosMateria», «AutoresPrincipais» и «situacaoAtual», с его содержимым

Пожалуйста, возможно ли создать фрейм данных из документа JSON, чтобы просто выбрать несколько внутренних ключей?

То, как я это делал, с помощью различной информации от коллег, работало. Но вы можете видеть, что некоторые столбцы были совершенно пустыми. Я не поняла почему, так как не указала полный путь до информации

Ответы [ 3 ]

0 голосов
/ 14 января 2019

Есть два уровня для JSON. Первым является "PesquisaBasicaMateria". Таким образом, чтобы получить нужный словарь, вы используете:

mats = projects['PesquisaBasicaMateria']['Materias']

А затем посмотрите или получите каждую "Материю" из mats.

materia = mats['Materia']

Это список, который вы должны распаковать еще дальше.

dict_l = [d['IdentificacaoMateria'] for d in mat]
df = pd.DataFrame(dict_l)

Это дает вам DataFrame из 10 столбцов и пяти строк. Столбцы:

['AnoMateria', 'CodigoMateria', 'DescricaoIdentificacaoMateria', 'DescricaoObjetivoProcesso', 'DescricaoSubtipoMateria', 'IndicadorTramitando', 'NomeCasaIdentificacaoMateria', 'NumeroMateria', 'SiglaCasaIdentificacaoMateria', 'SiglaSubtipoMateria']

0 голосов
/ 15 января 2019

Копая ответ JSON на Materia, мы находим список:

the_json["PesquisaBasicaMateria"]["Materias"]["Materia"]

В тестируемом образце содержалось 3014 items, каждый из которых представлял собой словарь с 2-4 из следующих ключей:

['IdentificacaoMateria', 'DadosBasicosMateria', 'AutoresPrincipais', 'SituacaoAtual']
['IdentificacaoMateria', 'DadosBasicosMateria', 'AutoresPrincipais']
['IdentificacaoMateria', 'DadosBasicosMateria', 'SituacaoAtual']
['IdentificacaoMateria', 'DadosBasicosMateria']

Каждый из этих 4 типов содержит уникальные поля, и, не зная больше о данных или вашем желании, трудно спроектировать, как вы хотите, чтобы эти данные были объединены в одном наборе записей.

Тем не менее, вы могли бы начать с просмотра 4 типов Materia в их собственных соответствующих фреймах данных, например:

the_records = {
    "IdentificacaoMateria": [],
    "DadosBasicosMateria":  [],
    "AutoresPrincipais":    [],
    "SituacaoAtual":        []
}
for item in the_json["PesquisaBasicaMateria"]["Materias"]["Materia"]:
    for subkey in item.keys():
        the_records[subkey].append(item[subkey])

IdentificacaoMateria_df = pd.DataFrame(the_records["IdentificacaoMateria"])
DadosBasicosMateria_df  = pd.DataFrame(the_records["DadosBasicosMateria"])
AutoresPrincipais_df    = pd.DataFrame(the_records["AutoresPrincipais"])
SituacaoAtual_df        = pd.DataFrame(the_records["SituacaoAtual"])

Тогда, может быть, взглянем на: https://pandas.pydata.org/pandas-docs/stable/merging.html и поэкспериментируйте с pd.concat, чтобы объединить записи так, как вы хотите.

0 голосов
/ 12 января 2019

Вы можете просто получить доступ к этому ключу и построить оттуда фрейм данных:

projects = r.json()

mats = projects.get('Materias') # This is a dictionary

if not mats:
    raise ValueError("Didn't find anything in 'Materias')

mats_list = mats.get('Materia') # This should be a list of dictionaries

if not mats_list:
    raise ValueError("Got None or empty list in 'Materia'")

df = pd.DataFrame(mats_list)

Предполагается, что структура json выглядит следующим образом:

{ 'Materias': {
     'Materia': [ # interesting dictionaries]
    }
}

Если вложение идет дальше, как кажется, это может быть немного сложнее

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...