Индекс / нарезка Pandas DataFrame с объектами Numpy datetime64

1

Я хотел бы узнать, смогу ли я сделать следующее для работы (Pandas 0.23.4). Любая помощь будет оценена по достоинству.

import numpy as np
import pandas as pd

rows = 12
rng = pd.date_range('2011-01', periods=rows, freq='M')

df = pd.DataFrame(np.arange(rows), index=rng)

print(df.loc['2011-01'])
print(df.loc[np.datetime64('2011-01')])

Первый print делает то, что я ожидаю: показывает все строки, которые находятся в январе 2011 года. Однако второй генерирует KeyError потому что значение не находится в индексе. Я надеялся, что он предоставит тот же результат, но после некоторого тестирования я понимаю, что он ищет точное соответствие 2011-01-01, которого нет в DataFrame. Я бы хотел, чтобы второй работал, так что я могу использовать numpy.arange или pandas.date_range чтобы легко создавать массивы дат, которые я могу выполнить. Кто-нибудь получил это на работу? (Похоже, это работает, но только если у вас есть точное соответствие датам.)

  • 0
    Спасибо за помощь cryptonome и jpp. К сожалению, похоже, что ответом для этой конкретной версии Панд является «Нет. Вы не можете сделать это точно». Я пометил ответ jpp как правильный, потому что он не требует другого цикла.
Теги:
pandas
numpy
datetime
indexing

2 ответа

1
Лучший ответ

Вы можете написать функцию для преобразования np.datetime64 в строки, совместимые с Pandas:

def stringify(x):
    year = x.astype('datetime64[Y]').astype(int) + 1970
    month = x.astype('datetime64[M]').astype(int) % 12 + 1
    return f'{year}-{month:02}'

a = df.loc['2011-01']
b = df.loc[stringify(np.datetime64('2011-01'))]

assert a.equals(b)
1

используйте DatetimeIndex.to_period() & Period.month

import numpy as np
import pandas as pd

rows = 12
rng = pd.date_range('2011-01', periods=rows, freq='M')

df = pd.DataFrame(np.arange(rows), index=rng)

# print(df.loc['2011-01'])
for idx, di in enumerate(df.index.to_period()):
    if di.month == np.datetime64('2011-01').item().month:
        print(f'loc: [{idx}] == {df.index[idx]}')

выход:

# loc: [0] == 2011-01-31 00:00:00

Поскольку ваши индексы df состоят из дат конца месяца, вы можете использовать этот трюк, чтобы использовать df.loc для получения строки:

>>>> df.loc[df.index == np.datetime64('2011-03', 'D') -1]
            0
2011-02-28  1

>>>> df.loc[df.index == np.datetime64('2011-04', 'D') -1]
            0
2011-03-31  2

>>>> df[df.index == np.datetime64('2011-12', 'D') -1]
             0
2011-11-30  10

# use 2012 January 1st minus one day to get 2011 Dec 31st
>>>> df[df.index == np.datetime64('2012-01', 'D') -1]
             0
2011-12-31  11
  • 0
    Спасибо @cryptonome. Метод to_period интересен; Я должен рассмотреть это. Однако я надеялся, что это можно сделать без добавления еще одного явного цикла, если это возможно. Неявное зацикливание в Numpy / Pandas намного более эффективно ...
  • 0
    так как ваш индекс всегда является концом месяца, а ваш np.datetime64 представлен в формате year-month , для этого можно воспользоваться трюком. позвольте мне отредактировать мой ответ.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню