【问题标题】:Pandas - Column expansion of List of Dictionary - How to Optimise?Pandas - 字典列表的列扩展 - 如何优化?
【发布时间】:2018-11-23 04:24:27
【问题描述】:

我有一个数据框 test 有 3 列 id, name, value 以下列 test['values']test 的外观示例如下:

    name                  values
0   impressions           [{'value': 17686, 'end_time': '2018-06-12T07:0...
1   reach                 [{'value': 6294, 'end_time': '2018-06-12T07:00...
2   follower_count        [{'value': 130, 'end_time': '2018-06-12T07:00:...
3   email_contacts        [{'value': 1, 'end_time': '2018-06-12T07:00:00...
4   phone_call_clicks     [{'value': 0, 'end_time': '2018-06-12T07:00:00...
5   text_message_clicks   [{'value': 0, 'end_time': '2018-06-12T07:00:00...
6   get_directions_clicks [{'value': 0, 'end_time': '2018-06

测试值单元格如下所示:

[{'end_time': '2018-06-12T07:00:00+0000', 'value': 17686},
 {'end_time': '2018-06-13T07:00:00+0000', 'value': 4064}]

我可以通过执行以下操作来扩展它:

test[['Values 1', 'Values 2']] = test['values'].apply(pd.Series)
test[['Date 1', 'Values 1']] = test['Values 1'].apply(pd.Series)
test[['Date 2', 'Values 2']] = test['Values 2'].apply(pd.Series)
test.drop(['values'], axis=1, inplace=True)

结果是这样的:

id                          name        Values 1    Values 2    Date 1  Date 2
/insights/impressions/day   impressions 17686   4064    2018-06-12T07:00:00+0000    2018-06-13T07:00:00+0000
/insights/reach/day reach   6294    2085    2018-06-12T07:00:00+0000    2018-06-13T07:00:00+0000
/insights/follower_count/day    follower_count  130 37  2018-06-12T07:00:00+0000    2018-06-13T07:00:00+0000

我想知道是否:

a.有一种更快的方法来扩展词典列表

b. 有一种方法可以取消透视数据,使值 1 和值 2 在一个列上。日期 1 和日期 2 在另一列中

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    如果输入数据是jsons,最好使用json_normalize

    j = [{'description': 'Total number 1', 'id': 'a', 'name': 'impressions', 'period': 'day', 'title': 'Impressions', 'values': [{'end_time': '2018-06-12T07:00:00+0000', 'value': 17686}, {'end_time': '2018-06-13T07:00:00+0000', 'value': 4064}]},
          {'description': 'fn', 'id': 'b', 'name': 'impressions', 'period': 'day', 'title': 'Impressions', 'values': [{'end_time': '2018-06-12T07:00:00+0000', 'value': 17686}, {'end_time': '2018-06-13T07:00:00+0000', 'value': 4064}]}]
    
    from pandas.io.json import json_normalize
    
    df = json_normalize(j, 'values')
    print (df)
                       end_time  value
    0  2018-06-12T07:00:00+0000  17686
    1  2018-06-13T07:00:00+0000   4064
    2  2018-06-12T07:00:00+0000  17686
    3  2018-06-13T07:00:00+0000   4064
    

    但如果需要还添加原始列:

    from pandas.io.json import json_normalize
    
    
    df = json_normalize(j, 'values', ['description', 'id', 'name', 'period', 'title'])
    print (df)
                       end_time  value     description id         name period  \
    0  2018-06-12T07:00:00+0000  17686  Total number 1  a  impressions    day   
    1  2018-06-13T07:00:00+0000   4064  Total number 1  a  impressions    day   
    2  2018-06-12T07:00:00+0000  17686              fn  b  impressions    day   
    3  2018-06-13T07:00:00+0000   4064              fn  b  impressions    day   
    
             title  
    0  Impressions  
    1  Impressions  
    2  Impressions  
    3  Impressions  
    

    第一个解决方案:

    test = pd.DataFrame({
        'name':['a', 'b', 'n'],
        'values':[[{'end_time': '2018-06-12T07:00:00+0000', 'value': 17686},
     {'end_time': '2018-06-13T07:00:00+0000', 'value': 4064}],[{'end_time': '2018-06-12T07:00:00+0000', 'value': 17686},
     {'end_time': '2018-06-13T07:00:00+0000', 'value': 4064}],[{'end_time': '2018-06-12T07:00:00+0000', 'value': 17686},
     {'end_time': '2018-06-13T07:00:00+0000', 'value': 4064}]]
    })
    
    
    df =  (pd.concat([pd.DataFrame(x) for x in test['values']], axis=1, keys=(1, 2))
            .stack(0)
            .reset_index(level=1, drop=True))
    print (df)
                       end_time  value
    0  2018-06-12T07:00:00+0000  17686
    0  2018-06-12T07:00:00+0000  17686
    1  2018-06-13T07:00:00+0000   4064
    1  2018-06-13T07:00:00+0000   4064
    
    df = test.join(df)
    print (df)
      name                                             values  \
    0    a  [{'end_time': '2018-06-12T07:00:00+0000', 'val...   
    0    a  [{'end_time': '2018-06-12T07:00:00+0000', 'val...   
    1    b  [{'end_time': '2018-06-12T07:00:00+0000', 'val...   
    1    b  [{'end_time': '2018-06-12T07:00:00+0000', 'val...   
    2    n  [{'end_time': '2018-06-12T07:00:00+0000', 'val...   
    
                       end_time    value  
    0  2018-06-12T07:00:00+0000  17686.0  
    0  2018-06-12T07:00:00+0000  17686.0  
    1  2018-06-13T07:00:00+0000   4064.0  
    1  2018-06-13T07:00:00+0000   4064.0  
    2                       NaN      NaN  
    

    【讨论】:

    • 您好,它来自 json。 JSON 看起来像这样:[{'description': 'Total number of times this profile has been seen', 'id': 'XXXXXXXXXXXXXXX/insights/impressions/day', 'name': 'impressions', 'period': 'day', 'title': 'Impressions', 'values': [{'end_time': '2018-06-12T07:00:00+0000', 'value': 17686}, {'end_time': '2018-06-13T07:00:00+0000', 'value': 4064}]},,然后它继续用于其他类别
    • @MattM - 为此添加了解决方案
    • @MattM - 如果需要所有数据一起添加解决方案 :)
    【解决方案2】:

    您可以使用两个applystack(加上set_indexreset_index)同时创建列值和end_time:

    (test.set_index('name')['values']
           .apply(pd.Series).stack()
             .apply(pd.Series).reset_index().drop('level_1',1))
    

    输出是这样的:

              name                  end_time  value
    0  impressions  2018-06-12T07:00:00+0000  17686
    1  impressions  2018-06-13T07:00:00+0000   4064
    

    【讨论】:

    • 谢谢 Ben,它也很完美!感谢帮助
    猜你喜欢
    • 1970-01-01
    • 2013-10-21
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 2023-03-08
    相关资源
    最近更新 更多