【问题标题】:How can I normalize a dict inside a CSV?如何规范化 CSV 中的字典?
【发布时间】:2021-03-23 10:12:45
【问题描述】:

我有一个包含 dict 值的 CSV 文件。

Test.CSV

id,name,contact,Location
1,Julie,"[{""name"":""Jenny Brown"",""relation"":""mother"",""number"":2113131313},{""name"":""Jorge"",""relation"":""brother"",""number"":121313131}]",US
2,Jim,"[{""name"":""Sana"",""relation"":""sister"",""number"":83279131}]",UK

我想规范化这个 CSV。预期输出:

id , name, contact_name,contact_realation,contact_number,location
1,Julie,Jenny Brown,mother,2113131313,US
1,Julie,Jorge,brother,121313131,US
2,Jim,Sana,sister,83279131,UK

我已经使用 CSV 阅读器加载了数据,但我无法标准化联系人值。我该怎么做?

csvfile = csv.reader(open(filename, encoding="utf8"))

到目前为止,我尝试过这个:

df=pd.read_csv(filename, converters={'contact':json.loads}, header=0)
contact_df = pd.io.json.json_normalize(df['contact'])

但出现以下错误:

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

【问题讨论】:

  • 解析每行的 json 块,然后从感兴趣的属性组装你的新行。
  • 嗨,我已经尝试过了,但出现错误:df=pd.read_csv(filename, converters={'contact':json.loads}, header=0) contact_df = pd.io.json。 json_normalize(df['contact'])
  • 在问题中添加您尝试过的内容以及失败的原因

标签: python python-3.x pandas python-2.7


【解决方案1】:

函数pd.io.json.json_normalize 用于直接处理JSON 对象。但您似乎想直接使用pd.Series。一个不错的技巧是将值映射到SeriesDataframe。然后您可以使用concat 创建具有多个索引的联系人数据框。最后,将其合并回原始数据框。

df=pd.read_csv(filename, converters={'contact':json.loads}, header=0)
df.index.name = 'row_id'
concat_df = df.merge(
    pd.concat(df["contact"].apply(pd.DataFrame).tolist(), keys=df.index),
    left_index=True, right_index=True
).drop("contact",1) 

输出:

          id name_x Location       name_y relation      number     role
row_id                                                                 
0      0   1  Julie       US  Jenny Brown   mother  2113131313      NaN
       1   1  Julie       US        Jorge      NaN   121313131  brother
1      0   2    Jim       UK         Sana   sister    83279131      NaN

【讨论】:

  • 我认为因为 pd.Series(x[0]) 它只是序列化 id 1 的第一个值
  • 不,apply 在所有 id 上运行。请注意,每一行都有一个list,现在您对每行列表中的第一个元素感兴趣吗?
  • 输出显示 ``` id name Location name 关系号 0 1 Julie US Jenny Brown mother 2113131313 1 2 Jim UK Sana Sister 83279131 ``` 但是输出应该有三行
  • 对不起。所以你想拆分行。没明白。我会修改
  • 是的,一个人可能有多个联系人,比如父亲、母亲
【解决方案2】:

如果您只想使用 csv module 执行此操作,您可以使用以下内容:

import csv
from io import StringIO
import json

data = """id,name,contact,location
1,Julie,"[{""name"":""Jenny Brown"",""relation"":""mother"",""number"":2113131313},{""name"":""Jorge"",""relation"":""brother"",""number"":121313131}]",US
2,Jim,"[{""name"":""Sana"",""relation"":""sister"",""number"":83279131}]",UK
3,Alice,,UK"""

reader = csv.DictReader(StringIO(data))
with open("processed.csv", 'w') as f:
    writer = csv.DictWriter(f, fieldnames=["id","name","contact_name","contact_relation","contact_number","location"])
    writer.writeheader()
    for row in reader:
        new_row = {k:row[k] for k in row if k != "contact"}
        if row["contact"]:
            contacts = json.loads(row["contact"])
            for contact in contacts:
                for key in contact:
                    new_row["contact_" + key] = contact[key]
                writer.writerow(new_row)
        else:
            writer.writerow(new_row)

结果:

$cat processed.csv
id,name,contact_name,contact_relation,contact_number,location
1,Julie,Jenny Brown,mother,2113131313,US
1,Julie,Jorge,brother,121313131,US
2,Jim,Sana,sister,83279131,UK
3,Alice,,,,UK

编辑:更新代码以说明没有联系信息的条目。

【讨论】:

  • 如果任何条目没有联系信息,代码会出错。
  • 对@SaNa3819,我没有考虑到这种可能性。我更新了代码来解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2020-12-31
  • 2013-05-30
  • 1970-01-01
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 2015-06-01
  • 2021-04-11
相关资源
最近更新 更多