基于列的熊猫南瓜数据框

时间:2018-09-04 16:39:04

标签: python pandas

我正在从返回JSON的API中读取 我正在使用

from pandas.io.json import json_normalize 
flatten = json_normalize(data['results'])

要展平JSON,现在输出就像

                                     breakdowns                 metric                  time         value   
0      [{u'key': u'platform', u'value': u'ios'}]      fb_ad_network_imp    2018-08-29T07:00:00+0000  12
1  [{u'key': u'platform', u'value': u'android'}]      fb_ad_network_imp    2018-08-29T07:00:00+0000  32
2      [{u'key': u'platform', u'value': u'ios'}]  fb_ad_network_request    2018-08-29T07:00:00+0000  33    
3  [{u'key': u'platform', u'value': u'android'}]  fb_ad_network_request    2018-08-29T07:00:00+0000  132 

现在我想根据平台将这4行压缩成2行,

           platform    date         clicks     impressions
0          ios         2018-08-29   33         12
1          android     2018-08-29   132        32

我还映射了以下名称:

fb_ad_network_request-> clicks
fb_ad_network_imp-> impressions

什么是最好的方法?

4 个答案:

答案 0 :(得分:5)

pivot_table展平后,可以使用dict

dddd['platform']=pd.concat([pd.DataFrame(x) for x in dddd.breakdowns]).value.values
dddd.pivot_table(index=['platform','time'],columns='metric',values='value',aggfunc=sum).reset_index()
Out[237]: 
metric platform        time  fb_ad_network_imp  fb_ad_network_request
0       android  2018-08-29                 32                    132
1           ios  2018-08-29                 12                     33

答案 1 :(得分:2)

设置

tmp = pd.Series([i[0].get('value', None) for i in df.breakdowns]).rename('platform')

mapping = {
    'columns': {
        'fb_ad_network_request': 'clicks',
        'fb_ad_network_imp': 'impressions',
        'time': 'date',
    }
}

使用groupbyunstack

(df.join(tmp).groupby(['platform', df.time.dt.date, 'metric'])
    .value.sum().unstack().reset_index().rename(**mapping))

metric platform        date  impressions  clicks
0       android  2018-08-29           32     132
1           ios  2018-08-29           12      33

答案 2 :(得分:2)

设置

df = pd.DataFrame({
    'breakdowns': [[{u'key': u'platform', u'value': u'ios'}],
                   [{u'key': u'platform', u'value': u'android'}],
                   [{u'key': u'platform', u'value': u'ios'}],
                   [{u'key': u'platform', u'value': u'android'}]],
    'metric': ['fb_ad_network_imp'] * 2 + ['fb_ad_network_request'] * 2,
    'time': ['2018-08-29T07:00:00+0000'] * 4,
    'value': [12, 32, 33, 132]
})
df['time'] = pd.DatetimeIndex(df['time'])

解决方案

这假设time列具有时间戳,然后使用dt访问器方法获取日期并将其分配给链式数据框中的新列。

我使用了lambda函数从细分列中获取平台,然后将这些值与日期和指标分组在一起。该指标已取消堆叠,因此每个指标都将位于单独的列中,重置索引并将列重命名为所需的格式。

result = (
    df
    .assign(date=df['time'].dt.date)
    .groupby([df['breakdowns'].apply(lambda x: x[0].get('value')), 'date', 'metric'])
    ['value']
    .sum()
    .unstack('metric')
    .reset_index()
    .rename(columns={
        'breakdowns': 'platform',
        'fb_ad_network_request': 'clicks',
        'fb_ad_network_imp': 'impressions'
    })
)
result.columns.name = None

>>> result
  platform        date  impressions  clicks
0  android  2018-08-29           32     132
1      ios  2018-08-29           12      33

答案 3 :(得分:1)

通过字典组合创建pandas.Series

m0 = dict(fb_ad_network_imp='impressions', fb_ad_network_request='clicks')
flatten.time = pd.to_datetime(flatten.time).dt.floor('D')

s = pd.Series({
    (b[0]['value'], t, m0[m]): v for b, m, t, v in flatten.values
})

s.rename_axis(['platform', 'date', None]).unstack().reset_index()

  platform       date  clicks  impressions
0  android 2018-08-29     132           32
1      ios 2018-08-29      33           12

类似地

m0 = dict(fb_ad_network_imp='impressions', fb_ad_network_request='clicks')

def f(tup):
  b = tup.breakdowns[0]['value']
  t = pd.to_datetime(tup.time).floor('D')
  m = m0[tup.metric]
  v = tup.value
  return ((b, t, m), v)

s = pd.Series(dict(map(f, flatten.itertuples())))

s.rename_axis(['platform', 'date', None]).unstack().reset_index()

  platform       date  clicks  impressions
0  android 2018-08-29     132           32
1      ios 2018-08-29      33           12