Spaces:
Runtime error
Runtime error
import json | |
import pandas as pd | |
import plotly.express as px | |
import plotly.graph_objects as go | |
import streamlit as st | |
import numpy as np | |
from datetime import datetime, timedelta | |
from dateutil.relativedelta import relativedelta | |
from pathlib import Path | |
from PIL import Image | |
import app_scripts.s_02_map as smap | |
import app_scripts.s_01_get_data as get_data | |
def drop_day(date: datetime) -> datetime: | |
return datetime(year=date.year, month=date.month, day=1) | |
# penciltip_im = Image.open(r'C:\Users\EPostolit\Programs\HHru\site (streamlit)\final\data\pictures\penciltip.png') | |
penciltip_im = Image.open(Path() / 'data' / 'pictures' / 'penciltip.png') | |
st.set_page_config( | |
page_title='Безработица, hh-ru', | |
page_icon= penciltip_im, | |
layout='wide' | |
) | |
def pm_num(num): | |
if num > 0: | |
return '+' + "%.1f" % num | |
else: | |
return "%.1f" % num | |
VTB_COLORS = [(0.228845, 0.413827, 0.561235), | |
(0.301203, 0.652293, 0.707487), | |
(0.834794, 0.267854, 0.225356), | |
(0.967809, 0.848523, 0.288235), | |
(0.0480806, 0.0308608, 0.0346505), | |
(0.744229, 0.744089, 0.740097), | |
(0.99389, 0.970688, 0.797143), | |
(0.721352, 0.321019, 0.293811) | |
] | |
# print(dir(scr)) | |
# DATA_FOLDER = Path(r'data') | |
# MAP_DATA = DATA_FOLDER / 'map_data' | |
st.title('Альтернативные данные по безработице.\nНа основе открытых данных из Headhunter') | |
st.write('[Безработица в мае по данным Росстата обновляет исторический минимум 2-ой месяц подряд](https://t.me/xtxixty/1951), достигнув отметки в 3.9%.\ | |
Все это происходит на фоне массового ухода иностранных компаний с российского рынка и [падения производства](https://t.me/xtxixty/1951).\ | |
О том, что разброс оценки безработицы из-за не очень большой выборки в ~77 тыс. человек | ~0.1% рабочей силы может быть большим писали [ранее](https://t.me/xtxixty/1792). ') | |
# st.markdown('# Headhunter в России') | |
counties = smap.get_counties() | |
stats_df = smap.prepare_stats_df() | |
# stats_df.to_excel('delte0.xlsx', index=False) | |
# stats_df[stats_df.columns[0:4]] | |
min_date = min(stats_df['date']) | |
max_date = max(stats_df['date']) | |
# min_date | |
# max_date | |
# prof_name = st.sidebar.selectbox('Проф. область', | |
# np.unique([str(i) for i in stats_df.prof_name])) | |
prof_name = 'все' | |
date = st.slider('Дата', min_value=min_date.to_pydatetime(), max_value=max_date.to_pydatetime(), | |
value=max_date.to_pydatetime(), step=timedelta(days=30)) | |
date = drop_day(date) | |
prof_df = stats_df[stats_df['prof_name'] == prof_name] | |
show_df = prof_df[(stats_df['date'] == date)] | |
# show_df.shape | |
show_df.to_excel('delte1.xlsx', index=False) | |
fig = go.Figure(go.Choroplethmapbox(geojson=counties, | |
locations=show_df['map_region_id'], | |
z=show_df['hh_index'], | |
text=show_df['name'], | |
# colorscale=[[0, f'rgb{VTB_COLORS[1]}'], | |
# [qq[1], f'rgb{VTB_COLORS[3]}'], | |
# [qq[2], f'rgb{VTB_COLORS[2]}'], | |
# [1, f'rgb{VTB_COLORS[2]}']], | |
colorscale=[[0, f'rgb{VTB_COLORS[1]}'], | |
[0.4, f'rgb{VTB_COLORS[3]}'], | |
[0.8, f'rgb{VTB_COLORS[2]}'], | |
[1.0, f'rgb{VTB_COLORS[2]}']], | |
colorbar_thickness=20, | |
customdata=np.stack([show_df['hh_index'], show_df['vacancies'].apply(pm_num), show_df['resumes'].apply(pm_num), show_df['hh_index_change'].apply(pm_num)], axis=-1), | |
hovertemplate='<b>%{text}</b>'+ '<br>' + | |
'hh индекс: %{z}' + '<br>' + | |
'изменение индекса: %{customdata[3]}% м/м' + '<br>' + | |
'активных вакансий: %{customdata[1]}% м/м' + '<br>' + | |
'активных резюме: %{customdata[2]}% м/м'# + '<br>' #+ | |
# 'Всего случаев: %{customdata[2]}' + '<br>' + | |
# 'Выздоровело: %{customdata[3]}' + | |
'<extra></extra>', | |
hoverinfo='text, z')) | |
fig.update_layout(mapbox_style="carto-positron", | |
mapbox_zoom=1, mapbox_center = {"lat": 66, "lon": 94}) | |
fig.update_traces(marker_line_width=0) | |
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0}) | |
st.plotly_chart(fig, use_container_width=True) | |
st.write('''На карте изображено распределение [hh-index-a](https://ru.wikipedia.org/wiki/HeadHunter#hh.%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81) в РФ, равного отношению числа активных резюме к количеству открытых вакансий на сервисах [hh.ru](http://hh.ru), т.е. прокси для безработицы.''') | |
# st.dataframe(stats_df[stats_df['location'] == 'total']) | |
# st.sidebar.write('hello') | |
# st.write('this is dataframe with data') | |
# st.dataframe(show_df) | |
# quantile graph by region | |
# TODO implement the ability to choose region | |
ros_df = get_data.load_rs_unemploment() | |
quantiles = (0.05, 0.5, 0.95) | |
quantile_data = prof_df[['date', 'hh_index', 'name']].groupby('date').apply(lambda df: | |
np.quantile(df['hh_index'], quantiles)) | |
lower = pd.Series(index=quantile_data.index, data=[val[0] for val in quantile_data.values]) | |
median = pd.Series(index=quantile_data.index, data=[val[1] for val in quantile_data.values]) | |
upper = pd.Series(index=quantile_data.index, data=[val[2] for val in quantile_data.values]) | |
hh_index_df = stats_df[stats_df['location'] == 'total'] | |
hh_index_df.to_excel('delte.xlsx', index=False) | |
blue_color_str = f'rgb{VTB_COLORS[0]}' | |
lightblue_color_str = f'rgb{VTB_COLORS[1]}' | |
rosstat_color_str = f'rgb{VTB_COLORS[2]}' | |
layout = go.Layout( | |
paper_bgcolor=f'rgb{VTB_COLORS[6]}' | |
,plot_bgcolor=f'rgb{VTB_COLORS[6]}' | |
,title='Распределение hh-индекса по регионам и данные росстата', title_x=0.5 | |
,margin=dict(l=2,r=2) | |
# ,width=st.get_container_width | |
,height=500 | |
) | |
fig = go.Figure(layout=layout) | |
fig.update_layout( | |
legend=dict( | |
yanchor="top", | |
y=0.99, | |
xanchor="center", | |
x=0.51 | |
) | |
) | |
fig.add_trace(go.Scatter(x=lower.index, y=lower.values, line_color=blue_color_str, | |
name=f'({quantiles[0]}, {quantiles[2]}) квантили распр. по регионам')) | |
# fig.add_trace(go.Scatter(x=median.index, y=median.values, fill='tonexty', line_color='blue', | |
# name=f'{quantiles[1]}-ый квантиль')) | |
fig.add_trace(go.Scatter(x=upper.index, y=upper.values, fill='tonexty', line_color=blue_color_str | |
,showlegend=False)) | |
fig.add_trace(go.Scatter(x=hh_index_df['date'], y=hh_index_df['hh_index'], line_color=lightblue_color_str, | |
name='hh индекс по всей России')) | |
fig.add_trace(go.Scatter(x=ros_df['date'], y=ros_df['unemp'], line_color=rosstat_color_str, | |
name='уровень безработицы (%), Росстат')) | |
st.plotly_chart(fig, use_container_width=True) | |
fig.write_image('pic.svg') | |
print('wrote') | |
st.write('После фераля hh-индекс резко вырос (на 30% м/м в марте и потом еще на на 16% м/м в апреле), но уровень беззработицы по данным Росстата продолжил снижение.') | |
st.write('Регионы с наибольшей безработицей по версии hh.ru') | |
# sort regions by force | |
show_df.sort_values(by=['hh_index'], inplace=True, ascending=False) | |
def get_headtail(df: pd.DataFrame, num: int = 5) -> pd.DataFrame: | |
cols = df.columns | |
dots_df = pd.DataFrame([['...'] * len(cols)], columns=cols, index=['...']) | |
ans_df = pd.concat([df.head(num), dots_df, df.tail(num)], axis=0) | |
for col in ans_df.columns: | |
ans_df[col] = ans_df[col].astype(str) | |
ans_df.index = ans_df.index.astype(str) | |
return ans_df | |
# cur_show = get_headtail(show_df[['date', 'name', 'hh_index', 'hh_index_change']].drop_duplicates().dropna(), 4) | |
cur_show = show_df[['date', 'name', 'hh_index', 'hh_index_change']].drop_duplicates().dropna() | |
cur_show.columns=['дата', 'регион', 'hh-индекс', 'изменение hh-индекса, % м/м'] | |
cur_show['hh-индекс'] = cur_show['hh-индекс'].apply(lambda x: '%.1f' % x) | |
for col in ['изменение hh-индекса, % м/м']: | |
cur_show[col] = cur_show[col].apply(lambda x: '%.0f' % x) | |
cur_show['дата'] = cur_show['дата'].apply(lambda x: x.strftime('%Y-%m-%d')) | |
st.dataframe(cur_show, width=8000) | |
st.write('За последние 3 месяца hh-индекс вырос сильнее всего в Московской, Нижегородской, Тверской, Самарской, Калмыцкой, Пермской и Рязанской областях.') | |
st.write('В то же время за эти же 3 месяца он сократился в Респ. Тыва, Алтайской респ, Магаданской обл., Чукотке, Еврейском АО, Ингушетии и на Камчатке.') | |
temp=""" | |
st.dataframe(show_df.dropna()) | |
# fig.show() | |
# sl = st.slider('Дата', min_value=min_date, max_value=max_date, value=date) | |
# unemployment delta by region | |
# percentage increased/decreased | |
(prev_date, cur_date) = st.slider('2-range', min_value=min_date.to_pydatetime(), | |
max_value=max_date.to_pydatetime(), | |
value=(max_date.to_pydatetime() - timedelta(days=30), | |
max_date.to_pydatetime()), step=timedelta(days=30), | |
format="M'YY") | |
prev_date, cur_date = map(drop_day, [prev_date, cur_date]) | |
color_good = tuple((np.array(VTB_COLORS[1]) * 255).astype(int)) | |
color_bad = tuple((np.array(VTB_COLORS[3]) * 255).astype(int)) | |
show_df = prof_df[['name', 'hh_index', 'date']][(prof_df['date'] == prev_date) | (prof_df['date'] == cur_date)] | |
show_df.to_excel('temp.xlsx', index=False) | |
st.dataframe(show_df) | |
st.write(f'Values: {prev_date, cur_date}') | |
""" | |
temp=""" | |
st.write('stats df') | |
stats_df['prof_id'] = stats_df['prof_id'].astype(str) | |
st.dataframe(stats_df) | |
""" | |
temp=""" | |
# salary distribution by specialization and prof area | |
# top skills | |
""" | |