【问题标题】:Flatten list of JSONs stored in pandas cell扁平化存储在 pandas 单元格中的 JSON 列表
【发布时间】:2019-08-13 12:51:19
【问题描述】:

我有一个 pandas 数据框,其中一列包含存储为字符串的 JSON 列表,我无法尝试将其展平为列。

JSON 列如下所示

[{'id':'item1','xp':'27097','lvl':'26','items':[]},
{'id':'item2','xp':'40650','lvl':'26','items':[]},
{'id':'item3','xp':'33900','lvl':'26','items':['item1', 'item2', 'item3']}]

这里是DF的截图(不能放图片,声望不够)https://i.imgur.com/1YNgXWE.png

json_normalize 在这里不起作用,因为它是嵌套在 pandas 数据帧中的字符串

预期结果:

+-----------+-------+-----+-----+-----------------------------+
| player_id |  id   | xp  | lvl |            items            |
+-----------+-------+-----+-----+-----------------------------+
| id1       | item1 | 444 |  10 | []                          |
| id1       | item2 |  12 |  77 | []                          |
| id1       | item3 |  15 |  20 | ['item1', 'item2', 'item3'] |
+-----------+-------+-----+-----+-----------------------------+

对于每个 id,我想将此列表展平为列并获取列表 if 项及其参数。

以下代码适用于单个 JSON,不适用于列表:

df = (pd.DataFrame([ast.literal_eval(x)[0] for x in original_df.pop('items')])
         .add_prefix('items.'))

【问题讨论】:

  • 不要链接到DF的屏幕截图,而是粘贴DF的一些示例数据
  • 您原来的player_id DataFrame 是如何格式化的?上面的列表长度是否与 DataFrame 的长度相同?
  • 是的,IMCoins,原始数据集具有唯一 ID,没有重复。
  • 你的问题解决了吗?
  • 您好,很抱歉回复晚了!是的,它有帮助,但我不得不修改解决方案,因为带有 JSON 的单元格包含 JSON 列表(在原始帖子中)。非常感谢您的时间和帮助

标签: python json pandas


【解决方案1】:

由于我们没有原始数据,我不得不重新创建它,并假设它会被格式化为这样。对此类对象执行pd.DataFrame(data) 会在您的图像中产生相同的数据。

但是,我正确地使用了pandas.io.json.json_normalize 并且它起作用了。我只是无法围绕meta_prefix 参数,如果我要求它应该剥离键的名称('意思是,避免'id' 变成'items.id')。但由于我无法使其工作,我只是创建了一个迭代列并正确重命名它们的函数。

EDIT :由于items 键是str 而不是dict,我看到的唯一解决方案是将所有字符串转换为字典。前段时间我遇到了同样的问题,找不到其他解决方案。当时我对它进行了大量的基准测试,但总体来说还是相当快的。查看更新的代码。

import json
from pandas.io.json import json_normalize

data = [
    {
        'player_id' : 'id1',
        'items' : '{"id" : "item1", "xp" : "27097", "lvl" : "26", "items":[]}'
    },
    {
        'player_id' : 'id2',
        'items' : '{"id":"item2","xp":"40650","lvl":"26","items":[]}'
    },
    {
        'player_id' : 'id3',
        'items' : '{"id":"item3","xp":"33900","lvl":"26","items":["item1", "item2", "item3"]}'
    }
]

for idx in range(len(data)):
    data[idx]['items'] = json.loads(data[idx]['items'])

df = json_normalize(data, meta='items')
#  player_id items.id items.xp items.lvl            items.items
#0       id1    item1    27097        26                     []
#1       id2    item2    40650        26                     []
#2       id3    item3    33900        26  [item1, item2, item3]

prefix = 'items.'
df.columns = [col[len(prefix):] if col.startswith(prefix) else col for col in df.columns]

print(df)
#   player_id     id     xp lvl                  items
# 0       id1  item1  27097  26                     []
# 1       id2  item2  40650  26                     []
# 2       id3  item3  33900  26  [item1, item2, item3]

【讨论】:

  • 您好!感谢您的回答,但它不起作用,因为熊猫单元格中的数据存储为字符串,这是我可以使用这些数据的唯一方法
  • @Jake_A1997 你的意思是items里面的字典是一个字符串吗?
  • 是的,完全正确。项目中的数据存储为字符串
  • @Jake_A1997 好吧,我有好消息和坏消息。阅读我的答案。 :)
【解决方案2】:

我在这里有答案。第 1 部分我重新创建数据,第 2 部分我回答问题

第 1 部分 - 创建数据集

In [1]:
import pandas as pd
row_1 = "[{'id':'item1','xp':'27097','lvl':'26','items':[]}]"
row_2 = "[{'id':'item2','xp':'40650','lvl':'12','items':[]}]"
row_3 = "[{'id':'item3','xp':'33900','lvl':'45','items':['item1', 'item2', 'item3']}]"

data = {"My Dict":[row_1, row_2, row_3]}
df = pd.DataFrame(data)
df

Out [1]:
    My Dict
0   [{'id':'item1','xp':'27097','lvl':'26','items'...
1   [{'id':'item2','xp':'40650','lvl':'12','items'...
2   [{'id':'item3','xp':'33900','lvl':'45','items'...

第 2 部分 - 将这一系列 Dict 转换为 Dataframe

In [2]:
from ast import literal_eval

my_list = df['My Dict'].tolist()

list_of_dict = []
## Get a list of dict instead of a list of list of dict 
for elem in my_list:
    my_dict = literal_eval(elem)[0]
    list_of_dict.append(my_dict)

## Turn this list of dict into 1 Dict
new_dict = {}
for item in list_of_dict:
    name = item.pop('id')
    new_dict[name] = item  



## Create a dataframe from this dict 
my_df = pd.DataFrame(new_dict).T.reset_index()
my_df

Out [2]:
    index      items                lvl     xp
0   item1   []                      26      27097
1   item2   []                      12      40650
2   item3   [item1, item2, item3]   45      33900

【讨论】:

  • @Jake_A1997 这解决了您的问题吗?你还在苦苦挣扎吗?
  • 您好!是的,这无疑是一个很好的解决方案,对我来说更容易理解,但我使用了 IMCoins 的解决方案,因为他更早地发布了它。非常感谢您的宝贵时间,非常感谢您的帮助,希望能给您加分
猜你喜欢
  • 2021-05-24
  • 2019-04-24
  • 2021-03-06
  • 2013-04-06
  • 2019-12-01
  • 1970-01-01
  • 2016-01-14
  • 2022-01-12
  • 2010-12-08
相关资源
最近更新 更多