将熊猫JSON行转换为单独的列

时间:2019-06-20 19:45:38

标签: python json pandas dataframe

我有pandas数据框,其中的一列是JSON格式。它包含给定标题的电影制作公司的列表。在示例结构下方:

ID | production_companies
---------------
 1 | "[{'name': 'Paramount Pictures', 'id': 4}, {'name': 'United Artists', 'id': 60}, {'name': 'Metro-Goldwyn-Mayer (MGM)', 'id': 8411}]"
 2 | "[{'name': 'Walt Disney Pictures', 'id': 2}]"
 3 | "[{'name': 'Bold Films', 'id': 2266}, {'name': 'Blumhouse Productions', 'id': 3172}, {'name': 'Right of Way Films', 'id': 32157}]"
 4 | nan
 5 | nan
 6 | nan
 7 | "[{'name': 'Ghost House Pictures', 'id': 768}, {'name': 'North Box Productions', 'id': 22637}]"

如您所见,一部电影(行)可以有多个制作公司。我想为每部电影创建单独的列,其中包含制片人的名称。列应类似于:name_1,name_2,name_3等。如果没有第二个或第三个生产者,则应为NaN。

我在处理JSON格式方面经验不足,我尝试了几种方法(具有lambda函数的迭代器),但它们甚至与我所需的方法也不尽相同。

因此,我希望对您有所帮助!

编辑:

以下代码(“电影”是主数据库):

from pandas.io.json import json_normalize
companies = list(movies['production_companies'])
json_normalize(companies)

给我以下错误:

AttributeError: 'str' object has no attribute 'values'

2 个答案:

答案 0 :(得分:1)

在上述@Andy的答案上附加答案OP的问题。

这部分是@Andy制作的:

import pandas as pd
import numpy as np
import ast
import itertools

# dummy data
df = pd.DataFrame({
    "ID": [1,2,3],
    "production_companies": ["[{'name': 'Paramount Pictures', 'id': 4}, {'name': 'United Artists', 'id': 60}, {'name': 'Metro-Goldwyn-Mayer (MGM)', 'id': 8411}]", np.nan, "[{'name': 'Walt Disney Pictures', 'id': 2}]"]
})

# remove the nans
df.dropna(inplace=True)

# convert the strings into lists
df["production_companies"] = df["production_companies"].apply(lambda x: ast.literal_eval(x))

我为回答OP的要求而添加的内容:

tmp_lst = []
for idx, item in df.groupby(by='ID'):

    # Crediting this part to @Andy above
    tmp_df = pd.DataFrame(list(itertools.chain(*item["production_companies"].values.tolist()))).drop(columns='id')

    # Transpose dataframe
    tmp_df = tmp_df.T

    # Add back movie id to tmp_df
    tmp_df['ID'] = item['ID'].values

    # Accumulate tmp_df from all unique movie ids
    tmp_lst.append(tmp_df)

pd.concat(tmp_lst, sort=False)  

结果:

                         0               1                          2  ID
name    Paramount Pictures  United Artists  Metro-Goldwyn-Mayer (MGM)   1
name  Walt Disney Pictures             NaN                        NaN   3

答案 1 :(得分:0)

这应该做

import pandas as pd
import numpy as np
import ast
import itertools

# dummy data
df = pd.DataFrame({
    "ID": [1,2,3],
    "production_companies": ["[{'name': 'Paramount Pictures', 'id': 4}, {'name': 'United Artists', 'id': 60}, {'name': 'Metro-Goldwyn-Mayer (MGM)', 'id': 8411}]", np.nan, "[{'name': 'Walt Disney Pictures', 'id': 2}]"]
})

# remove the nans
df.dropna(inplace=True)

# convert the strings into lists
df["production_companies"] = df["production_companies"].apply(lambda x: ast.literal_eval(x))

# flatten the column of lists into a single list, and convert to DataFrame
pd.DataFrame(list(itertools.chain(*df["production_companies"].values.tolist())))

哪种产量:

    id      name
0   4       Paramount Pictures
1   60      United Artists
2   8411    Metro-Goldwyn-Mayer (MGM)
3   2       Walt Disney Pictures