Как проверить строки на их совпадение в будущем?

Существует фрейм данных вида:

user_id order_completed_at  cart target(как должно быть)
65467   1   2019-05-08 16:09:41 55 1
709747  1   2020-01-17 14:44:23 82 0
709748  1   2020-01-17 14:44:23 798 0
709749  1   2020-01-17 14:44:23 86 0
709750  1   2020-01-17 14:44:23 421 0
709751  1   2020-01-17 14:44:23 204 0
709752  1   2020-01-17 14:44:23 55 1
800645  1   2020-02-06 22:46:55 55 1
921504  1   2020-03-02 13:43:20 23 0
921505  1   2020-03-02 13:43:20 14 0
921506  1   2020-03-02 13:43:20 231 0
921507  1   2020-03-02 13:43:20 88 1
921508  1   2020-03-02 13:43:20 19 0
921509  1   2020-03-02 13:43:20 812 0
921510  1   2020-03-02 13:43:20 55 1
1084508 1   2020-03-29 13:26:49 55 1
1084509 1   2020-03-29 13:26:49 169 0
1084510 1   2020-03-29 13:26:49 88 0
1207092 1   2020-04-14 01:31:20 55 1
1207093 1   2020-04-14 01:31:20 798 0
1207094 1   2020-04-14 01:31:20 812 0
1363077 1   2020-04-30 17:45:22 55 1
1622429 1   2020-05-24 11:13:59 798 0
1622430 1   2020-05-24 11:13:59 55 1
1622431 1   2020-05-24 11:13:59 14 1
1622432 1   2020-05-24 11:13:59 170 0
1622433 1   2020-05-24 11:13:59 171 0
1622434 1   2020-05-24 11:13:59 169 1
2348244 1   2020-07-14 10:20:58 88 0
2348245 1   2020-07-14 10:20:58 302 0
2348246 1   2020-07-14 10:20:58 803 0
2348247 1   2020-07-14 10:20:58 307 0
2348248 1   2020-07-14 10:20:58 54 0
2348249 1   2020-07-14 10:20:58 55 0
2348250 1   2020-07-14 10:20:58 14 0
2348251 1   2020-07-14 10:20:58 169 0
2348252 1   2020-07-14 10:20:58 149 0

Необходимо пройтись по каждой строке и проставить дополнительный столбец target, где будет указано, было ли повторение этого cart в следующем заказе или нет.

Максимум до чего я дошел:

def target_definition(df):
    users = list(set(df['user_id'].tolist()))
    for user in users:
        orders = list(set(df['order_completed_at'].loc[df['user_id'] == user].tolist())).sort()
        carts = list(set(df['cart'].loc[df['user_id'] == user].tolist())).sort()
        for cart in carts:
            while n < len(orders)
            n = 0
            df.loc[((df['user_id'] == user)&(df['cart'] == cart))&(df['order_completed_at']==orders[n]==orders[n+1]), 'target'] = 1
            n+=1

Дальше, что делать не понимаю.


Ответы (2 шт):

Автор решения: MaxU

Если я правильно понял условия:

df["target"] = (df
                .sort_values(["order_completed_at", "cart"])
                .groupby("user_id")
                ["cart"]
                .apply(lambda x: x.duplicated())
                .astype("int8"))

результат:

In [227]: df
Out[227]:
         user_id  order_completed_at  cart  target
