我正在使用以下命令从数据源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())
我得到一个错误:
列的长度必须与键的长度相同 这是可以理解的,因为我没有固定长度的数组。请让我知道可能的解决方案吗?
答案 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。