Построение данных из разных наборов данных с использованием plotnine и pandas

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


            Date      Time  WSA  WSV  WDV  WSM   SGT   T2M  T10M  DELTA_T   PBAR  SRAD     RH  PM25         AQI
0     2015-01-01  00:00:00  0.9  0.2  334  3.2  70.9  29.2  29.1     -0.1  740.4     8  102.5  69.0  157.970495
1     2015-01-01  01:00:00  1.5  0.7  129  4.0  58.8  29.6  29.2     -0.4  740.2     8  102.5  23.5   74.974249
2     2015-01-01  02:00:00  0.8  0.8   70  2.7  18.0  28.7  28.3     -0.4  740.3     7  102.2  40.1  112.326633
3     2015-01-01  03:00:00  1.1  1.0   82  3.4  21.8  28.2  27.8     -0.4  740.1     6  102.0  31.1   90.957082
4     2015-01-01  04:00:00  1.0  0.8   65  4.7  34.3  27.3  27.2     -0.2  739.7     6  101.7  13.7   54.364807
...          ...       ...  ...  ...  ...  ...   ...   ...   ...      ...    ...   ...    ...   ...         ...
43175 2016-12-30  19:00:00  1.7  0.7  268  4.1  63.6  33.8  34.1      0.3  738.8     8  100.7  38.4  108.140704
43176 2016-12-30  20:00:00  1.5  0.1  169  3.3  77.5  33.2  33.7      0.5  738.7     9  101.0  27.2   82.755365

43177 2016-12-30  21:00:00  1.4  0.5  278  4.0  65.7  32.5  32.8      0.3  738.6     9  101.4  42.5  118.236181
43178 2016-12-30  22:00:00  2.8  2.7  277  6.5  16.7  33.2  33.3      0.1  738.6     9  101.6  25.2   78.549356
43179 2016-12-30  23:00:00  1.9  0.3  241  4.2  74.2  31.0  31.6      0.6  738.4     9  100.4  18.7   64.879828

[43180 rows x 15 columns]

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

mask = (df['Date'].dt.month > 3) & (df['Date'].dt.month < 10)

summer = df[mask]
winter = df[~mask]

summer = summer.groupby(summer['Time'].dt.hour).mean().reset_index()
winter = winter.groupby(winter['Time'].dt.hour).mean().reset_index()

p = (
    ggplot(mapping=aes( x='Time', y='PM25')) +
    geom_point(data=summer, color='red')+
    geom_point(data=winter, color='blue')
    )

print(p)

График с отдельными фреймами данных: [1]: https://i.stack.imgur.com/W75kk.png

Я провел еще несколько исследований и узнал, что plotnine/ggplot может окрашивать точки данных в зависимости от одного из их атрибутов. Этот подход требует, чтобы данные были единым набором данных, поэтому я добавил параметр, указывающий сезон. Однако, когда я группирую по часам, этот атрибут «Сезон» удаляется. Я предполагаю, что это потому, что вы не можете взять среднее значение нечисловых данных. Таким образом, я нахожусь в некотором парадоксе. Вот моя попытка собрать данные вместе и добавить столбец «Сезон»:

df.insert(0,'Season', 0)

summer = (df['Date'].dt.month > 3) & (df['Date'].dt.month < 10)

df['Season'] = df.where(summer, other='w')
df['Season'] = df.where(~summer, other='s')

df = df.groupby(df['Time'].dt.hour).mean()

print(df)

p = (
    ggplot(data = df, mapping=aes( x='Time', y='PM25', color='Season')) +
    geom_point()
    )

print(p)

Когда я пытаюсь запустить это, возникает следующее, и если я просматриваю фрейм данных, все нечисловые параметры удаляются:

plotnine.exceptions.PlotnineError: "Could not evaluate the 'color' mapping: 'Season' (original error: name 'Season' is not defined)" 

Любые предложения будут очень признательны.


person Adam Conrad    schedule 16.07.2020    source источник


Ответы (1)


Предоставленные данные были сохранены в файле airq.csv. Помимо столбца «Сезон» добавлен столбец «Час». Предоставленный код был использован. «Час» и «Сезон» должны быть указаны в функции groupby. Предусмотрены две возможности plotnine.ggplot. Первый использует geom_point, а второй добавляет facet_wrap. Настройка темы была включена для каждого случая.

from plotnine import *
import pandas as pd

df = pd.read_csv('airq.csv', parse_dates=[0,1])
df.insert(0,'Season', 0)
summer = (df['Date'].dt.month > 3) & (df['Date'].dt.month < 9)
df['Season'] = df.where(summer, other='Winter')
df['Season'] = df.where(~summer, other='Summer')
df['Hour'] = df['Time'].dt.hour
df = df.groupby(['Hour', 'Season']).mean().reset_index()
custom_axis = theme(axis_text_x = element_text(color="grey", size=6, angle=90, hjust=.3),
                    axis_text_y = element_text(color="grey", size=6), 
                    plot_title = element_text(size = 25, face = "bold"), 
                    axis_title = element_text(size = 10)  
                    ) 
(
    ggplot(data = df, mapping = aes(x='Hour', y='PM25',
                          color='Season')) + geom_point() +
    custom_axis + ylab("Particulate matter 2.5 micrometres") + xlab("Hour") + labs(title="PM air quality report")
) 

опция geom_point

custom_axis = theme(axis_text_x = element_text(color="grey", size=6, angle=90, hjust=.3),
                    axis_text_y = element_text(color="grey", size=6), 
                    plot_title = element_text(size = 25, face = "bold"), 
                    axis_title = element_text(size = 10), 
                    panel_spacing_y=.4, 
                    figure_size=(8, 4) 
                    ) 

(
    ggplot(data = df, mapping = aes(x='Hour', y='PM25')) + geom_point(alpha=1) + facet_wrap('Season') + 
    custom_axis + ylab("Particulate matter 2.5 micrometres") + xlab("Hour") + labs(title="PM air quality report")
)

Добавление facet_wrap

person GERMAN RODRIGUEZ    schedule 01.08.2020
comment
Моя цель состоит в том, чтобы времена года разделяли один сюжет. В конце концов, я отказался от плотнина и использовал Seaborn. - person Adam Conrad; 02.08.2020