Python Pandas - трехмерная совокупность данных на основе критериев в нескольких столбцах, пока не будет достигнуто значение - PullRequest
0 голосов
/ 18 марта 2019

У меня возникли сложности с получением кумулятивной суммы 3D-данных в Python.

Образец информационного кадра, который я создал:

import numpy as np
import pandas as pd

arr=np.array([[[23, 10],
        [ 24,  5],
        [ 28,  8],
        [ 30, 11],
        [ 31, 1]],

       [[20, 11],
        [21, 3],
        [22, 5],
        [29, 15],
        [30, 10]],

       [[22, 26],
        [23, 29],
        [25, 32],
        [33, 10],
        [34, 15]]])

names = ['x', 'y', 'z']
index = pd.MultiIndex.from_product([range(s)for s in arr.shape], names=names)
df = pd.DataFrame({'Day': arr.flatten()}, index=index)['Day']
df = df.unstack(level='z')
df.columns = ['Price', 'Qty']
df.index.names = ['DATE', 'i']

В указанном диапазоне дат я хочу найти сумму количества товаров, если цена дешевле, чем определенное значение (x). Но я остановлюсь, когда сумма превысит определенную цифру (у), независимо от того, есть ли еще какие-либо в других магазинах или более поздние даты, которые соответствуют мин. ценовые критерии. Я начну суммировать сначала с самой ранней даты, и в каждую дату начну суммировать с самой низкой цены. Тогда я найду средневзвешенную цену до точки остановки.

В приведенном выше кадре данных, скажем, мои критерии: (1) Даты 0 и 1, (2) Цены равны или ниже 25, (3) Стоп, когда сумма количества впервые превышает 20. В этом случае соответствующие данные цена 23 и 24 в дату 0, и цена 20 в дату 1. Это связано с тем, что сумма кол-во для цены 23 и 24 в дату 0 равна 15, то есть меньше 20, но если добавить кол-во для цены 20 в дату 1, cumsum становится 26 и, следовательно, процесс останавливается. Таким образом, средневзвешенное значение составляет (23 * 10) + (24 * 5) + (20 * 5) / 20

Мой текущий метод слишком громоздок, поскольку я использую циклы while, чтобы пройти по оси времени, и использую другой цикл while для каждой даты, так что, если цена будет дешевле, чем мои критерии, я добавлю количество и взвешенное по цене количество к контрольная сумма. Когда сумма отслеживания превышает указанное значение, я остановлю процесс и вычислю средневзвешенное значение. Я также могу затем вернуть позицию, где процесс останавливается.

Хотел бы получить совет о том, как этого можно добиться более эффективным способом?

1 Ответ

0 голосов
/ 18 марта 2019

Вот пользовательская функция, которая делает это, просто подключите переменные, как в примере.

def weighted_average(df, dates, price_limit, stop_sum):
    # filter multiindex for your dates, plus price_limits
    tmp = df.loc[dates].loc[df['Price'] <= price_limit]
    # find index of halting cumsum condition, take tmp until there
    tmp = tmp.loc[:(tmp['Qty'].cumsum() > stop_sum).idxmax()]
    # update last value
    tmp.iat[-1, df.columns.get_loc('Qty')] -= tmp['Qty']sum() - stop_sum
    # return the weighted average
    return tmp.product(axis=1).sum() / stop_sum

dates = [0, 1]
price_limit = 25
stop_sum = 20

weighted_average(df, dates, price_limit, stop_sum)
> 22.5

A (возможно, более производительная, для большого набора данных) альтернатива фильтру (tmp = df.loc[dates].loc[df['Price'] <= price_limit]) -

tmp = df[(df.index.get_level_values(0).isin(dates)) & (df['Price'] <= price_limit)]
...