【问题标题】:pivot_table vs groupby : column namespivot_table vs groupby :列名
【发布时间】:2018-05-12 16:22:23
【问题描述】:

df_tier

device_id   month_id    net_grp     watch_hours class
843         201707      TCH         0.250277    Ser
896         201803      NJV         0.820833    Ser
748         201711      SHX         2.461111    Sr
115         201712      SPE         1.478055    Opter
107         201802      US          2.575555    Opter
249         201710      ECC         3.869166    Ser
786         201711      NCK         0.563888    Opter
183         201802      HO          1.690555    Opter
752         201712      LC          0.993611    Opter

我正在对数据集进行透视操作,最终结果将包含大约 500 万行和 600 列。 以上是创建数据透视的数据示例。

#Pivot
df_tier.pivot_table(index=['device_id'],
                        columns = 'net_grp',
                        values = 'watch_hours',
                        aggfunc = sum,fill_value = 0).reset_index()

对 200000 条记录样本的此操作大约需要 93.7 毫秒,当我按如下方式进行分组时:

#Grouby
df_tier.groupby(['device_id','net_grp']).agg({'tuning_hours':['sum']}).unstack(level='net_grp').fillna(0).reset_index().set_index('device_id')

大约需要 15 毫秒。

但是,pivot 的输出更有用,因为它包含正确的列名,而来自 groupby 的列名:

group by中的列名不正确,

(watch_hours,sum,TCH),(watch_hours,sum,SPE),(watch_hours,sum,NCK)

如何仅从这些列名中获取net_grpTCH

我想在这里使用 groupby,因为我在整个数据上运行时会出现性能问题。有人可以帮我正确获取列名吗?

谢谢

【问题讨论】:

  • 我的解决方案效果如何?你能测试.agg({'watch_hours':['sum']})['watch_hours'].sum() 在你的真实数据中的规模吗?我很好奇哪种解决方案更快。谢谢。
  • 你好@jezrael ..我正在对总数据运行它并将更新结果。使用枢轴,服务器上的内存使用率上升到大约 70%。我也很想知道 groupby。将很快更新。谢谢:)
  • 你好@jezrael .. 它现在使用 group by 占用高达 60% 的内存 .. 使用 pivot 它高达 70% .. 虽然减少了 10%,但我仍然需要优化更多。 :) 非常感谢!
  • 嗯,根据我的经验,最快的是 groupby + sum,如果仍然不是很快我建议使用 dask 进行快速聚合,(但不确定是否支持 unstack())
  • 是的,我打算这样做。但速度和内存使用可能不是线性相关的。我的意思是该程序需要大约 4 个小时来执行,但平均内存使用量约为 50%。您是否建议使用多处理来并行化某些操作,这将有助于减少内存占用?对不起,虽然我懂一点python,但优化编程是另一回事,我还在学习!

标签: python pandas group-by pivot-table


【解决方案1】:

我建议使用sum 而不是agg 删除列中Multiindex 中的第一个和第二个不必要的级别:

df1 = (df_tier.groupby(['device_id','net_grp'])['watch_hours']
              .sum()
              .unstack(level='net_grp', fill_value=0))
print (df1)
net_grp         ECC        HO        LC       NCK       NJV       SHX  \
device_id                                                               
107        0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   
115        0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   
183        0.000000  1.690555  0.000000  0.000000  0.000000  0.000000   
249        3.869166  0.000000  0.000000  0.000000  0.000000  0.000000   
748        0.000000  0.000000  0.000000  0.000000  0.000000  2.461111   
752        0.000000  0.000000  0.993611  0.000000  0.000000  0.000000   
786        0.000000  0.000000  0.000000  0.563888  0.000000  0.000000   
843        0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   
896        0.000000  0.000000  0.000000  0.000000  0.820833  0.000000   

net_grp         SPE       TCH        US  
device_id                                
107        0.000000  0.000000  2.575555  
115        1.478055  0.000000  0.000000  
183        0.000000  0.000000  0.000000  
249        0.000000  0.000000  0.000000  
748        0.000000  0.000000  0.000000  
752        0.000000  0.000000  0.000000  
786        0.000000  0.000000  0.000000  
843        0.000000  0.250277  0.000000  
896        0.000000  0.000000  0.000000 

如果想使用agg 的解决方案,可以通过droplevel 删除第一级和第二级:

df1 = (df_tier.groupby(['device_id','net_grp'])
              .agg({'watch_hours':['sum']})
              .unstack(level='net_grp', fill_value=0))

df1.columns = df1.columns.droplevel([0,1])

【讨论】:

    猜你喜欢
    • 2016-01-22
    • 2014-04-27
    • 2019-06-30
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    相关资源
    最近更新 更多