pandas 如何在DataFrame中扁平化dict并连接所有结果行

c90pui9n  于 2023-01-07  发布在  其他
关注(0)|答案(2)|浏览(143)

我正在使用Github的GraphQL API获取一些问题细节。
我使用Python Requests在本地获取数据。

{
    "data": {
        "viewer": {
            "login": "some_user"
        },
        "repository": {
            "issues": {
                "edges": [
                    {
                        "node": {
                            "id": "I_kwDOHQ63-s5auKbD",
                            "title": "test issue 1",
                            "number": 146,
                            "createdAt": "2023-01-06T06:39:54Z",
                            "closedAt": null,
                            "state": "OPEN",
                            "updatedAt": "2023-01-06T06:42:00Z",
                            "comments": {
                                "edges": [
                                    {
                                        "node": {
                                            "id": "IC_kwDOHQ63-s5R2XCV",
                                            "body": "comment 01"
                                        }
                                    },
                                    {
                                        "node": {
                                            "id": "IC_kwDOHQ63-s5R2XC9",
                                            "body": "comment 02"
                                        }
                                    }
                                ]
                            },
                            "labels": {
                                "edges": []
                            }
                        },
                        "cursor": "Y3Vyc29yOnYyOpHOWrimww=="
                    },
                    {
                        "node": {
                            "id": "I_kwDOHQ63-s5auKm8",
                            "title": "test issue 2",
                            "number": 147,
                            "createdAt": "2023-01-06T06:40:34Z",
                            "closedAt": null,
                            "state": "OPEN",
                            "updatedAt": "2023-01-06T06:40:34Z",
                            "comments": {
                                "edges": []
                            },
                            "labels": {
                                "edges": [
                                    {
                                        "node": {
                                            "name": "food"
                                        }
                                    },
                                    {
                                        "node": {
                                            "name": "healthy"
                                        }
                                    }
                                ]
                            }
                        },
                        "cursor": "Y3Vyc29yOnYyOpHOWripvA=="
                    }
                ]
            }
        }
    }
}

json被放入一个列表中

result = response.json()["data"]["repository"]["issues"]["edges"]

然后这个列表被放到一个DataFrame中

import pandas as pd
df = pd.DataFrame (result, columns = ['node', 'cursor'])
df

这些是数据框的内容
| 身份证|标题|数|创建时间|关闭时间|状态|更新时间|评论|标号|
| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------|
| I_kwDOHQ63-s5auKbD|测试问题1|一百四十六|2023年01月06日星期六06:39:54|无|开放|2023年1月6日星期一06:42:00中文|{"边":[{"节点":{"标识":" IC_kwDOHQ63-s5R2XCV ","正文":"注解01 "}},{"节点":{"标识":" IC_kwDOHQ63-s5R2XC9 ","正文":"注解02 "}}]}| {"边缘":[]}|
| I_kwDOHQ63 - 5auKm8|测试问题2|一百四十七|2023年1月6日星期一06:40:34中文|无|开放|2023年1月6日星期一06:40:34中文|{"边缘":[]}| {"边":[{"节点":{"名称":"食物"}},{"节点":{"名称":"健康"}}]}|
我想拆分/分解commentslabels列。这些列中的值是嵌套字典
我希望在一个问题中有commentslabels一样多的行。我希望数据框扁平化。这涉及到拆分/分解和concat。
有几个stackoverflow的答案深入到这个主题。我已经尝试了其中几个的代码。我不能粘贴到这些问题的链接,因为stackoverflow标记我的问题为垃圾邮件,由于许多链接。但这些是我已经尝试过的步骤

df3 = df2['comments'].apply(pd.Series)

进一步深入

df4 = df3['edges'].apply(pd.Series)
df4

进一步深入

df5 = df4['node'].apply(pd.Series)
df5

