Python / Pandas:优化unstack('var')。fillna(0).stack('var')的速度

时间:2018-09-19 14:33:44

标签: python pandas

我有包含以下信息的数据:产品编号i产品上市时间t商家ID 作为m和价格。对于每种产品i,都有一个列出时间t的清单,在该清单上我为所有商人m定价。

当特定商人mi处没有t的要约时,(i,t,m)的条目就会丢失。

我想要一个价格为零的条目,以表示该商人目前没有报价。

请注意,每种产品的商家是分开的:我想为在产品上出现过的商家添加条目,而不是为所有出现在该产品上的商家添加条目任何产品。

以下代码达到了我想要的结果:

def addMissingMerchants(pDF):
    return pDF.set_index(['i','t','m']).unstack('m').fillna(0).stack('m').reset_index();

df = df.groupby('i').progress_apply(addMissingMerchants).drop('i',axis=1).reset_index().drop('level_1',axis=1);

但是,这段代码很慢:它在我的系统上每秒处理大约15种产品。

有什么方法可以更快地达到相同的结果?

最小工作示例:

          i                   t        m              p
40181    3996 2018-08-26 02:33:45      162082         67.90
40182    3996 2018-08-26 03:14:10      162082         67.90
40194    3996 2018-08-26 02:33:45      193879         58.00
40195    3996 2018-08-26 03:14:10      193879         58.00
40210    3996 2018-08-26 03:14:10      256684         57.98
40226    3996 2018-08-26 02:33:45      373084         58.00
40227    3996 2018-08-26 03:14:10      373084         58.00
40247    3996 2018-08-26 02:33:45     1238707         53.98
40248    3996 2018-08-26 03:14:10     1238707         53.98

所需的输出:

     i                      t      m              p
0    3996 2018-08-26 02:33:45      162082         67.90
1    3996 2018-08-26 02:33:45      193879         58.00
2    3996 2018-08-26 02:33:45      256684          0.00
3    3996 2018-08-26 02:33:45      373084         58.00
4    3996 2018-08-26 02:33:45     1238707         53.98
5    3996 2018-08-26 03:14:10      162082         67.90
6    3996 2018-08-26 03:14:10      193879         58.00
7    3996 2018-08-26 03:14:10      256684         57.98
8    3996 2018-08-26 03:14:10      373084         58.00
9    3996 2018-08-26 03:14:10     1238707         53.98

(请注意以2开头的新行)

当前时间成本:

%%timeit
addMissingMerchants(df)
100 loops, best of 3: 7.59 ms per loop

1 个答案:

答案 0 :(得分:0)

与其重新组织和重新堆叠,不如对整个数据框重新编制索引。首先建立一个元组列表:

tuples = [];
for i, productData in df.groupby('i'):
    tList = productData.t.unique();
    for m in productData.m.unique():
        tuples.extend([(i,m,t) for t in tList]);

然后使用元组为数据框重新编制索引:

df = df.set_index(['i','m','t']) 
df = df[~df.index.duplicated(keep='first')] 
idx = pd.MultiIndex.from_tuples(tuples,names=['i','m','t'])
df = df.reindex(idx,fill_value=0).reset_index()

这需要花费几分钟才能完成整个数据帧,这比groupby-unstack-restack解决方案(大约需要1.5h)要好得多。