Индексирование / нарезка фрейма данных Pandas с объектами Numpy datetime64

Я хотел бы выяснить, смогу ли я заставить работать следующее (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 для легкого создания массивов дат, которые я мог бы перебирать. У кого-нибудь это работает? (Похоже на это работает, но только если у вас есть точное совпадение дат.)

Спасибо за помощь cryptonome и jpp. К сожалению, похоже, что ответ для этой конкретной версии Pandas - «Нет. Вы не можете сделать это точно». Я отметил ответ jpp как правильный, потому что для него не требуется еще один цикл.

Ryan 21.10.2018 14:52
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
791
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

используйте DatetimeIndex.to_period () & Период. Месяц

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

Спасибо @cryptonome. Интересен метод to_period; Я должен это учитывать. Однако я надеялся найти способ сделать это без добавления еще одного явного цикла, если это возможно. Неявный цикл в Numpy / Pandas намного эффективнее ...

Ryan 20.10.2018 02:27

поскольку ваш индекс всегда указывает на конец месяца, а ваш np.datetime64 находится в формате year-month, вы можете использовать для этого трюк. позвольте мне отредактировать свой ответ.

deadvoid 20.10.2018 03:07

Еще раз спасибо, @cryptonome. К сожалению, ваш новый код работает только для точных совпадений. Я надеялся провести поиск весь месяц. Тем не менее, я ценю вашу помощь.

Ryan 21.10.2018 14:50

все в порядке @ Райан, может я неправильно понял твой вопрос

deadvoid 22.10.2018 04:44
Ответ принят как подходящий

Вы можете написать функцию для преобразования 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)

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