python - 使用 pandas 和 json_normalize 来展平嵌套的 JSON API 响应

标签 python json pandas surveymonkey

我有一个嵌套很深的 JSON,我正尝试使用 json_normalize 将其转换为 Pandas Dataframe。

我正在处理的 JSON 数据的 generic sample 看起来像这样(我在帖子底部添加了我正在尝试做的事情的上下文):

{
    "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)在 JSON 数据中都是“id:”。

我确信这是可能的,但我做不到。有关如何执行此操作的任何示例?

其他上下文: 我正在尝试创建 SurveyMonkey API response output 的数据框。

我的长期目标是重新创建 "all responses" excel sheet that their export service provides

我计划通过设置响应数据框(如上),然后使用 .apply() 将响应与他们的 survey structure API output 匹配来实现这一点。

我发现 SurveyMonkey API 在提供有用的输出方面相当乏善可陈,但我是 Pandas 的新手,所以它可能在我身上。

最佳答案

您需要修改最后一个选项的 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'})

关于python - 使用 pandas 和 json_normalize 来展平嵌套的 JSON API 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53198931/

相关文章:

python - 每次在 Python 中运行代码时,如何以相同的顺序随机化 pandas 列?

python - Odoo 8 - 计算字段不使用 self.env 也不搜索

python - Python 中的 ITK : SimpleITK or not?

Python subprocess.Popen.wait() 即使发生错误也返回 0

javascript - 使用Jquery将序列化表单数据转换为json对象?

python - 根据多个其他列中特定范围内的日期的存在情况创建列

python - 将数据从套接字绘制到 TKinter 时,pickle 出现 EOFError

javascript - 使用点击时获得的 key 访问 javascript 对象

Javascript 输出(脚本编辑器 (MacOSX))不带引号

python - 在Chrome或Edge中,并非大数据框中的所有行都显示 Pandas 样式