65467          1 2019-05-08 16:09:41    55       0
709747         1 2020-01-17 14:44:23    82       0
709748         1 2020-01-17 14:44:23   798       0
709749         1 2020-01-17 14:44:23    86       0
709750         1 2020-01-17 14:44:23   421       0
709751         1 2020-01-17 14:44:23   204       0
709752         1 2020-01-17 14:44:23    55       1
800645         1 2020-02-06 22:46:55    55       1
921504         1 2020-03-02 13:43:20    23       0
921505         1 2020-03-02 13:43:20    14       0
921506         1 2020-03-02 13:43:20   231       0
921507         1 2020-03-02 13:43:20    88       0
921508         1 2020-03-02 13:43:20    19       0
921509         1 2020-03-02 13:43:20   812       0
921510         1 2020-03-02 13:43:20    55       1
1084508        1 2020-03-29 13:26:49    55       1
1084509        1 2020-03-29 13:26:49   169       0
1084510        1 2020-03-29 13:26:49    88       1
1207092        1 2020-04-14 01:31:20    55       1
1207093        1 2020-04-14 01:31:20   798       1
1207094        1 2020-04-14 01:31:20   812       1
1363077        1 2020-04-30 17:45:22    55       1
1622429        1 2020-05-24 11:13:59   798       1
1622430        1 2020-05-24 11:13:59    55       1
1622431        1 2020-05-24 11:13:59    14       1
1622432        1 2020-05-24 11:13:59   170       0
1622433        1 2020-05-24 11:13:59   171       0
1622434        1 2020-05-24 11:13:59   169       1
2348244        1 2020-07-14 10:20:58    88       1
2348245        1 2020-07-14 10:20:58   302       0
2348246        1 2020-07-14 10:20:58   803       0
2348247        1 2020-07-14 10:20:58   307       0
2348248        1 2020-07-14 10:20:58    54       0
2348249        1 2020-07-14 10:20:58    55       1
2348250        1 2020-07-14 10:20:58    14       1
2348251        1 2020-07-14 10:20:58   169       1
2348252        1 2020-07-14 10:20:58   149       0
→ Ссылка
Автор решения: MaxU

Если единицы надо расставить в каждой группе для одинаковых user_id и cart так, чтобы все строки в группе получили единицы в том случае если перед ними в группе существуют другие строки, то сделать это можно так:

df["target"] = (df
                .sort_values(["order_completed_at", "cart"])
                .groupby("user_id")
                ["cart"]
                .apply(lambda x: x.duplicated(keep="last"))
                .astype("int8"))

результат, осторированный по полям ["user_id", "cart", "order_completed_at"]:

In [304]: df.sort_values(["user_id", "cart", "order_completed_at"])
Out[304]:
         user_id  order_completed_at  cart  target  target2
921505         1 2020-03-02 13:43:20    14       1        1
1622431        1 2020-05-24 11:13:59    14       1        1
2348250        1 2020-07-14 10:20:58    14       0        0
921508         1 2020-03-02 13:43:20    19       0        0
921504         1 2020-03-02 13:43:20    23       0        0
2348248        1 2020-07-14 10:20:58    54       0        0
65467          1 2019-05-08 16:09:41    55       1        1
709752         1 2020-01-17 14:44:23    55       1        1
800645         1 2020-02-06 22:46:55    55       1        1
921510         1 2020-03-02 13:43:20    55       1        1
1084508        1 2020-03-29 13:26:49    55       1        1
1207092        1 2020-04-14 01:31:20    55       1        1
1363077        1 2020-04-30 17:45:22    55       1        1
1622430        1 2020-05-24 11:13:59    55       1        1
2348249        1 2020-07-14 10:20:58    55       0        0
709747         1 2020-01-17 14:44:23    82       0        0
709749         1 2020-01-17 14:44:23    86       0        0
921507         1 2020-03-02 13:43:20    88       1        1
1084510        1 2020-03-29 13:26:49    88       1        1
2348244        1 2020-07-14 10:20:58    88       0        0
2348252        1 2020-07-14 10:20:58   149       0        0
1084509        1 2020-03-29 13:26:49   169       1        1
1622434        1 2020-05-24 11:13:59   169       1        1
2348251        1 2020-07-14 10:20:58   169       0        0
1622432        1 2020-05-24 11:13:59   170       0        0
1622433        1 2020-05-24 11:13:59   171       0        0
709751         1 2020-01-17 14:44:23   204       0        0
921506         1 2020-03-02 13:43:20   231       0        0
2348245        1 2020-07-14 10:20:58   302       0        0
2348247        1 2020-07-14 10:20:58   307       0        0
709750         1 2020-01-17 14:44:23   421       0        0
709748         1 2020-01-17 14:44:23   798       1        1
1207093        1 2020-04-14 01:31:20   798       1        1
1622429        1 2020-05-24 11:13:59   798       0        0
2348246        1 2020-07-14 10:20:58   803       0        0
921509         1 2020-03-02 13:43:20   812       1        1
1207094        1 2020-04-14 01:31:20   812       0        0

PS я специально создал новый столбец, чтобы сравнить результат с ожидаемым. Судя по всему в примере данных много ошибок в ожидаемом столбце target или же автор что-то не договаривает об алгоритме расставления единиц и нулей.

→ Ссылка