当json_normalize无法迭代列以展平时如何修复它?

Posted

技术标签:

【中文标题】当json_normalize无法迭代列以展平时如何修复它?【英文标题】:How to fix json_normalize when it cannot iterate over column to flatten? 【发布时间】:2018-12-11 17:24:23 【问题描述】:

我有一个如下所示的数据框:

ID       phone_numbers
1        [u'updated_at': u'2017-12-02 15:29:54', u'created_at': u'2017-12-0 
          2 15:29:54', u'sms': 0, u'number': u'1112223333', u'consumer_id': 
          12345, u'organization_id': 1, u'active': 1, u'deleted_at': 
           None, u'type': u'default', u'id': 1234]

我想获取 phone_numbers 列并将其中的信息展平,这样我就可以查询“id”字段。

当我尝试时;

json_normalize(df.phone_numbers)

我得到错误:

AttributeError: 'str' 对象没有属性 'itervalues'

我不确定为什么会产生此错误以及为什么我无法展平此列。

编辑:

最初是从响应对象(r.text)中读取的 JSON 字符串:

https://docs.google.com/document/d/1Iq4PMcGXWx6O48sWqqYnZjG6UMSZoXfmN1WadQLkWYM/edit?usp=sharing

编辑:

通过此命令将我需要展平的列转换为 JSON

a = df.phone_numbers.to_json()

"0":["updated_at":"2018-04-12 12:24:04","created_at":"2018-04-12 12:24:04","sms":0,"number":"","consumer_id":123,"org_id":123,"active":1,"deleted_at":null,"type":"default","id":123]

【问题讨论】:

一个想法,DataFrame 是从json 创建的吗?也许更好的是使用df = json_normalize(json) 我试过了,因为我通过 API 获得了 json 响应。但我得到与上面相同的错误 好的,可以添加json样本吗? @jezrael,JSON 响应包含患者信息,我无法发布该信息,即使经过擦洗,我也害怕可能会遗漏一些东西。但是,当将 json 对象传递给 json_normalize 时,我得到的错误是属性错误 ''unicode' object has no attribute 'itervalues' 看起来phone_numbers 列中的每条记录都是长度为 1 的 JSON 字符串列表。而不仅仅是一个 JSON 字符串。检查确切的内容以确保。 【参考方案1】:

使用列表推导进行展平并将新元素 ID 添加到字典中:

df = pd.DataFrame('ID': [1, 2], 'phone_numbers': [['a': '2017', 'b': '2017', 'sms': 1, 
                                                    'a': '2018', 'b': '2017', 'sms': 2], 
                                                  ['a': '2017', 'b': '2017', 'sms': 3]])
print (df)
   ID                                      phone_numbers
0   1  ['a': '2017', 'b': '2017', 'sms': 1, 'a': '...
1   2             ['a': '2017', 'b': '2017', 'sms': 3]

df = pd.DataFrame([dict(y, ID=i) for i, x in df.values.tolist() for y in x])
print (df)  

   ID     a     b  sms
0   1  2017  2017    1
1   1  2018  2017    2
2   2  2017  2017    3

编辑:

df = pd.DataFrame('phone_numbers':"0":["type":"default","id":123])

df = pd.DataFrame([y for x in df['phone_numbers'].values.tolist() for y in x])
print (df) 
    id     type
0  123  default

【讨论】:

抱歉延迟回复。当我运行您的上述行时,我收到错误“太多值无法解包”。我认为问题可能是 ID 字段嵌入在嵌套的 json 中,而不是作为单独的列。你认为这就是你的代码对我不起作用的原因吗? 在引入 ID 列后,我仍然收到错误 'too many values to unpack' @RustyShackleford - 是否可以更改输入数据?具有匿名数据的最佳样本json 确定我会匿名输入数据,给我一些时间彻底清理它 我已将文件上传到驱动器。我将 API 调用中的 JSON 字符串写入 word doc,将所有字段替换为单词“FIELD”。请让我知道这是否有帮助。我也找不到一条记录的结尾和下一条记录的开头,所以它是整个字符串。【参考方案2】:

我不确定,但我认为 json 规范化期望作为第一个参数 json,而不是 pd.series,首先将系列转换为字典或字典列表。你可以使用to_dict()

json_normalize(df.phone_numbers.to_dict())

【讨论】:

当我尝试这个时,它将整列转换为一行。【参考方案3】:

团队:

我想我找到了这个问题的答案。如果你挖;您会看到第一次迭代后 pd.json_normalize 的输出是一个字符串。我成功地诱使 pandas 重新认为这是一个字典列表。

fb_customers = test_schema_a["FBCustomers"].to_list()
fb_customers_b = list(itertools.chain(*fb_customers))
test_schema_b = pd.DataFrame(fb_customers_b)

【讨论】:

【参考方案4】:

对我来说最简单的解决方案是首先使用内置 json 包加载文件,然后将该对象与 normalize 一起使用:

从字符串中读取:

import json
json_str = ' "name":"John", "age":30, "city":"New York"'
data = json.loads(json_str)
df = json_normalize(data)
print(df)

并从文件中读取:

import json
                
with open(filepath, 'r') as file:
    data = json.load(file)
    df = json_normalize(data)
    print(df)

【讨论】:

【参考方案5】:

简单的一个衬垫来展平熊猫中的 json 列/系列。

import json
import pandas as pd

df_flattened_col = pd.json_normalize(df['JSON_COLUMN'].apply(json.loads).tolist())

⭐为我工作⭐

【讨论】:

以上是关于当json_normalize无法迭代列以展平时如何修复它?的主要内容,如果未能解决你的问题,请参考以下文章

指定元路径的 1.0.0 中的 python pandas json_normalize - 期望可迭代

Pandas json_normalize 无法在 Python 中使用大型 JSON 文件

pandas json_normalize KeyError

如何使用 NaN 对列进行 json_normalize

如何使用 json_normalize 规范化嵌套的 json

jOOQ 无法映射 PostgreSQL 列以使 JPA 满意