Использование pandas и json_normalize для выравнивания вложенного ответа JSON API - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть глубоко вложенный JSON, который я пытаюсь превратить в Pandas Dataframe, используя json_normalize .

A обобщенный образец данных JSON, с которыми я работаю, выглядит следующим образом (я добавил контекст того, что я пытаюсь сделать, внизу поста):

{
    "per_page": 2,
    "total": 1,
    "data": [{
            "total_time": 0,
            "collection_mode": "default",
            "href": "https://api.surveymonkey.com/v3/responses/5007154325",
            "custom_variables": {
                "custvar_1": "one",
                "custvar_2": "two"
            },
            "custom_value": "custom identifier for the response",
            "edit_url": "https://www.surveymonkey.com/r/",
            "analyze_url": "https://www.surveymonkey.com/analyze/browse/",
            "ip_address": "",
            "pages": [
                {
                    "id": "103332310",
                    "questions": [{
                            "answers": [{
                                    "choice_id": "3057839051"
                                }
                            ],
                            "id": "319352786"
                        }
                    ]
                },
                {
                    "id": "44783164",
                    "questions": [{
                            "id": "153745381",
                            "answers": [{
                                    "text": "some_name"
                                }
                            ]
                        }
                    ]
                },
                {
                    "id": "44783183",
                    "questions": [{
                            "id": "153745436",
                            "answers": [{
                                    "col_id": "1087201352",
                                    "choice_id": "1087201369",
                                    "row_id": "1087201362"
                                }, {
                                    "col_id": "1087201353",
                                    "choice_id": "1087201373",
                                    "row_id": "1087201362"
                                }
                                ]
                            }
                        ]
                }
            ],
            "date_modified": "1970-01-17T19:07:34+00:00",
            "response_status": "completed",
            "id": "5007154325",
            "collector_id": "50253586",
            "recipient_id": "0",
            "date_created": "1970-01-17T19:07:34+00:00",
            "survey_id": "105723396"
        }
    ],
    "page": 1,
    "links": {
        "self": "https://api.surveymonkey.com/v3/surveys/123456/responses/bulk?page=1&per_page=2"
    }
}

Я хотел бы получить фрейм данных, который содержит question_id, page_id, response_id и данные ответа, такие как:

    choice_id      col_id      row_id       text   question_id       page_id      response_id
0  3057839051         NaN         NaN        NaN     319352786     103332310       5007154325
1         NaN         NaN         NaN  some_name     153745381      44783164       5007154325
2  1087201369  1087201352  1087201362        NaN     153745436      44783183       5007154325
3  1087201373  1087201353  1087201362        NaN     153745436      44783183       5007154325

Я могу приблизиться, запустив следующий код (Python 3.6):

df = json_normalize(data=so_survey_responses['data'], record_path=['pages', 'questions'], meta='id', record_prefix ='question_')
print(df)

Что возвращает:

                                    question_answers question_id          id
0                      [{'choice_id': '3057839051'}]   319352786  5007154325
1                            [{'text': 'some_name'}]   153745381  5007154325
2  [{'col_id': '1087201352', 'choice_id': '108720...   153745436  5007154325

Но если я попытаюсь запустить json_normalize в более глубоком гнезде и сохранить данные 'question_id' из вышеприведенного результата, я смогу получить только значения page_id, но не истинные значения question_id:

answers_df = json_normalize(data=so_survey_responses['data'], record_path=['pages', 'questions', 'answers'], meta=['id', ['questions', 'id'], ['pages', 'id']])
print(answers_df)

Возвращает:

    choice_id      col_id      row_id       text          id questions.id   pages.id
0  3057839051         NaN         NaN        NaN  5007154325    103332310  103332310
1         NaN         NaN         NaN  some_name  5007154325     44783164   44783164
2  1087201369  1087201352  1087201362        NaN  5007154325     44783183   44783183
3  1087201373  1087201353  1087201362        NaN  5007154325     44783183   44783183

Осложняющим фактором может быть то, что все вышеперечисленное (question_id, page_id, response_id) является 'id:' в данных JSON.

Я уверен, что это возможно, но я не могу туда добраться. Какие-нибудь примеры, как это сделать?

Дополнительный контекст: Я пытаюсь создать фрейм данных для ответа от SurveyMonkey API .

Моя долгосрочная цель состоит в том, чтобы заново создать лист Excel "1035 *" все ответы ", который предоставляет их служба экспорта .

Я планирую сделать это, настроив фрейм данных ответа (см. Выше), а затем использую .apply () , чтобы сопоставить ответы с их выходными данными API структуры опроса .

Я нашел SurveyMonkey API довольно тусклым в предоставлении полезного вывода, но я новичок в Pandas, так что, вероятно, на мне.

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Вам нужно изменить параметр meta вашего последнего параметра, и, если вы хотите переименовать столбцы в соответствии с вашими желаниями, вы можете сделать это с помощью rename:

answers_df = json_normalize(data=so_survey_responses['data'],
                        record_path=['pages', 'questions', 'answers'],
                        meta=['id', ['pages', 'questions', 'id'], ['pages', 'id']])\
.rename(index=str,
        columns={'id': 'response_id', 'pages.questions.id': 'question_id', 'pages.id': 'page_id'})
0 голосов
/ 12 ноября 2018

Нет способа сделать это полностью универсальным способом, используя json_normalize(). Вы можете использовать аргументы record_path и meta, чтобы указать, как вы хотите обрабатывать JSON.

Однако вы можете использовать пакет flatten , чтобы сгладить глубоко вложенный JSON, а затем преобразовать его в фрейм данных Pandas. На странице есть пример использования того, как сгладить глубоко вложенный JSON и преобразовать в фрейм данных Pandas.

...