#python #pandas #matplotlib #seaborn
#python #pandas #matplotlib #сиборн
Вопрос:
У меня есть еженедельные данные временных рядов, которые я хочу использовать для построения еженедельного линейного графика matplotlib/seaborn
. Для этого я правильно агрегировал данные временных рядов и попытался построить графики, но результат был для меня неправильным. По сути, в моих данных столбцы представляют собой список стран, а индекс — еженедельный временной индекс. Что я хотел сделать, так это сначала выполнить итерацию столбцов pandas по каждой стране, а затем сгруппировать их по годам и неделям, чтобы у меня была еженедельная линейная диаграмма для каждой страны. Способ агрегирования моих данных немного неэффективен, что, как я полагаю, и создало мне проблему. Кто-нибудь может предложить мне возможный способ сделать это? Любой способ получить линейную диаграмму путем итерации столбцов pandas, в которых группируется его временной индекс? Есть идеи?
моя попытка и данные
import pandas as pd
import matplotlib.pyplot as plt
url = 'https://gist.githubusercontent.com/adamFlyn/7c96d7f7c05f16abcc39befcd74f5ca8/raw/8997332cd3cdec7610aeaa0300a1b85f9daafccb/prod_sales.csv'
df = pd.read_csv(url, parse_dates=['date'])
df.drop(columns=['Unnamed: 0'], inplace=True)
df1_bf.index = pd.to_datetime(df1_bf.index, errors="coerce")
df1_bf.index.name = 'date'
df1_bf.reset_index('date')
df1_bf['year'] = pd.DatetimeIndex(df1_bf.index).year
df1_bf['week'] = pd.DatetimeIndex(df1_bf.index).week
for i in df1_bf.columns:
df_grp = df1.groupby(['year', 'week'])[i].sum().unstack()
fig,ax1 = plt.subplots(nrows=1,ncols=1,squeeze=True,figsize=(16,10))
for j in df_grp['year']:
ax1.plot(df_grp.week, j, next(linecycler),linewidth=3)
plt.gcf().autofmt_xdate()
plt.style.use('ggplot')
plt.xticks(rotation=0)
plt.show()
plt.close()
но я не смог получить правильный график, выполнив описанное выше. Кажется, я могу ошибаться в части агрегирования данных для создания данных графика. Кто-нибудь может предложить мне возможный способ сделать это правильно? есть мысли?
желаемый результат
Это пример графика, который я хочу создать. Я хочу повторить столбцы pandas, а затем сгруппировать его timeindex, поэтому я хочу получить линейный график еженедельных временных рядов для каждой страны в цикле.
как я должен получить этот желаемый график? Есть ли какой-нибудь способ сделать это правильно с matplotlib
помощью или seaborn
? Есть идеи?
Ответ №1:
Вам нужен melt
ваш фрейм данных, а затем groupby
. Затем используйте Seaborn
для создания графика, передавая данные, x, y и hue
. Передача hue
позволяет избежать зацикливания и делает его намного чище:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
url = 'https://gist.githubusercontent.com/adamFlyn/7c96d7f7c05f16abcc39befcd74f5ca8/raw/8997332cd3cdec7610aeaa0300a1b85f9daafccb/prod_sales.csv'
df = pd.read_csv(url, parse_dates=['Unnamed: 0'])
df = df.rename({'Unnamed: 0' : 'date'}, axis=1)
df['year'] = df['date'].dt.year
df['week'] = df['date'].dt.week
df = df.melt(id_vars=['date','week','year'])
df = df.groupby(['year', 'week'], as_index=False)['value'].sum()
fig, ax = plt.subplots(squeeze=True,figsize=(16,10))
sns.lineplot(data=df, x='week', y='value', hue='year',linewidth=3)
plt.show()
Это первая и последние 5 строк df
перед построением графика:
year week value
0 2018 1 2268.0
1 2019 1 11196.0
2 2019 2 0.0
3 2019 3 0.0
4 2019 4 0.0
.. ... ... ...
100 2020 49 17111.0
101 2020 50 18203.0
102 2020 51 12787.0
103 2020 52 26245.0
104 2020 53 11772.0
Согласно вашему комментарию, вы ищете relplot
и проходите kind='line'
. Существуют всевозможные параметры форматирования, которые вы можете передать, relplot
или вы можете искать, как выполнить цикл, axes
чтобы внести дополнительные изменения:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
url = 'https://gist.githubusercontent.com/adamFlyn/7c96d7f7c05f16abcc39befcd74f5ca8/raw/8997332cd3cdec7610aeaa0300a1b85f9daafccb/prod_sales.csv'
df = pd.read_csv(url, parse_dates=['Unnamed: 0'])
df = df.rename({'Unnamed: 0' : 'date'}, axis=1)
df['year'] = df['date'].dt.year
df['week'] = df['date'].dt.isocalendar().week
df = df.melt(id_vars=['date','week','year'], var_name='country')
df = df.loc[df['value'] < 3000].groupby(['country', 'year', 'week'], as_index=False)['value'].sum()
sns.relplot(data=df, x='week', y='value', hue='year', row='country', kind='line', facet_kws={'sharey': False, 'sharex': True})
df
Комментарии:
1. можем ли мы повторять столбцы, чтобы мы могли отображать графики выше для каждой страны, например, создавать графики выше для
JAPAN
,MEXICO
, …? Кроме того, как мы можем удалить разметку в этих данных временных рядов?2. @Adam смотрите мой ответ. Я также отфильтровал выбросы с
df.loc[df['value'] < 3000]
помощью . Это должно дать вам представление, если вы могли бы любезно принять решение и открыть другой вопрос, ссылающийся на этот, если у вас есть еще вопросы.3. спасибо, я не совсем уверен в использовании
replot
. Можем ли мы сделать это, используяmatplotlib
вместо этого? график для каждой страны не имеет общей оси x, поэтому был бы отдельный график, и я мог бы настроить линию и цвет и так далее. Я думаю, мы могли бы сделать это сmatplotlib
помощью . Не могли бы вы подсказать мне, как это сделать? Спасибо!4. @Adam вы можете использовать
sns.relplot(data=df, x='week', y='value', hue='year', row='country', kind='line', facet_kws={'sharey': False, 'sharex': True})
и, я бы не стал использоватьmatplotlib
. Для одного графика я бы использовалmatplotlib
, но для нескольких графиков я бы использовалseaborn
. Извините, мне нужно бежать.5. @Adam рад, что это сработало. Вы можете использовать
seaborn
иmatplotlib
вместе.seaborn
работает поверхmatplotlib
. Итеративно запрашивать обновленные версии ответа крайне не рекомендуется, особенно дляseaborn
/matplotlib
. Эти вопросы о графике могут быть чрезвычайно подробными. Я бы посоветовал вам создать новый вопрос и, пожалуйста, примите это как ответ. Кто-то еще из сообщества, вероятно, сможет ответить на этот вопрос, поскольку я, возможно, не буду в StackOverflow до следующей недели. Спасибо!