Выполните итерацию по строкам и выберите все между максимальным и минимальным

#python #pandas #dataframe #data-science

Вопрос:

Предположим, у меня есть фрейм данных Pandas, подобный следующему:

 ID  update_time     cap date      diff
A   05/05/21 1:45   136 05/05/21    136
A   05/05/21 1:50   0   05/05/21    -136
A   05/05/21 2:10   1   05/05/21    1
A   05/05/21 2:15   0   05/05/21    -1
A   05/05/21 3:35   1   05/05/21    1
A   05/05/21 3:40   0   05/05/21    -1
A   05/05/21 14:40  158 06/05/21    158
A   05/05/21 14:45  0   06/05/21    -158
A   05/05/21 15:10  1   06/05/21    1
A   07/05/21 9:49   0   07/05/21    -1
B   05/05/21 1:10   500 05/05/21    500
B   05/05/21 1:15   63  05/05/21    -437
B   05/05/21 1:20   0   05/05/21    -63
B   05/05/21 1:35   8   05/05/21    8
B   05/05/21 1:40   0   05/05/21    -8
B   05/05/21 1:45   3   05/05/21    3
B   05/05/21 1:50   0   05/05/21    -3
B   05/05/21 14:35  255 06/05/21    255
B   05/05/21 14:40  0   06/05/21    -255
 

Я хочу отбросить все cap значения, которые появляются после первого падения, до 0 в пределах каждого идентификатора и даты. Есть какие-нибудь указания на то, как я могу этого достичь? Я приложил ожидаемый результат ниже.

 ID  update_time     cap date      diff
A   05/05/21 1:45   136 05/05/21    136
A   05/05/21 1:50   0   05/05/21    -136
A   05/05/21 14:40  158 06/05/21    158
A   05/05/21 14:45  0   06/05/21    -158
B   05/05/21 1:10   500 05/05/21    500
B   05/05/21 1:15   63  05/05/21    -437
B   05/05/21 1:20   0   05/05/21    -63
B   05/05/21 14:35  255 06/05/21    255
B   05/05/21 14:40  0   06/05/21    -255
 

Любые указатели будут оценены по достоинству!

Комментарии:

1. Что означает «после того, как они изначально упадут до 0»? Как получилось, что строка «A, 158» существует, если мы исключаем все после 0, почему бы не рассмотреть строки «A, 1»?

2. A, 158 выбрано, так как значение в столбце «дата» изменяется.

3. @thinrhino это важная деталь, которую я бы рекомендовал вам добавить в свой вопрос!

Ответ №1:

Сначала вам нужно выполнить groupby ID операцию «и date «, так как вы хотите "all rows before a drop to 0 occurs in caps" для каждой уникальной комбинации идентификатора и даты. Затем мы применим пользовательскую функцию, которая выбирает все строки до появления первого нуля. Функция учитывает граничный случай, когда «падение до 0» не может произойти для даты идентификатора, которая происходит только один раз.

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

 import numpy as np
import pandas as pd

## recreate the relevant portion of your DataFrame
df = pd.DataFrame({
    'ID':['A']*10 ['B']*9,
    'cap':[136,0,1,0,1,0,158,0,1,0,500,63,0,8,0,3,0,255,0],
    'date':['05/05/21']*6 ['06/05/21']*3 ['07/05/21'] ['05/05/21']*7 ['06/05/21']*2
})

## get the caps values before the first occurrence of a zero 
def get_caps_before_zero(df_column):
    ## for an ID-cap groupby of length 1, no "drop" to zero can occur, so return an empty DataFrame
    if len(df_column) == 1:
        return df_column.iloc[0:0]
    else:
        idx_first_zero = np.where(df_column == 0)[0].min()   1
        return df_column.iloc[:idx_first_zero]

df_subset = (df.groupby(['ID','date'])
    .apply(lambda x: get_caps_before_zero(x['cap']))
    .reset_index()
    .drop(columns='level_2')
)
 

Выход:

 >>> df_subset
  ID      date  cap
0  A  05/05/21  136
1  A  05/05/21    0
2  A  06/05/21  158
3  A  06/05/21    0
4  B  05/05/21  500
5  B  05/05/21   63
6  B  05/05/21    0
7  B  06/05/21  255
8  B  06/05/21    0
 

Комментарии:

1. Спасибо вам за решение. Узнал несколько новых вещей о пандах.

2. Нет проблем, рад, что мое решение оказалось полезным!