Есть ли способ сохранить строки с указанным c условием и удалить другие, если это условие не выполняется? - PullRequest
2 голосов
/ 21 января 2020

У меня есть следующий фрейм данных (df)

                ID  start                        end                     Diff
                A   1/8/2020 12:00:00 AM         1/8/2020 12:00:10 AM    10
                A   1/8/2020 12:00:05 AM         1/8/2020 12:00:10 AM    5
                B   1/9/2020 1:00:05 AM          1/9/2020 1:00:10 AM     5
                B   1/9/2020 1:00:06 AM          1/9/2020 1:00:10 AM     4
                B   1/9/2020 1:00:20 AM          1/9/2020 1:00:25 AM     5
                C   1/10/2020 5:00:05 AM         1/10/2020 5:00:25 AM    20
                C   1/10/2020 5:00:40 AM         1/10/2020 5:00:45 AM    5

Вот проблема: Когда времена окончания идентичны, я хотел бы удалить строку с большей продолжительностью, удалив строку с самой короткой длительность.

Желаемый результат:

                ID  start                      end                     Diff
                A   1/8/2020 12:00:05 AM       1/8/2020 12:00:10 AM    5
                B   1/9/2020 1:00:06 AM        1/9/2020 1:00:10 AM     4
                B   1/9/2020 1:00:20 AM        1/9/2020 1:00:25 AM     5
                C   1/10/2020 5:00:05 AM       1/10/2020 5:00:25 AM    20
                C   1/10/2020 5:00:40 AM       1/10/2020 5:00:45 AM    5

По существу, когда время окончания идентично, я буду sh, чтобы удалить строку с большей продолжительностью. Я пробовал это, однако, это не принимая во внимание условие: сохранить строку более короткой продолжительности, когда время окончания идентично

                df.sort_values(['Diff']).drop_duplicates(subset=['ID'])

Любое предложение (я) приветствуется.

Ответы [ 4 ]

3 голосов
/ 21 января 2020

Мы могли бы использовать Series.map

df[df['Diff'].eq(df['end'].map(df.groupby('end')['Diff'].min()))]

  ID                 start                   end  Diff
1  A  1/8/2020 12:00:05 AM  1/8/2020 12:00:10 AM     5
3  B   1/9/2020 1:00:06 AM   1/9/2020 1:00:10 AM     4
4  B   1/9/2020 1:00:20 AM   1/9/2020 1:00:25 AM     5
5  C  1/10/2020 5:00:05 AM  1/10/2020 5:00:25 AM    20
6  C  1/10/2020 5:00:40 AM  1/10/2020 5:00:45 AM     5
3 голосов
/ 21 января 2020

Используйте groupby для end столбца, преобразованного с минимальным значением Diff, затем сравните с df['Diff'] и оставьте те, которые возвращают True, проверьте, как преобразование возвращает минимум для всей группы ниже:

df[df['Diff'].eq(df.groupby('end')['Diff'].transform('min'))]

  ID                 start                   end  Diff
1  A  1/8/2020 12:00:05 AM  1/8/2020 12:00:10 AM     5
3  B   1/9/2020 1:00:06 AM   1/9/2020 1:00:10 AM     4
4  B   1/9/2020 1:00:20 AM   1/9/2020 1:00:25 AM     5
5  C  1/10/2020 5:00:05 AM  1/10/2020 5:00:25 AM    20
6  C  1/10/2020 5:00:40 AM  1/10/2020 5:00:45 AM     5

Выход groupby+transform

print(df.groupby('end')['Diff'].transform('min'))

0     5
1     5
2     4
3     4
4     5
5    20
6     5

print(df['Diff'].eq(df.groupby('end')['Diff'].transform('min')))

0    False
1     True
2    False
3     True
4     True
5     True
6     True
2 голосов
/ 21 января 2020

Сортировка по 'start', и «более короткая» продолжительность, естественно, будет последней. Затем используйте drop_duplicates

df.sort_values(['ID', 'start', 'end']).drop_duplicates(['ID', 'end'], keep='last')

  ID               start                 end  Diff
1  A 2020-01-08 00:00:05 2020-01-08 00:00:10     5
3  B 2020-01-09 01:00:06 2020-01-09 01:00:10     4
4  B 2020-01-09 01:00:20 2020-01-09 01:00:25     5
5  C 2020-01-10 05:00:05 2020-01-10 05:00:25    20
6  C 2020-01-10 05:00:40 2020-01-10 05:00:45     5
1 голос
/ 21 января 2020

Сортировка по ID и end, затем выберите самую короткую Diff.

>>> df.sort_values(['ID', 'end', 'Diff']).groupby(['ID', 'end'], sort=False).head(1)

  ID                 start                   end  Diff
1  A  1/8/2020 12:00:05 AM  1/8/2020 12:00:10 AM     5
3  B   1/9/2020 1:00:06 AM   1/9/2020 1:00:10 AM     4
4  B   1/9/2020 1:00:20 AM   1/9/2020 1:00:25 AM     5
5  C  1/10/2020 5:00:05 AM  1/10/2020 5:00:25 AM    20
6  C  1/10/2020 5:00:40 AM  1/10/2020 5:00:45 AM     5
...