上面的最后一条语句给出了我所理解的KeyError: 'node',这是因为node不是DataFrame中的键。
但是,我还能如何拆分这个字典并将所有列连接回issues行呢?这就是我希望输出的样子
| 身份证|标题|数|创建时间|关闭时间|状态|更新时间|评论|标号|
| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------|
| I_kwDOHQ63-s5auKbD|测试问题1|一百四十六|2023年01月06日星期六06:39:54|无|开放|2023年1月6日星期一06:42:00中文|注解01|无效|
| I_kwDOHQ63-s5auKbD|测试问题1|一百四十六|2023年01月06日星期六06:39:54|无|开放|2023年1月6日星期一06:42:00中文|备注02|无效|
| I_kwDOHQ63 - 5auKm8|测试问题2|一百四十七|2023年1月6日星期一06:40:34中文|无|开放|2023年1月6日星期一06:40:34中文|无效|食物|
| I_kwDOHQ63 - 5auKm8|测试问题2|一百四十七|2023年1月6日星期一06:40:34中文|无|开放|2023年1月6日星期一06:40:34中文|无效|健康|

fnx2tebb

fnx2tebb1#

如果dct是问题中的字典,您可以尝试:

df = pd.DataFrame(d['node'] for d in dct['data']['repository']['issues']['edges'])
df['comments'] = df['comments'].str['edges']
df = df.explode('comments')
df['comments'] = df['comments'].str['node'].str['body']

df['labels'] = df['labels'].str['edges']
df = df.explode('labels')
df['labels'] = df['labels'].str['node'].str['name']

print(df.to_markdown(index=False))

图纸:
| 身份证|标题|数|创建时间|关闭时间|状态|更新时间|评论|标号|
| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------| - ------|
| I_kwDOHQ63-s5auKbD|测试问题1|一百四十六|2023年01月06日星期六06:39:54||开放|2023年1月6日星期一06:42:00中文|注解01|楠|
| I_kwDOHQ63-s5auKbD|测试问题1|一百四十六|2023年01月06日星期六06:39:54||开放|2023年1月6日星期一06:42:00中文|备注02|楠|
| I_kwDOHQ63 - 5auKm8|测试问题2|一百四十七|2023年1月6日星期一06:40:34中文||开放|2023年1月6日星期一06:40:34中文|楠|食物|
| I_kwDOHQ63 - 5auKm8|测试问题2|一百四十七|2023年1月6日星期一06:40:34中文||开放|2023年1月6日星期一06:40:34中文|楠|健康|

lpwwtiir

lpwwtiir2#

@andrej-kesely已经回答了我的问题。
我选择他的回答作为这个问题的答案。
我现在发布一个整合的脚本,其中包括我的糟糕代码和andrej的伟大代码。
在这个脚本中,我想从Github's GraphQL API Server获取详细信息。
把它放进Pandas体内。
此脚本的主要来源是gist
剩余代码的主要部分是answer by @andrej-kesely。现在来看合并脚本。
首先导入必要的包并设置头文件

import requests
import json
import pandas as pd

headers = {"Authorization": "token <your_github_personal_access_token>"}

现在定义从github获取数据的查询。
在我的特殊情况下,我正在获取特定回购协议的发行细节,它可以是其他东西给你。

query = """
{
  viewer {
    login
  }
repository(name: "your_github_repo", owner: "your_github_user_name") {
  issues(states: OPEN, last: 2) {
    edges {
      node {
        id
        title
        number
        createdAt
        closedAt
        state
        updatedAt
        comments(first: 10) {
          edges {
            node {
              id
              body
            }
          }
        }
        labels(orderBy: {field: NAME, direction: ASC}, first: 10) {
          edges {
            node {
              name
            }
          }
        }
        comments(first: 10) {
          edges {
            node {
              id
              body
            }
          }
        }
      }
      cursor
    }
  }
}
}
"""

执行查询并保存响应

def run_query(query):
    request = requests.post('https://api.github.com/graphql', json={'query': query}, headers=headers)
    if request.status_code == 200:
        return request.json()
    else:
        raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query))

result = run_query(query)

现在是最棘手的部分。
在我的查询响应中,有几个嵌套的字典。
我想把它们分开--更多细节见我上面的问题。
来自@andrej-kesely的这段神奇的代码可以帮你做到这一点。

df = pd.DataFrame(d['node'] for d in result['data']['repository']['issues']['edges'])
df['comments'] = df['comments'].str['edges']
df = df.explode('comments')
df['comments'] = df['comments'].str['node'].str['body']

df['labels'] = df['labels'].str['edges']
df = df.explode('labels')
df['labels'] = df['labels'].str['node'].str['name']

print(df)

相关问题