#python #pandas #matplotlib #seaborn
#python #pandas #matplotlib #seaborn
Вопрос:
Меня интересует, как пандемия COVID влияет на мясоперерабатывающие предприятия по всей стране. Я извлек данные NYT по COVID на уровне округа и статистические данные из агентства по продовольствию. Здесь я исследую, как растут случаи заболевания COVID в округах, где расположены крупные предприятия пищевой промышленности, потому что большее количество больных сотрудников на заводах может оказать негативное влияние на бизнес. В моей первой попытке я вычислил графики временных рядов со скользящим средним, на которых новые случаи COVID по сравнению с 7 днями в среднем по дате.
Но, я думаю, было бы более эффективно, я мог бы заменить график, который представляет num-emp
и new-cases
по округам в цикле for. Для достижения этого, я думаю, было бы лучше сгруппировать их по уровню компании и развернуть их на несколько графиков, чтобы линии не перекрывались и не становились трудноразличимыми. Я не уверен, как добиться этого с помощью моей текущей попытки. Кто-нибудь может предложить возможные способы сделать это в matplotlib? Есть идея?
моя текущая попытка:
Вот воспроизводимые данные в этом gist, которые я использовал в своем эксперименте:
импортируйте pandas как pd, импортируйте matplotlib.pyplot как plt, импортируйте matplotlib.dates как mdates, импортируйте seaborn как sns из datetime, импортируйте timedelta, datetime
df = pd.read_csv("https://gist.githubusercontent.com/jerry-shad/7eb2dd4ac75034fcb50ff5549f2e5e21/raw/477c07446a8715f043c9b1ba703a03b2f913bdbf/covid_tsdf.csv")
df.drop(['Unnamed: 0', 'fips', 'non-fed-slaughter', 'fed-slaughter', 'total-slaughter', 'mcd-asl'], axis=1, inplace=True)
for ct in df['county_state'].unique():
dd = df[df['county_state'] == ct].groupby(['county_state', 'date', 'est'])[['cases','new_cases']].sum().unstack().reset_index()
dd.columns= ['county_state','date', 'cases', 'new_cases']
dd['date'] = pd.to_datetime(dd['date'])
dd['rol7'] = dd[['date','new_cases']].rolling(7).mean()
fig = plt.figure(figsize=(8,6),dpi=144)
ax = fig.add_subplot(111)
colors = sns.color_palette()
ax2 = ax.twinx()
ax = sns.lineplot('date', 'rol7', data=dd, color=colors[1], ax=ax)
ax2 = sns.lineplot('date', 'cases', data=dd, color=colors[0], ax=ax2)
ax.set_xlim(dd.date.min(), dd.date.max())
fig.legend(['rolling7','cases'],loc="upper left", bbox_to_anchor=(0.01, 0.95), bbox_transform=ax.transAxes)
ax.grid(axis='both', lw=0.5)
locator = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(locator)
fig.autofmt_xdate(rotation=45)
ax.set(title=f'US covid tracking in meat processing plants by county - Linear scale')
plt.show()
вот мой текущий результат:
но этот результат не совсем важен для понимания того, как COVID влияет на компанию по переработке продуктов питания из-за зараженных сотрудников. Чтобы сделать это более визуально доступным для понимания, я думаю, мы можем заменить два графика на num-emp
и недавно зараженный случай new_cases
и нарисовать округа, которые нам нужны в процессе цикла. На этом этапе было бы лучше сгруппировать их по характеристикам компании и т.д. И разложить их на несколько графиков, чтобы линии не перекрывались и их было трудно увидеть. Я хочу создать EDA, который предоставляет такого рода информацию визуально. Кто-нибудь может предложить возможные способы сделать это с matplotlib
? Есть мысли? Спасибо!
Ответ №1:
- Было несколько проблем, я сделал встроенные обозначения
- Основная проблема заключалась в
.groupby
- Данные уже выбраны,
'country_state'
поэтому вgroupby
этом нет необходимости - Только
reset_index(level=1)
сохраняйте дату в индексе для переноса .unstack()
создавал многоуровневые имена столбцов.
- Данные уже выбраны,
- Набор
ci=None
для построения графика. - Это не имеет смысла использовать
'num-emp'
в качестве метрики. Он постоянен во времени.- Если вы хотите увидеть график, поменяйте
'cases'
местами в цикле, для'num-emp'
.
- Если вы хотите увидеть график, поменяйте
- Я думаю, что лучший способ увидеть влияние COVID на данную компанию — это найти набор данных с доходом.
- Поскольку предприятия по переработке пищевых продуктов считаются критически важной инфраструктурой, вероятно, не произойдет значительных изменений в их численности персонала, и любой, кто болен, вероятно, находится в отпуске по болезни или увольнении.
import pandas as pd
import matplotlib.pyplot as plt
url = 'https://gist.githubusercontent.com/jerry-shad/7eb2dd4ac75034fcb50ff5549f2e5e21/raw/477c07446a8715f043c9b1ba703a03b2f913bdbf/covid_tsdf.csv'
# load the data and parse the dates
df = pd.read_csv(url, parse_dates=['date'])
# drop unneeded columns
df.drop(['Unnamed: 0', 'fips', 'non-fed-slaughter', 'fed-slaughter', 'total-slaughter', 'mcd-asl'], axis=1, inplace=True)
for ct in df['county_state'].unique():
# groupby has been updated: no need for county becasue they're all the same, given the loop; keep date in the index for rolling
dd = df[df['county_state'] == ct].groupby(['date', 'est', 'packer'])[['cases','new_cases']].sum().reset_index(level=[1, 2])
dd['rol7'] = dd[['new_cases']].rolling(7).mean()
colors = sns.color_palette()
fig, ax = plt.subplots(figsize=(8, 6), dpi=144)
ax2 = ax.twinx()
sns.lineplot(dd.index, 'rol7', ci=None, data=dd, color=colors[1], ax=ax) # date is in the index
sns.lineplot(dd.index, 'cases', ci=None, data=dd, color=colors[0], ax=ax2) # date is in the index
ax.set_xlim(dd.index.min(), dd.index.max()) # date is in the index
fig.legend(['rolling7','cases'], loc="upper left", bbox_to_anchor=(0.01, 0.95), bbox_transform=ax.transAxes)
# set y labels
ax.set_ylabel('7-day Rolling Mean')
ax2.set_ylabel('Current Number of Cases')
ax.grid(axis='both', lw=0.5)
locator = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(locator)
fig.autofmt_xdate(rotation=45)
# create a dict for packer and est
vals = dict(dd[['packer', 'est']].reset_index(drop=True).drop_duplicates().values.tolist())
# create a custom string from vals, for the title
insert = ', '.join([f'{k}: {v}' for k, v in vals.items()])
# ax.set(title=f'US covid tracking in meat processing plants for {ct} nPacker: {", ".join(dd.packer.unique())}nEstablishments: {", ".join(dd.est.unique())}')
# alternate title based on comment request
ax.set(title=f'US covid tracking in meat processing plants for {ct} n{insert}')
plt.savefig(f'images/{ct}.png') # save files by ct name to images directory
plt.show()
plt.close()