как создавать линейные диаграммы путем итерации столбцов pandas в python?

#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 до следующей недели. Спасибо!