日々精進

新しく学んだことを書き留めていきます

binningはPandasよりnumpyを使うと速い

大体そうだと思うけど、binningが遅い場合はnumpyで処理すると速くなる。

以下がpandasを使った実装。

def cut_bins(s):
    m = s.max()
    categories = pd.cut(s, [0, m * 0.05, m * 0.25, m * 0.75, m * 0.95, m])
    category_counts = categories.cat.codes.value_counts()
    if s.nunique() == 1:
        return [0, 0, 1, 0, 0]
    total = category_counts.sum()
    result = []
    for i in range(5):
        if i in category_counts.index:
            result.append(str(category_counts[i] / float(total)))
        else:
            result.append("0")
    return ",".join(result)

summary_counts = summary.groupby([TITLE])[SALES_COUNT].progress_aggregate(cut_bins)

これをnumpyを使って実装すると以下のようになる。

def cut_bins(s):
    values = summary[SALES_COUNT].iloc[0:100].values
    m = values.max()
    categories = np.digitize(values, [m * 0.05, m * 0.25, m * 0.75, m * 0.95])
    unique, counts = np.unique(categories, return_counts=True)
    d = dict(zip(unique, counts))
    total = counts.sum()
    if total == counts.max():
        return "0,0,1,0,0"
    else:
        res = []
        for i in range(5):
            if i in d:
                res.append(str(d[i] / float(total)))
            else:
                res.append("0")
        return ",".join(res)

summary_counts = summary.groupby([TITLE])[SALES_COUNT].progress_aggregate(cut_bins)

これで33倍ぐらい速くなった。

参考:

realpython.com