Удалить строки ниже первого вхождения определенного значения - PullRequest
0 голосов
/ 01 января 2019

Цель состоит в том, чтобы определить, когда c и d в code, для каждого уникального ID, происходит после a, а затем установить подкадр данных (подмножество groupby будет таким же хорошим), чтобы не включатьэти ID с.

Пример df:

df = pd.DataFrame({'ID':np.repeat([1,2,3],[3,4,3]), 'dates' : [(pd.Timestamp('2018-12-30 00:00:00') + pd.Timedelta(hr, unit = 'h')) for hr in range(10)], 'cd': ['c','b','a','b','c','a','c','b','a','d']})

grouped = df.groupby('ID', as_index = False).apply(lambda x: x.sort_values('dates', ascending = False))

grouped = grouped.groupby('ID')

С этим набором данных ID==2 и ID==3 должны быть удалены из df:

for key, item in grouped:
    print(grouped.get_group(key), "\n\n")

Вывод:

     ID               dates cd
0 2   1 2018-12-30 02:00:00  a
  1   1 2018-12-30 01:00:00  b
  0   1 2018-12-30 00:00:00  c 


     ID               dates cd
1 6   2 2018-12-30 06:00:00  c
  5   2 2018-12-30 05:00:00  a
  4   2 2018-12-30 04:00:00  c
  3   2 2018-12-30 03:00:00  b 


     ID               dates cd
2 9   3 2018-12-30 09:00:00  d
  8   3 2018-12-30 08:00:00  a
  7   3 2018-12-30 07:00:00  b 

Я думаю, что следующая цель достигает этой цели, когда она создает строку для каждой группы, а затем использует str.find() для определения приоритета:

for i,r in grouped:
    cdSeq = ''
    for code in r['cd']:
        cdSeq+=code
    if abs(cdSeq.find('c')) < abs(cdSeq.find('a')) or abs(cdSeq.find('d'))<abs(cdSeq.find('a')):
        df = df[df['ID']!=i]

df.groupby('ID', as_index = False).apply(lambda x: x.sort_values('dates', ascending = False))

Вывод:

       ID                 dates cd
0   2   1   2018-12-30 02:00:00  a
    1   1   2018-12-30 01:00:00  b
    0   1   2018-12-30 00:00:00  c

Есть ли более лаконичный, эффективный и / или питонский способ сделать это?

1 Ответ

0 голосов
/ 01 января 2019

Во-первых, определите, какие строки появляются после "a" в группе как u.Затем определите, какие строки содержат «c» и «d», как v.Используя mul, мы определяем, какие строки соответствуют нашим критериям, а затем используем groupby и any, чтобы получить маску для их устранения.

u = df['cd'].eq('a').groupby(df.ID).cumsum()
v = df['cd'].isin(['c', 'd'])

df[~u.mul(v).groupby(df.ID).transform('any')]

   ID               dates cd
0   1 2018-12-30 00:00:00  c
1   1 2018-12-30 01:00:00  b
2   1 2018-12-30 02:00:00  a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...