Получить список клиентов, которые не совершают покупки в определенном магазине - PullRequest
1 голос
/ 15 октября 2019

Допустим, у меня есть данные о транзакциях и клиентах:

df = pd.DataFrame({'shop': pd.Series(['McDonalds', 'McDonalds', 'McDonalds', 'McDonalds', 'Burger King', 'Burger King', 'Burger King', 'Burger King', 'Burger King', 'Trump Golf Course', 'Trump Golf Course', 'Trump Golf Course', 'Trump Golf Course', 'Trump Golf Course', 'Trump Golf Course'],dtype='object',index=pd.RangeIndex(start=0, stop=15, step=1)), 'Customer': pd.Series(['John Ryan', 'Jim Bob', 'Mary Ryan', 'Michael Patric', 'John Ryan', 'Jim Bob', 'Mary Ryan', 'Sean Connery', 'Brad Pitt', 'John Ryan', 'John Ryan', 'Michael Patric', 'Mary Ryan', 'John Ryan', 'Jim Bob'],dtype='object',index=pd.RangeIndex(start=0, stop=15, step=1)), 'Customer ID': pd.Series([1, 2, 3, 4, 1, 2, 3, 5, 6, 1, 1, 4, 3, 1, 2],dtype='int64',index=pd.RangeIndex(start=0, stop=15, step=1)), 'Amount': pd.Series([50, 32, 15, 65, 32, 51, 54, 84, 52, 51, 2, 32, 54, 87, 65],dtype='int64',index=pd.RangeIndex(start=0, stop=15, step=1))}, index=pd.RangeIndex(start=0, stop=15, step=1))

print(df)

                 shop        Customer  Customer ID  Amount
0           McDonalds       John Ryan            1      50
1           McDonalds         Jim Bob            2      32
2           McDonalds       Mary Ryan            3      15
3           McDonalds  Michael Patric            4      65
4         Burger King       John Ryan            1      32
5         Burger King         Jim Bob            2      51
6         Burger King       Mary Ryan            3      54
7         Burger King    Sean Connery            5      84
8         Burger King       Brad Pitt            6      52
9   Trump Golf Course       John Ryan            1      51
10  Trump Golf Course       John Ryan            1       2
11  Trump Golf Course  Michael Patric            4      32
12  Trump Golf Course       Mary Ryan            3      54
13  Trump Golf Course       John Ryan            1      87
14  Trump Golf Course         Jim Bob            2      65

Я хочу извлечь или пометить клиентов Burger King, которые еще не покупали в McDonalds. (В данном случае Шон Коннери и Брэд Питт)

Я пытаюсь создать маску где shop == McDonalds, и получить идентификатор клиента

mask1 = df.shop == 'McDonalds'

mcdonalds_customer_ids = df[mask1]['Customer ID'].values

array([1, 2, 3, 4], dtype=int64)

Затем создать отдельную маскугде shop=='Burger King', а идентификатор клиента отсутствует в списке идентификаторов клиентов McDonalds:

mask = (df['shop'] == 'Burger King' & df['Customer ID'] not in mcdonalds_customer_ids)

Я получаю следующие ошибки:

TypeError: ufunc 'bitwise_and' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

TypeError: cannot compare a dtyped [int64] array with a scalar of type [bool]

Я пытался использовать np.where тоже, но стало еще грязнее.

Мой ожидаемый результат - просто извлечь двух клиентов Burger King, которые не покупали в McDonalds:

                 shop        Customer  Customer ID  Amount
7         Burger King    Sean Connery            5      84
8         Burger King       Brad Pitt            6      52

Или пометить их, используя np.where:

                 shop        Customer  Customer ID  Amount  No_McDonalds
7         Burger King    Sean Connery            5      84  True
8         Burger King       Brad Pitt            6      52  True

Я могу сделать это с помощью функции, но надеялся как-то векторизовать ее. Полный провал, любая помощь приветствуется.

Ответы [ 6 ]

6 голосов
/ 15 октября 2019

Вот векторизованное решение с loc и isin. Сначала мы получаем строки Burger King, затем получаем Customers от McDonalds

И, наконец, проверяем, какой клиент из Burger King имел , а не был McDonalds:

bk = df.loc[df['shop'].eq('Burger King')]
mc = df.loc[df['shop'].eq('McDonalds'), 'Customer']

bk[~bk['Customer'].isin(mc)]

          shop      Customer  Customer ID  Amount
7  Burger King  Sean Connery            5      84
8  Burger King     Brad Pitt            6      52
2 голосов
/ 15 октября 2019

В вашем случае, Я хочу извлечь или пометить клиентов Burger King, которые еще не покупали в McDonalds , вы можете просто сделать:

s = (set(df.loc[df.shop.eq('Burger King'), 'Customer ID']) 
    - set(df.loc[df.shop.eq('McDonalds'), 'Customer ID'])
    )

Вывод s:

{5, 6}

И для извлечения этих записей клиентов с помощью Buger King:

df[df.shop.eq('Burger King') & df['Customer ID'].isin(s)]

Вывод:

          shop      Customer  Customer ID  Amount
7  Burger King  Sean Connery            5      84
8  Burger King     Brad Pitt            6      52
1 голос
/ 15 октября 2019

вы можете сделать это с помощью группового, как это

result = df.groupby("Customer") \
.apply(lambda g: g.assign(No_McDonalds= (g["shop"]!="McDonalds").all())) \
.reset_index(drop=True)

1 голос
/ 15 октября 2019
df.loc[~df['Customer'].isin(df.where(df['shop'] == 'McDonalds')['Customer'].dropna().values) & df['shop'].eq('Burger King')]

Результат:

          shop      Customer  Customer ID  Amount
7  Burger King  Sean Connery            5      84
8  Burger King     Brad Pitt            6      52
1 голос
/ 15 октября 2019

Сочетание groupby transform, unique и списка понимания

m = ['McDonalds' not in x for x in  df.groupby('Customer').shop.transform('unique')]

df[m]

Out[494]:
          shop      Customer  Customer ID  Amount
7  Burger King  Sean Connery  5            84
8  Burger King  Brad Pitt     6            52
1 голос
/ 15 октября 2019

Это должно сделать:

aux = df.groupby('Customer').shop.sum()

df['No_McDonalds'] = df.Customer.map(aux.apply(lambda x: ('Burger King' in x) & ('McDonalds' not in x)))

Вывод:

                 shop        Customer  Customer ID  Amount  No_McDonalds
0           McDonalds       John Ryan            1      50         False
1           McDonalds         Jim Bob            2      32         False
2           McDonalds       Mary Ryan            3      15         False
3           McDonalds  Michael Patric            4      65         False
4         Burger King       John Ryan            1      32         False
5         Burger King         Jim Bob            2      51         False
6         Burger King       Mary Ryan            3      54         False
7         Burger King    Sean Connery            5      84          True
8         Burger King       Brad Pitt            6      52          True
9   Trump Golf Course       John Ryan            1      51         False
10  Trump Golf Course       John Ryan            1       2         False
11  Trump Golf Course  Michael Patric            4      32         False
12  Trump Golf Course       Mary Ryan            3      54         False
13  Trump Golf Course       John Ryan            1      87         False
14  Trump Golf Course         Jim Bob            2      65         False

Если вам нужно какое-то объяснение, пожалуйста, дайте мне знать, и я помогу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...