【问题标题】:Pandas expand json field across recordsPandas 跨记录扩展 json 字段
【发布时间】:2014-10-20 03:06:49
【问题描述】:

我有一个有趣的问题,我想知道是否有一种简洁、pythonic(pandastic?)的方法来做到这一点,而不是遍历数据框的行。

获取一个数据帧,其中一个字段是信息的 json 编码:

    Name      Data
0   Joe       '[{"label":"a","value":"1"},{"label":"b","value":"2"}]'
1   Sue       '[{"label":"a","value":"3"},{"label":"c","value":"4"}]'
2   Bob       '[{"label":"b","value":"4"},{"label":"d","value":"1"}]'

我想将json字段扩展为数据字段,合并不同的列标题,得到这个:

    Name      Data                 a    b    c    d
0   Joe       '[{"label":"a"...    1    2    
1   Sue       '[{"label":"a"...    3         4
2   Bob       '[{"label":"b"...         4         1

空格是缺失值。我知道我可以使用 read_json 从 json 字段创建数据帧,但是我想将这些数据帧重新展平为原始数据集的额外列。

那么,有没有一种优雅的方法可以在不遍历数据框的各个行的情况下做到这一点?任何帮助将不胜感激。

【问题讨论】:

  • 字符串 '{{a:1},{b:2}}' 不是有效的 JSON。这真的是你所拥有的,还是可以用json.loads 解码实际值?
  • 谢谢,我又快又马虎了。我已经重做了这个问题,以获得与问题相对应的正确 json。

标签: python json pandas


【解决方案1】:

给定

In [96]: df
Out[96]: 
  Name                   Data
0  Joe  [{"a":"1"},{"b":"2"}]
1  Sue  [{"a":"3"},{"c":"4"}]
2  Bob  [{"b":"4"},{"d":"1"}]

如果你定义

import json
def json_to_series(text):
    keys, values = zip(*[item for dct in json.loads(text) for item in dct.items()])
    return pd.Series(values, index=keys)

然后

In [97]: result = pd.concat([df, df['Data'].apply(json_to_series)], axis=1)

In [98]: result
Out[98]: 
  Name                   Data    a    b    c    d
0  Joe  [{"a":"1"},{"b":"2"}]    1    2  NaN  NaN
1  Sue  [{"a":"3"},{"c":"4"}]    3  NaN    4  NaN
2  Bob  [{"b":"4"},{"d":"1"}]  NaN    4  NaN    1

给定

In [22]: df
Out[22]: 
  Name                                               Data
0  Joe  [{"label":"a","value":"1"},{"label":"b","value...
1  Sue  [{"label":"a","value":"3"},{"label":"c","value...
2  Bob  [{"label":"b","value":"4"},{"label":"d","value...

如果你定义

def json_to_series(text):
    keys, values = zip(*[(dct['label'], dct['value']) for dct in json.loads(text)])
    return pd.Series(values, index=keys)

然后

In [20]: result = pd.concat([df, df['Data'].apply(json_to_series)], axis=1)

In [21]: result
Out[21]: 
  Name                                               Data    a    b    c    d
0  Joe  [{"label":"a","value":"1"},{"label":"b","value...    1    2  NaN  NaN
1  Sue  [{"label":"a","value":"3"},{"label":"c","value...    3  NaN    4  NaN
2  Bob  [{"label":"b","value":"4"},{"label":"d","value...  NaN    4  NaN    1

参考资料:

【讨论】:

  • 非常感谢 unutbu -- 这太棒了。调整代码是否很容易,以便它适用于我在修改后的问题中提供的输入,并且列标题包含在 json 中?
  • 当然。你只需要一点点改变。这里使用的工具需要一些时间来解释。我认为文档比我做得更好。所以我留下了一些参考链接;如果您有任何问题,请随时提出。
猜你喜欢
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
  • 2017-12-16
  • 2021-02-12
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多