Как переформатировать блок данных с различными функциями, применяемыми к каждому столбцу?
Я имею временные ряды с температурой и излучением в pandas dataframe
. Временное разрешение равно 1 минуте.
import datetime
import pandas as pd
import numpy as np
date_times = pd.date_range(datetime.datetime(2012, 4, 5, 8, 0),
datetime.datetime(2012, 4, 5, 12, 0),
freq='1min')
tamb = np.random.sample(date_times.size) * 10.0
radiation = np.random.sample(date_times.size) * 10.0
frame = pd.DataFrame(data={'tamb': tamb, 'radiation': radiation},
index=date_times)
frame
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 241 entries, 2012-04-05 08:00:00 to 2012-04-05 12:00:00
Freq: T
Data columns:
radiation 241 non-null values
tamb 241 non-null values
dtypes: float64(2)
Как я могу понизить выбор этого dataframe
до разрешения одного часа, вычисляя почасовое среднее значение для температуры и почасовой суммы для излучения?
Ответы
Ответ 1
С pandas 0.18 изменился API перепрограммирования (см. docs).
Итак, для pandas >= 0.18 ответ:
In [31]: frame.resample('1H').agg({'radiation': np.sum, 'tamb': np.mean})
Out[31]:
tamb radiation
2012-04-05 08:00:00 5.161235 279.507182
2012-04-05 09:00:00 4.968145 290.941073
2012-04-05 10:00:00 4.478531 317.678285
2012-04-05 11:00:00 4.706206 335.258633
2012-04-05 12:00:00 2.457873 8.655838
Старый ответ:
Я отвечаю на свой вопрос, чтобы отразить изменения, связанные с временными рядами в pandas >= 0.8
(все остальные ответы устарели).
Используя pandas >= 0,8, ответ:
In [30]: frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean})
Out[30]:
tamb radiation
2012-04-05 08:00:00 5.161235 279.507182
2012-04-05 09:00:00 4.968145 290.941073
2012-04-05 10:00:00 4.478531 317.678285
2012-04-05 11:00:00 4.706206 335.258633
2012-04-05 12:00:00 2.457873 8.655838
Ответ 2
Вы также можете уменьшить использование asof
метода pandas.DateRange
объектов.
In [21]: hourly = pd.DateRange(datetime.datetime(2012, 4, 5, 8, 0),
... datetime.datetime(2012, 4, 5, 12, 0),
... offset=pd.datetools.Hour())
In [22]: frame.groupby(hourly.asof).size()
Out[22]:
key_0
2012-04-05 08:00:00 60
2012-04-05 09:00:00 60
2012-04-05 10:00:00 60
2012-04-05 11:00:00 60
2012-04-05 12:00:00 1
In [23]: frame.groupby(hourly.asof).agg({'radiation': np.sum, 'tamb': np.mean})
Out[23]:
radiation tamb
key_0
2012-04-05 08:00:00 271.54 4.491
2012-04-05 09:00:00 266.18 5.253
2012-04-05 10:00:00 292.35 4.959
2012-04-05 11:00:00 283.00 5.489
2012-04-05 12:00:00 0.5414 9.532
Ответ 3
Чтобы подделать вас, в pandas 0.8.0 (при интенсивном развитии в ветке timeseries
на GitHub), вы сможете:
In [5]: frame.convert('1h', how='mean')
Out[5]:
radiation tamb
2012-04-05 08:00:00 7.840989 8.446109
2012-04-05 09:00:00 4.898935 5.459221
2012-04-05 10:00:00 5.227741 4.660849
2012-04-05 11:00:00 4.689270 5.321398
2012-04-05 12:00:00 4.956994 5.093980
Вышеупомянутые методы являются правильной стратегией с текущей производственной версией pandas.
Ответ 4
Вам нужно использовать groupby
как таковой:
grouped = frame.groupby(lambda x: x.hour)
grouped.agg({'radiation': np.sum, 'tamb': np.mean})
# Same as: grouped.agg({'radiation': 'sum', 'tamb': 'mean'})
с выходом:
radiation tamb
key_0
8 298.581107 4.883806
9 311.176148 4.983705
10 315.531527 5.343057
11 288.013876 6.022002
12 5.527616 8.507670
Итак, по сути, я расщепляю на значение часа, а затем вычисляю среднее значение tamb
и сумму radiation
и возвращаю обратно DataFrame
(аналогичный подход к R ddply
). Для получения дополнительной информации я бы посмотрел страницу документации groupby, а также это сообщение в блоге.
Изменить: Чтобы сделать этот масштаб немного лучше, вы можете группировать как день, так и время:
grouped = frame.groupby(lambda x: (x.day, x.hour))
grouped.agg({'radiation': 'sum', 'tamb': 'mean'})
radiation tamb
key_0
(5, 8) 298.581107 4.883806
(5, 9) 311.176148 4.983705
(5, 10) 315.531527 5.343057
(5, 11) 288.013876 6.022002
(5, 12) 5.527616 8.507670