Передискретизировать multiindex

У меня есть DataFrame с MultiIndex. Первый уровень - это DatetimeIndex с еженедельной периодичностью. Второй уровень - это НЕТ, согласованный между группировками по первому уровню.

Я хочу сгруппировать первый уровень по месяцам и взять строки первых недель.

Настраивать

midx = pd.MultiIndex.from_arrays([
    pd.date_range('2018-01-01', freq='W', periods=10).repeat(2),
    list('ABCDEFGHIJ' * 2)
], names=['Date', 'Thing'])

df = pd.DataFrame(dict(Col=np.arange(10, 30)), midx)

Ожидаемые результаты

df

                  Col    
Date       Thing     
2018-01-07 A       10    # This is the first week
           B       11    # of January 2018 
2018-01-14 C       12
           D       13
2018-01-21 E       14
           F       15
2018-01-28 G       16
           H       17
2018-02-04 I       18    # This is the first week
           J       19    # of February 2018
2018-02-11 A       20
           B       21
2018-02-18 C       22
           D       23
2018-02-25 E       24
           F       25
2018-03-04 G       26    # This is the first week
           H       27    # of March 2018
2018-03-11 I       28
           J       29

Результаты должны быть

                  Col    
Date       Thing     
2018-01-07 A       10    # This is the first week
           B       11    # of January 2018 
2018-02-04 I       18    # This is the first week
           J       19    # of February 2018
2018-03-04 G       26    # This is the first week
           H       27    # of March 2018

Пытаться

df.unstack().asfreq('M', 'ffill').stack()

                   Col
Date       Thing      
2018-01-31 G      16.0
           H      17.0
2018-02-28 E      24.0
           F      25.0

Это неверно на нескольких уровнях.

  1. Дата - это фактический конец месяца, а не фактическая наблюдаемая дата.
  2. Вещи не с правильной даты. Обратите внимание, что я хотел ['A', 'B'] от '2018-01-07', а не ['G', 'H'].
  3. Я распаковываю, чтобы позволить себе использовать asfreq, но это вводит nan и конвертирует в float
  4. Я не знаю, что случилось с March 2018
1
0
1 042
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ты мог бы сделать

In [384]: date = df.index.get_level_values('Date')

In [385]: firstweek = date.to_frame().groupby(date.strftime('%Y-%m')).min()['Date']

In [386]: df[date.isin(firstweek)]
Out[386]:
                  Col
Date       Thing
2018-01-07 A       10
           B       11
2018-02-04 I       18
           J       19
2018-03-04 G       26
           H       27

Подробности

In [387]: date.to_frame().groupby(date.strftime('%Y-%m')).min()
Out[387]:
              Date
2018-01 2018-01-07
2018-02 2018-02-04
2018-03 2018-03-04

Альтернатива.

In [400]: fweek = df.assign(dt=date).resample('M', level='Date')['dt'].min()

In [401]: df[date.isin(fweek)]
Out[401]:
                  Col
Date       Thing
2018-01-07 A       10
           B       11
2018-02-04 I       18
           J       19
2018-03-04 G       26
           H       27

Мне это очень нравится!

piRSquared 10.08.2018 15:31

У меня было другое решение, но это привело к df.loc[df.index.get_level_values(0).to_series().resample('M'‌​).first()], который намного лучше.

piRSquared 10.08.2018 15:36

Ах, это мило.

Zero 10.08.2018 15:37

Если первая неделя месяца - это только первые семь дней месяца, вы можете просто отфильтровать вот так

df[df.index.get_level_values(0).day <= 7]

                Col
Date       Thing     
2018-01-07 A       10
           B       11
2018-02-04 I       18
           J       19
2018-03-04 G       26
           H       27

Если вы не ищете первую неделю, заканчивающуюся воскресеньем, в этом случае это не сработает.

Умно, но легко ломается.

piRSquared 10.08.2018 16:12

Другие вопросы по теме