Оптимизация pandas итерации - PullRequest
1 голос
/ 02 апреля 2020
Customer  Year   Customer Lost/Retained
A         2009          Retained
A         2010          Retained   
A         2011          Lost
B         2008          Lost
C         2008          Retained
C         2009          lost

Я использовал itterrows () для создания столбца «Потерянный / удержанный клиент» на основе приведенного выше лога c.

Если клиент дублируется в течение последовательного года, он сохраняется или теряется.

for i, row in df.iterrows(): 
    if (df[df['Year'] == row['Year']+1]['Customer']).str.contains(df['Customer'].iloc[i]).any():
        df['Customer Lost/Retained'].iloc[i] = 'Retained'
    else:
        df['Customer Lost/Retained'].iloc[i] = 'Lost'

Можно ли оптимизировать этот код дальше?

Ответы [ 3 ]

2 голосов
/ 02 апреля 2020
# groupby customer
g = df.groupby('Customer')['Year']
# create a mask of conditions by using shift
mask = (g.shift(0) == g.shift(-1)-1)
# use npy.wehre to create a list of results based on the mask
df['Retained/lost'] = np.where(mask, 'Retained', 'Lost')

  Customer  Year Retained/lost
0        A  2009      Retained
1        A  2010      Retained
2        A  2011          Lost
3        B  2008          Lost
4        C  2008      Retained
5        C  2009          Lost
1 голос
/ 02 апреля 2020

Вы можете сделать это как merge с самим собой, но изменив год:

In [83]: df['retained'] = pd.notnull(df.merge(
    ...:     df,
    ...:     how="left",
    ...:     left_on=["Customer", "Year"],
    ...:     right_on=["Customer", df["Year"].sub(1)],
    ...:     suffixes=['', "_match"]
    ...: )["Year_match"]).map({True: 'Retained', False: 'Lost'})

In [84]: df
Out[84]:
  Customer  Year Customer Lost/Retained  retained
0        A  2009               Retained  Retained
1        A  2010               Retained  Retained
2        A  2011                   Lost      Lost
3        B  2008                   Lost      Lost
4        C  2008               Retained  Retained
5        C  2009                   lost      Lost
0 голосов
/ 02 апреля 2020

Мы добавляем столбец с надписью 'Retained':

df['Customer Lost/Retained'] = 'Retained'

За исключением индексов с наибольшим годом на одного клиента, они получают значение 'Lost':

mask = df.groupby('Customer')['Year'].idxmax()
df.loc[mask, 'Customer Lost/Retained'] = 'Lost'
  Customer  Year Customer Lost/Retained
0        A  2009               Retained
1        A  2010               Retained
2        A  2011                   Lost
3        B  2008                   Lost
4        C  2008               Retained
5        C  2009                   Lost

Или, альтернативно, сначала введите 'Lost', а затем .fillna():

df.loc[df.groupby('Customer')['Year'].idxmax(), 'Customer Lost/Retained'] = 'Lost'
df['Customer Lost/Retained'] = df['Customer Lost/Retained'].fillna('Retained')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...