«Итеративная» оконная функция на подмножестве данных - PullRequest
0 голосов
/ 24 октября 2018

Я ищу способ создания столбца 'min_value' из кадра данных df ниже.Для каждой строки i мы подставляем из всего фрейма данных все записи, которые соответствуют группировке ['Date_A', 'Date_B'] строки i и имеют условие 'Advance' меньше 'Advance' строки i, и, наконец, мы выбираем минимум изДля столбца 'Amount' из этого подмножества установить 'min_value' для строки i:

Исходный кадр данных:

dates_A = ['2017-12-25','2017-12-25','2017-12-25','2018-1-25','2018-1-25','2018-1-25']
Date_A = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_A]
dates_B = ['2018-1-1','2018-1-1','2018-1-1','2018-2-1','2018-2-1','2018-2-1']
Date_B = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_B]
df = pd.DataFrame({'Date_A':Date_A,
       'Date_B':Date_B,        
       'Advance' : [10,103,200,5,8,150],
       'Amount' : [180,220,200,230,220,240]})

df  = df [['Date_A', 'Date_B', 'Advance', 'Amount']]
df 

Желаемый вывод:

dates_A = ['2017-12-25','2017-12-25','2017-12-25','2018-1-25','2018-1-25','2018-1-25']
Date_A = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_A]
dates_B = ['2018-1-1','2018-1-1','2018-1-1','2018-2-1','2018-2-1','2018-2-1']
Date_B = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_B]
df_out = pd.DataFrame({'Date_A':Date_A,
       'Date_B':Date_B,        
       'Advance' : [10,103,200,5,8,150],
       'Amount' : [180,220,200,230,220,240],
       'min_value': [180,180,180,230,230,220] })

df_out  = df_out [['Date_A', 'Date_B', 'Advance', 'Amount','min_value']]
df_out 

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

Улучшение вопроса Большое спасибо за ответ.Для последней части, строки NA, я хотел бы заменить сумму строки на общую сумму Date_A, Date_B, предварительной группировки, чтобы у меня был общий минимум за последний день до date_A

Улучшение желаемого выхода (два перекодировщика для наименьшего значения аванса)

dates_A = ['2017-12-25','2017-12-25','2017-12-25','2017-12-25']
Date_A = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_A]
dates_B = ['2018-1-1','2018-1-1','2018-1-1','2018-1-1']
Date_B = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_B]

df_out = pd.DataFrame({'Date_A':Date_A,
       'Date_B':Date_B,        
       'Advance' : [5,8,150,5],
       'Amount' : [230,220,240,225],
       'min_value': [225,230,220,225] })

df_out  = df_out [['Date_A', 'Date_B', 'Advance', 'Amount','min_value']]
df_out 

Спасибо

1 Ответ

0 голосов
/ 24 октября 2018

Вы можете использовать groupby для 'Date_A' и 'Date_B' после сортировки значения по 'Advance' и apply функции cummin и shift для столбца 'Amount',Затем используйте fillna со значением из столбца 'Amount', например:

df['min_value'] = (df.sort_values('Advance').groupby(['Date_A','Date_B'])['Amount']
                      .apply(lambda ser_g: ser_g.cummin().shift()).fillna(df['Amount']))

, и вы получите:

       Date_A      Date_B  Advance  Amount  min_value 
0  2017-12-25  2018-01-01       10     180      180.0      
1  2017-12-25  2018-01-01      103     220      180.0 
2  2017-12-25  2018-01-01      200     200      180.0 
3  2018-01-25  2018-02-01        5     230      230.0 
4  2018-01-25  2018-02-01        8     220      230.0 
5  2018-01-25  2018-02-01      150     240      220.0 
...