pandas: группа фильтров по нескольким условиям?

у меня есть фрейм данных, который выглядит так:

df = pd.DataFrame([
  {'id': 123, 'date': '2016-01-01', 'is_local': True },
  {'id': 123, 'date': '2017-01-01', 'is_local': False },
  {'id': 124, 'date': '2016-01-01', 'is_local': True },
  {'id': 124, 'date': '2017-01-01', 'is_local': True }
])
df.date = df.date.astype('datetime64[ns]')

Я хочу получить список всех идентификаторов, для которых is_local было истинно в начале 2016 года, но ложно в начале 2017 года. Я начал с группировки по ID:

gp = df.groupby('id')

тогда я попытался это просто фильтровать по второму из этих условий (как способ начать работу), но он возвращает все группы:

gp.apply(lambda x: ~x.is_local & (x.date > '2016-12-31'))

как я могу фильтровать так, как мне нужно?

3 ответов


d1 = df.set_index(['id', 'date']).is_local.unstack()
d1.index[d1['2016-01-01'] & ~d1['2017-01-01']].tolist()

[123]

другой способ сделать это через поворот:

In [24]: ids_by_dates = df.pivot(index='id', columns='date',values='is_local')

In [25]: ids_by_dates['2016-01-01'] & ~ids_by_dates['2017-01-01']
Out[25]: 
id
123     True
124    False

вы можете попробовать использовать модуль datetime из библиотеки datetime и передать несколько условий для фрейма данных

from datetime import datetime
df = pd.DataFrame([
  {'id': 123, 'date': '2016-01-01', 'is_local': True },
  {'id': 123, 'date': '2017-01-01', 'is_local': False },
  {'id': 124, 'date': '2016-01-01', 'is_local': True },
  {'id': 124, 'date': '2017-01-01', 'is_local': True }
])
df.date = df.date.astype('datetime64[ns]')

используйте несколько условий для вырезания требуемого фрейма данных

a = df[(df.is_local==True) & (df.date<datetime(2016,12,31) & (df.date>datetime(2015,12,31))]
b = df[(df.is_local==False) & (df.date<datetime(2017,12,31)) & (df.date>datetime(2016,12,31))]

используйте pandas concatenate позже

final_df = pd.concat((a,b))

выведет вам строки 1 и 2

    date        id  is_local
2   2016-01-01  124 True
1   2017-01-01  123 False

в одной строке следующим образом

final_df = pd.concat((df[(df.is_local==True) & (df.date<datetime(2016,12,31) & (df.date>datetime(2015,12,31))], df[(df.is_local==False) & (df.date<datetime(2017,12,31)) & (df.date>datetime(2016,12,31))]))