如何在熊猫中转换json对象的数组

时间:2018-08-06 15:45:06

标签: python pandas

我正在使用以下命令从数据源https://www.kaggle.com/tmdb/tmdb-movie-metadata中读取数据:

tmdbDataSet = pd.read_csv('tmdb_5000_movies.csv')

使用上述方法,某些列中的数据以json对象数组的形式出现,例如production_countries,关键字等。

如何将这些列转换为多列?

我正尝试如下所示:

pd.io.json.json_normalize(tmdbDataSet.production_companies.apply(json.loads))

但是我遇到了错误

  

AttributeError:“列表”对象没有属性“值”

编辑: 感谢杨的帮助。但是我观察到production_companies的最大数组长度为26,这不是您创建多个列所说明的有效方法。我已经使用下面的代码来找出长度。

length =0
for index, row in tmdbDataSet.iterrows():
    company = json.loads(row['production_companies'])
    if(len(company) > length):
        length = len(company)
print(length)

好像我需要寻找其他选择。但是我观察到口语栏有9个不同的值。我使用下面的代码创建了9个不同的列:

for i in range(9):
    tmdbDataSet['spoken_languages_' + str(i)] = ""

然后,当我运行以下代码时:

columns = ['spoken_languages_0','spoken_languages_1','spoken_languages_2','spoken_languages_3','spoken_languages_4','spoken_languages_5','spoken_languages_6','spoken_languages_7','spoken_languages_8']
tmdbDataSet[columns] = pd.DataFrame(tmdbDataSet.spoken_languages.values.tolist(), index= tmdbDataSet.index)
print(tmdbDataSet.head())

我得到一个错误:

  

列的长度必须与键的长度相同   这是可以理解的,因为我没有固定长度的数组。请让我知道可能的解决方案吗?

1 个答案:

答案 0 :(得分:1)

问题是您要在列表对象上调用json.loads。键入tmdbDataSet.production_companies时,它将从数据框中返回Series对象,您可以在(documentation here)上调用apply()方法。

但是,系列中的每个元素仍然是一个 list对象-当您注意到某些列包含JSON对象的 array 时,您惊讶地观察到了。因此,将函数json.loads应用于该系列将不起作用,因为json.loads期望使用JSON对象,而是接收一个列表对象。

不幸的是,这是由数据源进行的数据打包,但这可能是因为数组的长度可以根据行/电影而变化。 也许最好/最简单的访问此数据的方法是编写一个循环(即:for company in row['production_companies']:),而不是尝试将该列解压缩为多个数据框列。如果要解压缩该列而不丢失任何数据,则首先必须遍历该列并找到最长列表的长度,以便知道要创建多少个新列。您还会碰到数据框中大部分条目将为空白占位符的可能性,因为最长的数组长度可能只会出现一次或两次。

编辑: 但是,如果您必须融化数据框,可以采用以下建议的流程(抱歉,我没有个人时间来提供更多详细信息):

1)遍历production_companies列,找到最长长度为 k 的数组。

2)创建更多 k 个(空)列,以将JSON对象存储在数据框中。

3)再次遍历production_companies列,并遍历数组:         对于数组中的每个JSON项:             取出JSON文件并放入下一个可用的JSON列

请注意,由于许多电影的制作公司数量少于最高的制作公司,因此现在您的数据框中将有很多'nan's。