Python 如何将JSON列转换为数据帧?

Python 如何将JSON列转换为数据帧?,python,json,pandas,Python,Json,Pandas,我有一个混合列的.csv文件,其中一些包含JSON语法的条目(嵌套)。我想从这些列中提取相关数据,以获得数据更丰富的数据框架,以便进一步分析。我已经检查过了,但是没有得到想要的结果 为了更好地解释我的问题,我在下面准备了一个数据库的虚拟版本 raw = {"team":["Team_1","Team_2"], "who":[[{"name":"Andy", "age":22},{"name":"Rick", "age":30}],[{"name":"Oli", "age":19},

我有一个混合列的.csv文件,其中一些包含JSON语法的条目(嵌套)。我想从这些列中提取相关数据,以获得数据更丰富的数据框架,以便进一步分析。我已经检查过了,但是没有得到想要的结果

为了更好地解释我的问题,我在下面准备了一个数据库的虚拟版本

raw = {"team":["Team_1","Team_2"],
       "who":[[{"name":"Andy", "age":22},{"name":"Rick", "age":30}],[{"name":"Oli", "age":19},{"name":"Joe", "age":21}]]}

df = pd.DataFrame(raw)
我想生成以下列(或等效列):

我试过以下方法

代码1:

test_norm = json_normalize(data=df)
AttributeError: 'str' object has no attribute 'values'
test_norm = json_normalize(data=df, record_path='who')
TypeError: string indices must be integers
test_norm = json_normalize(data=df, record_path='who', meta=[team])
TypeError: string indices must be integers
代码2:

test_norm = json_normalize(data=df)
AttributeError: 'str' object has no attribute 'values'
test_norm = json_normalize(data=df, record_path='who')
TypeError: string indices must be integers
test_norm = json_normalize(data=df, record_path='who', meta=[team])
TypeError: string indices must be integers
代码3:

test_norm = json_normalize(data=df)
AttributeError: 'str' object has no attribute 'values'
test_norm = json_normalize(data=df, record_path='who')
TypeError: string indices must be integers
test_norm = json_normalize(data=df, record_path='who', meta=[team])
TypeError: string indices must be integers

有什么方法可以有效地做到这一点吗?我在其他stackoverflow主题中寻找了一个解决方案,但我找不到使用json_normalize的有效解决方案。

我在
who
列中包含的DICT列表中使用json_normalize时也遇到了问题。我的解决方法是将每一行重新格式化为一个Dict,每个团队成员的姓名/年龄都有唯一的键(
name\u 1
age\u 1
name\u 2
,等等)。在此之后,创建具有所需结构的数据帧是很简单的

这是我的步骤。从你的例子开始:

raw = {"team":["Team_1","Team_2"],
       "who":[[{"name":"Andy", "age":22},{"name":"Rick", "age":30}],[{"name":"Oli", "age":19},{"name":"Joe", "age":21}]]}

df = pd.DataFrame(raw)
df

    team    who
0   Team_1  [{'name': 'Andy', 'age': 22}, {'name': 'Rick',...
1   Team_2  [{'name': 'Oli', 'age': 19}, {'name': 'Joe', '...
  • 编写一个方法,将列表重新格式化为Dict,并应用于
    who
    列中的每一行:
  • who
    列上使用json_normalize。然后确保规范化数据帧的列按所需顺序显示:
  • 将json_normalize创建的数据帧连接回原始df,并删除
    who
    列:

  • 如果您的real.csv文件有太多行,那么我的解决方案可能有点太贵(看看它是如何迭代每一行,然后迭代每一行中包含的列表中的每个条目的)。如果(希望)情况不是这样,也许我的方法就足够好了。

    一个选择是自己打开字典。像这样:

    from pandas.io.json import json_normalize 
    
    raw = {"team":["Team_1","Team_2"],
           "who":[[{"name":"Andy", "age":22},{"name":"Rick", "age":30}],[{"name":"Oli", "age":19},{"name":"Joe", "age":21}]]}
    
    
    # add the corresponding team to the dictionary containing the person information
    for idx, list_of_people in enumerate(raw['who']):
        for person in list_of_people:
            person['team'] = raw['team'][idx]
    
    # flatten the dictionary
    list_of_dicts = [dct for list_of_people in raw['who'] for dct in list_of_people]
    
    # normalize to dataframe
    json_normalize(list_of_dicts)
    
    # due to unpacking of dict, this results in the same as doing
    pd.DataFrame(list_of_dicts)
    
    这输出有点不同。我的输出通常更便于进一步分析

    输出:

    age name    team
    22  Andy    Team_1
    30  Rick    Team_1
    19  Oli     Team_2
    21  Joe     Team_2
    
    
    age_0   name_0  age_1   name_1  team
    22      Andy    30      Rick    Team_1
    19      Oli     21      Joe     Team_2
    

    您可以分别迭代
    raw['who']
    中的每个元素,但当您这样做时,生成的数据帧将在单独的行中包含两个对手

    例如:

    json_normalize(raw['who'][0])
    
    Output:
    
    age     name
    22      Andy
    30      Rick
    
    您可以将这些行展平为一行,然后连接所有行以获得最终输出

    def flatten(df_temp):
        df_temp.index = df_temp.index.astype(str)
        flattened_df = df_temp.unstack().to_frame().sort_index(level=1).T
        flattened_df.columns = flattened_df.columns.map('_'.join)
        return flattened_df
    
    df = pd.concat([flatten(pd.DataFrame(json_normalize(x))) for x in raw['who']])
    df['team'] = raw['team']
    
    输出:

    age name    team
    22  Andy    Team_1
    30  Rick    Team_1
    19  Oli     Team_2
    21  Joe     Team_2
    
    
    age_0   name_0  age_1   name_1  team
    22      Andy    30      Rick    Team_1
    19      Oli     21      Joe     Team_2
    
    可能重复的