Чтобы упорядочить большой набор данных по месяцам, я пытаюсь преобразовать все фактические даты записи в конец месяца.

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

df['CalcEnd'] = pd.to_datetime(df['ActualDate'], format="%m/%d/%Y") + MonthEnd(1)

Это приводит к:

    ActualDate    CalcEnd
    7/1/2019      7/31/2019
    7/2/2019      7/31/2019
    7/31/2019     8/31/2019

Третья запись должна вернуться 31.07.2009.

Я пытался использовать numpy, чтобы использовать CalcEnd только в том случае, если дата не является концом месяца, чтобы избежать этой проблемы, но по какой-то причине CalcEnd вывел странную серию чисел, если это не был уже конец месяца.

Конкретно я пытался:

def isMonthEnd(date):
    return date + pd.offsets.MonthEnd(0) == date

df['EndCheck'] = isMonthEnd(pd.to_datetime(df['ActualDate'], format="%m/%d/%Y"))
df['CalcEnd'] = pd.to_datetime(df['ActualDate'], format="%m/%d/%Y") + MonthEnd(1)
df['End'] = np.where(df['EndCheck']==False, df['CalcEnd'], df['ActualDate'])

Когда EndCheck имеет значение False, вместо отображения 31.07.2009, он показывает 1564531200000000000.

Но когда это правда, он показывает ActualDate как 31.07.2009.

Любой совет по:

1) Как преобразовать все указанные даты в кадре данных в конец месяца, даже если данная дата уже является концом месяца; и

2) Почему оператор np.where не работает при попытке использовать вычисляемый столбец

.... будет принята с благодарностью!

Я смог найти обходной путь, просто записав фрейм данных в CSV и прочитав этот новый CSV обратно в фрейм данных перед созданием End; кажется, что это решает проблему с помощью оператора np.where, возвращающего 1564531200000000000. Однако я надеюсь, что есть более элегантное решение.

Спасибо!

0
Chrestomanci 15 Авг 2019 в 02:04

2 ответа

Лучший ответ

Это поведение упоминается в документах:

Если п не 0 , если данная дата не на узловую точку, она привязывается к следующей (предыдущей) точки привязки , и переехал | п | -1 дополнительные шаги вперед или назад. , Если данная дата на опорной точке , он перемещается | п | указывает вперед или назад.

Вам не нужно np.where. Исправить это просто. Если вы идете вперед, просто вычтите один день, прежде чем добавить якорь. Если вы идете назад, добавьте один день, прежде чем вычесть якорь

Вы идете вперед к MonthEnd, так что просто вычтите один день перед добавлением якоря

df['CalcEnd'] = df['ActualDate']  - pd.offsets.Day() + pd.offsets.MonthEnd(1)

Out[370]:
  ActualDate    CalcEnd
0 2019-07-01 2019-07-31
1 2019-07-02 2019-07-31
2 2019-07-31 2019-07-31
2
Andy L. 15 Авг 2019 в 00:13

Просто проверьте, находится ли дата в том же месяце, если вы добавляете один день и делаете смещение в зависимости от результата

def to_end_of_month(date):
    if (date + pd.offsets.Day(1)).month == date.month:
        return date + pd.offsets.MonthEnd(1)
    else:
        return date + pd.offsets.MonthEnd(0)

df['CalcEnd'] = df['ActualDate'].apply(to_end_of_month)

Результат

    ActualDate  CalcEnd
0   2019-07-01  2019-07-31
1   2019-07-02  2019-07-31
2   2019-07-31  2019-07-31
2
pythonic833 14 Авг 2019 в 23:42