Уменьшите фрейм данных интервала pandas до таблицы совокупных значений за 12 месяцев x 24 часа

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

Формат годовой сводки будет представлять собой таблицу за 12 месяцев x 24 часа (288 отдельных ячеек), где каждая ячейка представляет собой либо среднее, либо максимальное значение, либо количество всех значений за этот конкретный месяц и час.

Для простоты давайте просто посмотрим на подсчет количества. (Из предложений я могу сделать вывод о выполнении аналогичных вычислений для средних и максимальных значений.)

Я попробовал грубый подход к фильтрации временных меток по месяцам и часам (цикл из 288 значений) и сведению подсчетов в матрицу. Однако этот подход кажется очень медленным, поскольку я выполняю эти расчеты даже на 20 метрах. Мне любопытно, есть ли более быстрый способ добиться этого с использованием pandas/numpy.

Ниже приведен пример форматирования интервальных данных.

from datetime import datetime
import pandas as pd

df = pd.DataFrame()
df["start"] = pd.date_range(start=datetime(2018, 1, 1), end=datetime(2018, 12, 31, 23), freq='900S')
df["value"] = 1
df.set_index("start", inplace=True)

В настоящее время я выполняю расчет по следующим направлениям:

for month in range(1, 13):
    for hour in range(0, 24):
        count = df.query("index.dt.month == {} and index.dt.hour == {}".format(month, hour)).count()

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

     1    2    3    4    5    6    7    8    9    10   11   12
0   124  112  124  120  124  120  124  124  120  124  120  124
1   124  112  124  120  124  120  124  124  120  124  120  124
2   124  112  124  120  124  120  124  124  120  124  120  124
3   124  112  124  120  124  120  124  124  120  124  120  124
4   124  112  124  120  124  120  124  124  120  124  120  124
5   124  112  124  120  124  120  124  124  120  124  120  124
6   124  112  124  120  124  120  124  124  120  124  120  124
7   124  112  124  120  124  120  124  124  120  124  120  124
8   124  112  124  120  124  120  124  124  120  124  120  124
9   124  112  124  120  124  120  124  124  120  124  120  124
10  124  112  124  120  124  120  124  124  120  124  120  124
11  124  112  124  120  124  120  124  124  120  124  120  124
12  124  112  124  120  124  120  124  124  120  124  120  124
13  124  112  124  120  124  120  124  124  120  124  120  124
14  124  112  124  120  124  120  124  124  120  124  120  124
15  124  112  124  120  124  120  124  124  120  124  120  124
16  124  112  124  120  124  120  124  124  120  124  120  124
17  124  112  124  120  124  120  124  124  120  124  120  124
18  124  112  124  120  124  120  124  124  120  124  120  124
19  124  112  124  120  124  120  124  124  120  124  120  124
20  124  112  124  120  124  120  124  124  120  124  120  124
21  124  112  124  120  124  120  124  124  120  124  120  124
22  124  112  124  120  124  120  124  124  120  124  120  124
23  124  112  124  120  124  120  124  124  120  124  120  124
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
130
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Вы можете использовать pandas.crosstab, а затем, при необходимости, использовать DataFrame.rename_axis для удаления имен осей в соответствии с желаемым результатом.

df_new = (pd.crosstab(df.index.hour, df.index.month)
          .rename_axis(None)
          .rename_axis(None, axis=1))

[выход]

     1    2    3    4    5    6    7    8    9    10   11   12
