Заставить все строки принимать значение после условия - PullRequest
1 голос
/ 30 сентября 2019

Я работаю над средним размером фрейма данных и после многих манипуляций с данными получаю следующий фрейм данных:

        id_1   id_2  flag_1  flag_2  flag_3
0       000d  5d238       0       0       0
1       001v  5cdd4       0       0       0
2       001v  5d36e       1       1       1
3       001v  5d53c       1       1       1
4       001c  5cc1a       1       0       0
...      ...    ...     ...     ...     ...
124809  003n  5d89f       0       0       0
124810  003n  5d8a6       1       0       0
124811  003n  5d8b1       1       1       0
124812  003n  5d8b3       1       1       1
124813  003n  5d8cc       1       1       1

Вот код, который вы можете использовать для воссоздания фрейма данных:

import pandas as pd
a = {'id_1':['000d','001v','001v','001v','001c','003n','003n','003n','003n','003n'],'id_2':['5d238','5cdd4','5d36e','5d35c','5cc1a','5d89f','5d8a6','5d8b1','5d8b3','5d8cc'],'flag_1':[0,0,1,1,1,0,1,1,1,1],'flag_2':[0,0,1,1,0,0,0,1,1,1],'flag_3':[0,0,1,1,0,0,0,0,1,1]}
pd.DataFrame(a)

Я пытаюсь создать условие, чтобы всякий раз, когда в столбце появлялось 1, все строки после него принудительно становились равными 0 для каждого уникального id_1 и для каждого столбца независимо. Я попытался использовать groupby('id_1')['flag_1'].max(), чтобы создать дополнительный фрейм данных, а затем добавить его, но он не работает (или я, скорее всего, делаю что-то не так). Я также попытался создать список уникальных значений id_1, а затем выполнить итерацию по каждому из них, чтобы найти первую строку со значением 1 и заставить все остальные значения равны 0, а затем повторить цикл для других столбцов, ноэто оказывается очень неэффективным и отнимает много времени. Мой ожидаемый результат:

        id_1   id_2  flag_1  flag_2  flag_3
0       000d  5d238       0       0       0
1       001v  5cdd4       0       0       0
2       001v  5d36e       1       1       1
3       001v  5d53c       0       0       0
4       001c  5cc1a       1       0       0
...      ...    ...     ...     ...     ...
124809  003n  5d89f       0       0       0
124810  003n  5d8a6       1       0       0
124811  003n  5d8b1       0       1       0
124812  003n  5d8b3       0       0       1
124813  003n  5d8cc       0       0       0

Ответы [ 3 ]

3 голосов
/ 30 сентября 2019

Вы можете попробовать это:

df.assign(**df.groupby('id_1')[cols].apply(lambda x: x.ne(1).shift().cumprod() * x).fillna(df))

Вывод:

   id_1   id_2 flag_1 flag_2 flag_3
0   00d  5d238      0      0      0
1  001v  5cdd4      0      0      0
2  001v  5d36e      1      1      1
3  001v  5d35c      0      0      0
4  001c  5cc1a      1      0      0
5  003N  5d89f      0      0      0
6  003N  5d8a6      1      0      0
7  003N  5d8b1      0      1      0
8  003N  5d8b3      0      0      1
9  003N  5d8cc      0      0      0

В основном, используя ne и cumprod в каждой группе. Когда flag = 1, ne (1) возвращает ноль и использует cumprod для сохранения нуля.

2 голосов
/ 30 сентября 2019

Вы можете использовать DataFrame.groupby с , применять :

df.groupby('id_1',as_index=False)['flag_1','flag_2','flag_3'].apply(lambda x:  (x.eq(1))&(x.shift(1).eq(0)) ).astype(int)
print(df)

   id_1   id_2  flag_1  flag_2  flag_3
0   00d  5d238       0       0       0
1  001v  5cdd4       0       0       0
2  001v  5d36e       1       1       1
3  001v  5d35c       0       0       0
4  001c  5cc1a       0       0       0
5  003N  5d89f       0       0       0
6  003N  5d8a6       1       0       0
7  003N  5d8b1       0       1       0
8  003N  5d8b3       0       0       1
9  003N  5d8cc       0       0       0
1 голос
/ 30 сентября 2019

Вот один из способов:

# the flag columns
# can be df.filter(like='flag')
flags = df.iloc[:,2:]

# find the first 1.0 rows for each group
maxidx = flags.where(flags.eq(1)).groupby(df['id_1']).transform('idxmax')

# mask these rows with 1 else 0
df.iloc[:,2:] = np.where(flags.index.values[:,None] == maxidx, 1, 0)

Вывод:

   id_1   id_2  flag_1  flag_2  flag_3
0   00d  5d238       0       0       0
1  001v  5cdd4       0       0       0
2  001v  5d36e       1       1       1
3  001v  5d35c       0       0       0
4  001c  5cc1a       1       0       0
5  003N  5d89f       0       0       0
6  003N  5d8a6       1       0       0
7  003N  5d8b1       0       1       0
8  003N  5d8b3       0       0       1
9  003N  5d8cc       0       0       0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...