Как я могу ввести новый столбец, который не учитывается в каждой строке?

У меня есть следующий кадр данных об аукционах:

id.product_permutation id.iteration property.product property.price
1 1 1 200
1 2 1 300
1 3 1 400
1 4 3 100
1 5 3 200
1 6 3 300
1 7 2 500
1 8 2 600
2 1 3 300
2 2 3 400
2 3 1 200
2 4 1 300
2 5 2 700
2 6 2 800
2 7 2 900
2 8 2 700
3 1 1 200
... ... ... ...

На аукционе выставлено 3 разных товара, и в столбце property.product указано, какой товар продается в данный момент. Если номер продукта в property.product меняется, продукт продается. property.price показывает цену на данный момент. Если число в id.product_permutation меняется, то весь аукцион завершается, все 3 предмета продаются и начинается новый аукцион (с теми же 3 предметами).

Теперь я хотел бы ввести новый столбец amount_of_sold_items, в котором подсчитывается, сколько товаров уже продано (как показано ниже). Я много пробовал, но, к сожалению, не получил желаемого результата. Может ли кто-нибудь помочь мне решить эту проблему?

id.product_permutation id.iteration property.product property.price amount_of_sold_items
1 1 1 200 0
1 2 1 300 0
1 3 1 400 0
1 4 3 100 1
1 5 3 200 1
1 6 3 300 1
1 7 2 500 2
1 8 2 600 2
1 NaN NaN NaN 3
2 1 3 300 0
2 2 3 400 0
2 3 1 200 1
2 4 1 300 1
2 5 2 700 2
2 6 2 800 2
2 7 2 900 2
2 8 2 700 2
2 NaN NaN NaN 3
3 1 1 200 0
... ... ... ... ...

person leolumpy    schedule 20.06.2021    source источник


Ответы (1)


df["n_items_sold"] = (df.groupby("id.product_permutation")["property.product"]
                        .transform(lambda x: x.diff().ne(0, fill_value=0).cumsum()))

Для каждой группы id.product_permutation мы назначаем новый ряд, который смотрит на поворотные точки через разность, не равную 0 (fill_value=0 существует, чтобы не считать самую первую точку поворотной). Кумулятивная сумма этих поворотных точек отслеживает количество проданных товаров.

Это дает:

    id.product_permutation  id.iteration  property.product  property.price  n_items_sold
0                        1             1                 1             200             0
1                        1             2                 1             300             0
2                        1             3                 1             400             0
3                        1             4                 3             100             1
4                        1             5                 3             200             1
5                        1             6                 3             300             1
6                        1             7                 2             500             2
7                        1             8                 2             600             2
8                        2             1                 3             300             0
9                        2             2                 3             400             0
10                       2             3                 1             200             1
11                       2             4                 1             300             1
12                       2             5                 2             700             2
13                       2             6                 2             800             2
14                       2             7                 2             900             2
15                       2             8                 2             700             2
16                       3             1                 1             200             0

Чтобы поместить [id_prod_perm, NaN, NaN, NaN, 3] строк в конце каждой id.product_permuation, мы можем определить точки изменения id.product_permuation и вставить столбцы в транспонированный фрейм, который, по сути, вставляет строки в исходный при транспонировании:

# following is [8, 16] for the above example
changing_points = np.where(df["id.product_permutation"]
                             .diff().ne(0, fill_value=0))[0].tolist()

# insert to transpose and then come back
df = df.T
offset = 0  # helper for insertion location
for j, point in enumerate(changing_points, start=1):
    # to the given point, insert a column with the same name
    df.insert(loc=point+offset, column=point, value=[j, *[np.nan]*3, 3],
              allow_duplicates=True)

    # since an insertion enlarges the frame, old changing points
    # need to increase, this is handled by the `offset`
    offset += 1

# go back to original form, and also reset the index to 0..N-1
df = df.T.reset_index(drop=True)

получить

>>> df

    id.product_permutation  id.iteration  property.product  property.price  n_items_sold
0                      1.0           1.0               1.0           200.0           0.0
1                      1.0           2.0               1.0           300.0           0.0
2                      1.0           3.0               1.0           400.0           0.0
3                      1.0           4.0               3.0           100.0           1.0
4                      1.0           5.0               3.0           200.0           1.0
5                      1.0           6.0               3.0           300.0           1.0
6                      1.0           7.0               2.0           500.0           2.0
7                      1.0           8.0               2.0           600.0           2.0
8                      1.0           NaN               NaN             NaN           3.0
9                      2.0           1.0               3.0           300.0           0.0
10                     2.0           2.0               3.0           400.0           0.0
11                     2.0           3.0               1.0           200.0           1.0
12                     2.0           4.0               1.0           300.0           1.0
13                     2.0           5.0               2.0           700.0           2.0
14                     2.0           6.0               2.0           800.0           2.0
15                     2.0           7.0               2.0           900.0           2.0
16                     2.0           8.0               2.0           700.0           2.0
17                     2.0           NaN               NaN             NaN           3.0
18                     3.0           1.0               1.0           200.0           0.0
person Mustafa Aydın    schedule 20.06.2021
comment
Большое спасибо, Мустафа!! - person leolumpy; 20.06.2021