0   124  112  124  120  124  120  124  124  120  124  120  124
1   124  112  124  120  124  120  124  124  120  124  120  124
2   124  112  124  120  124  120  124  124  120  124  120  124
3   124  112  124  120  124  120  124  124  120  124  120  124
4   124  112  124  120  124  120  124  124  120  124  120  124
5   124  112  124  120  124  120  124  124  120  124  120  124
6   124  112  124  120  124  120  124  124  120  124  120  124
7   124  112  124  120  124  120  124  124  120  124  120  124
8   124  112  124  120  124  120  124  124  120  124  120  124
9   124  112  124  120  124  120  124  124  120  124  120  124
10  124  112  124  120  124  120  124  124  120  124  120  124
11  124  112  124  120  124  120  124  124  120  124  120  124
12  124  112  124  120  124  120  124  124  120  124  120  124
13  124  112  124  120  124  120  124  124  120  124  120  124
14  124  112  124  120  124  120  124  124  120  124  120  124
15  124  112  124  120  124  120  124  124  120  124  120  124
16  124  112  124  120  124  120  124  124  120  124  120  124
17  124  112  124  120  124  120  124  124  120  124  120  124
18  124  112  124  120  124  120  124  124  120  124  120  124
19  124  112  124  120  124  120  124  124  120  124  120  124
20  124  112  124  120  124  120  124  124  120  124  120  124
21  124  112  124  120  124  120  124  124  120  124  120  124
22  124  112  124  120  124  120  124  124  120  124  120  124
23  124  112  124  120  124  120  124  124  120  124  120  124

Значит, cross_tab ведет подсчет по умолчанию (если вы не передадите aggfunc?)

Andy Hayden 08.04.2019 21:08

@AndyHayden да точно

Chris Adams 08.04.2019 21:09

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

Andy Hayden 08.04.2019 21:18

Работает как шарм! Просто для справки: я смог вычислить «среднее» и «максимальное» с помощью pd.crosstab(df.index.hour, df.index.month, df.values, aggfunc=aggfunc), где aggfunc — это np.mean и np.max соответственно.

Sean Chon 08.04.2019 23:49

Я бы использовал groupby, а затем распаковал:

In [11]: res = df.groupby([df.index.month, df.index.hour])["value"].sum().unstack(0, fill_value=0)

In [12]: res.columns.name = "month"  # or None to suppress

In [13]: res.index.name = "hour"  # or None to suppress

In [14]: res
Out[44]:
month   1    2    3    4    5    6    7    8    9    10   11   12
hour
0      124  112  124  120  124  120  124  124  120  124  120  124
1      124  112  124  120  124  120  124  124  120  124  120  124
2      124  112  124  120  124  120  124  124  120  124  120  124
3      124  112  124  120  124  120  124  124  120  124  120  124
4      124  112  124  120  124  120  124  124  120  124  120  124
5      124  112  124  120  124  120  124  124  120  124  120  124
6      124  112  124  120  124  120  124  124  120  124  120  124
7      124  112  124  120  124  120  124  124  120  124  120  124
8      124  112  124  120  124  120  124  124  120  124  120  124
9      124  112  124  120  124  120  124  124  120  124  120  124
10     124  112  124  120  124  120  124  124  120  124  120  124
11     124  112  124  120  124  120  124  124  120  124  120  124
12     124  112  124  120  124  120  124  124  120  124  120  124
13     124  112  124  120  124  120  124  124  120  124  120  124
14     124  112  124  120  124  120  124  124  120  124  120  124
15     124  112  124  120  124  120  124  124  120  124  120  124
16     124  112  124  120  124  120  124  124  120  124  120  124
17     124  112  124  120  124  120  124  124  120  124  120  124
18     124  112  124  120  124  120  124  124  120  124  120  124
19     124  112  124  120  124  120  124  124  120  124  120  124
20     124  112  124  120  124  120  124  124  120  124  120  124
21     124  112  124  120  124  120  124  124  120  124  120  124
22     124  112  124  120  124  120  124  124  120  124  120  124
23     124  112  124  120  124  120  124  124  120  124  120  124

Примечание. Я получаю разные значения, я получаю ~ 120, поскольку 4 раза в час умножается на количество дней в каждом месяце (некоторые месяцы длиннее других)...

Хорошо поймал! Я исправил вопрос, чтобы отразить правильный ожидаемый результат.

Sean Chon 08.04.2019 22:48

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