【问题标题】:Pandas: Expand column containing JSON encoded array of observations into rowsPandas:将包含 JSON 编码观察数组的列展开为行
【发布时间】:2018-04-27 02:08:04
【问题描述】:

将包含 JSON 编码观察数组的列扩展为其他行的惯用 Pandas 方法是什么?

在下面的示例中,Out[3] 是一个包含贷款数据的DataFrame。每笔贷款有一行。 Loan IDStart DateEnd DateAmount 列在贷款期限内不会发生变化。零个或多个带日期戳的付款以 JSON(字符串)数组的形式编码到 Payments 列中。

Out[5] 中的目标输出显示了目标。每原始行一行或多行,每次来自Payments 的付款都会导致在输出中创建一个新行。

我已经通过两种方式做到了这一点:使用iterrows,它看起来理智且易于阅读,以及使用一种复杂的、有点手摇的方法,我将固定属性拉入索引以保留它们,然后是@987654333 @ 并重新索引。

一定有更好的方法!请分享熊猫大师的秘密:)

【问题讨论】:

    标签: pandas


    【解决方案1】:

    首先通过dropna 删除Payments 列中的NaNs,然后通过ast.literal_evaljsons 转换为dicts:

    import ast
    
    s = df['Payments'].dropna().apply(ast.literal_eval)
    print (s)
    0    [{'Payment Amount': 1000, 'Payment Date': '201...
    Name: Payments, dtype: object
    

    然后将list comprehensionconcat 中的每个值一起转换为DataFrame - keys 参数对于对齐原始行很重要:

    df1 = pd.concat([pd.DataFrame(x) for x in s], keys=s.index)
    print (df1)
         Payment Amount Payment Date
    0 0            1000   2018-03-11
      1            2000   2018-03-13
      2            3000   2018-03-15
    

    删除列和join 为原始DataFrame,最后为唯一索引添加reset_index

    df = df.drop('Payments', 1).join(df1.reset_index(level=1, drop=True)).reset_index(drop=True)
    df['Payment Date'] = pd.to_datetime(df['Payment Date'])
    print (df)
       LoanId  Start Date    End Date  Amount  Payment Amount Payment Date
    0     100  2018-01-01  2021-01-01   10000          1000.0   2018-03-11
    1     100  2018-01-01  2021-01-01   10000          2000.0   2018-03-13
    2     100  2018-01-01  2021-01-01   10000          3000.0   2018-03-15
    3     101  2018-01-02  2021-01-02   20000             NaN          NaT
    4     102  2018-01-03  2021-01-03   30000             NaN          NaT
    

    【讨论】:

    • 非常感谢。 concat 步骤是我一直在寻找的魔法,尤其是 keys=s.index 部分。
    猜你喜欢
    • 2019-05-26
    • 2019-10-24
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    相关资源
    最近更新 更多