繁体   English   中英

将 json 列转换为标准 pandas dataframe

[英]Convert json column into standard pandas dataframe

我有一个 pandas dataframe ,其中有一列 json 格式,如下所示。

ID 日期 性别 回复
1 2021 年 1 月 14 日 "{'score':3,'reason':{'description':array(['a','b','c'])}"
2 2020 年 5 月 16 日 F "{'score':4,'reason':{'description':array(['x','y','z'])}"

我想通过展平响应列中的字典将其转换为 dataframe。 字典以字符串形式存储在数据库中。

python 中是否有一种简单的方法可以将响应列转换为字典 object,然后将其展平为 dataframe,如下所示:

ID 日期 性别 分数 描述
1 2021 年 1 月 14 日 3 一个
1 2021 年 1 月 14 日 3 b
1 2021 年 1 月 14 日 3 c
2 2020 年 5 月 16 日 F 4 X
2 2020 年 5 月 16 日 F 4 是的
2 2020 年 5 月 16 日 F 4 z

鉴于您提供的 dataframe:

import pandas as pd

df = pd.DataFrame(
    {
        "id": [1, 2],
        "date": ["1/14/2021", "5/16/2020"],
        "gender": ["M", "F"],
        "response": [
            "{'score':3,'reason':{'description':array(['a','b','c'])}",
            "{'score':4,'reason':{'description':array(['x','y','z'])}",
        ],
    }
)

您可以定义 function 以展平response列中的值:

def flatten(data, new_data):
    """Recursive helper function.

    Args:
        data: nested dictionary.
        new_data: empty dictionary.

    Returns:
        Flattened dictionary.

    """
    for key, value in data.items():
        if isinstance(value, list):
            for item in value:
                flatten(item, new_data)
        if isinstance(value, dict):
            flatten(value, new_data)
        if (
            isinstance(value, str)
            or isinstance(value, int)
            or isinstance(value, ndarray)
        ):
            new_data[key] = value
    return new_data

And then, proceed like this using Numpy ndarrays to take care of the arrays and Python standard libray eval built-in function to make dictionaries from the strings in response column:

import numpy as np
from numpy import ndarray

# In your example, closing curly braces are missing, hence the "+ '}'"
df["response"] = df["response"].apply(
    lambda x: flatten(eval(x.replace("array", "np.array") + "}"), {})
)

# For each row, flatten nested dict, make a dataframe of it
# and concat it with non nested columns
# Then, concat all new dataframes
new_df = pd.concat(
    [
        pd.concat(
            [
                pd.DataFrame(df.loc[idx, :]).T.drop(columns="response"),
                pd.DataFrame(df.loc[idx, "response"]).reset_index(drop=True),
            ],
            axis=1,
        ).fillna(method="ffill")
        for idx in df.index
    ]
).reset_index(drop=True)

以便:

print(new_df)
# Output
   id       date gender  score description
0   1  1/14/2021      M      3           a
1   1  1/14/2021      M      3           b
2   1  1/14/2021      M      3           c
3   2  5/16/2020      F      4           y
4   2  5/16/2020      F      4           x
5   2  5/16/2020      F      4           z

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM