Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- #имопрт библиотек
- import dash
- import dash_core_components as dcc
- import dash_html_components as html
- from dash.dependencies import Input, Output
- import plotly.graph_objs as go
- import pandas as pd
- from datetime import datetime
- from sqlalchemy import create_engine
- #задаем параметры подключения к БД
- db_config = {'user': 'my_user',
- 'pwd': 'my_user_password',
- 'host': 'localhost',
- 'port': 5432,
- 'db': 'zen'}
- #подключаемся к БД
- engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
- db_config['pwd'],
- db_config['host'],
- db_config['port'],
- db_config['db']))
- #SQL запросы к БД, результаты сохраняем в таблицы и преобразуем данные к нужным типам
- query = '''
- SELECT * FROM dash_visits
- '''
- dash_visits = pd.io.sql.read_sql(query, con=engine)
- dash_visits['dt'] = pd.to_datetime(dash_visits['dt'])
- dash_visits['age_segment'] = dash_visits['age_segment'].fillna('Нет информации')
- dash_visits['item_topic'] = dash_visits['item_topic'].fillna('Нет информации')
- query = '''
- SELECT * FROM dash_engagement
- '''
- dash_engagement = pd.io.sql.read_sql(query, con=engine)
- dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt'])
- #задаем лэйаут
- external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
- app = dash.Dash(__name__, external_stylesheets = external_stylesheets, compress=False)
- app.layout = html.Div(children=[
- #заголовок
- html.H1(children = 'Дашборд Яндекс.Дзен'),
- #описание
- html.Div(children =
- '''Дашборд характеризует взаимодействие пользователей с карточками Яндекс.Дзен'''),
- html.Br(),
- #первый ряд - фильтры
- html.Div([
- #первая колонка из двух фильтров
- html.Div([
- #фильтр по дате
- html.Div([
- html.Label('Фильтр по дате'),
- dcc.DatePickerRange(
- start_date = dash_visits['dt'].min(),
- end_date = dash_visits['dt'].max(),
- display_format = 'YYYY-MM-DD HH:SS',
- id = 'dt_selector'),
- ], className = 'row container-display'),
- #фильтр по возрастным сегментам
- html.Div([
- html.Label('Фильтр по возрастным сегментам'),
- dcc.Dropdown(
- options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
- value = dash_visits['age_segment'].unique().tolist(),
- multi = True,
- id = 'age_dropdown'),
- ], className = 'row container-display'),
- ], className = 'six columns'
- ),
- #вторая колонка из фильтма по темам
- #фильтр по темам карточек
- html.Div([
- html.Label('Фильтр по темам карточек'),
- dcc.Dropdown(
- options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
- value = dash_visits['item_topic'].unique().tolist(),
- multi = True,
- id = 'item_topic_dropdown'
- ),
- ], className = 'six columns'),
- ], className = 'row',
- ),
- #второй ряд - графики
- html.Br(),
- html.Div([
- #график истории событий, stacked area
- html.Div([
- html.Label('График истории событий по темам карточек'),
- dcc.Graph(
- style = {'height': '50vw'},
- id = 'history_absolute_visits'
- ),
- ], className = 'six columns'),
- #график событий по темам, pie chart
- html.Div([
- html.Label('События по темам источников'),
- dcc.Graph(
- style = {'height':'25vw'},
- id = 'pie_visits'
- ),
- ], className = 'six columns'),
- #график воронки, bar chart
- html.Div([
- html.Label('Глубина взаимодействия'),
- dcc.Graph(
- style = {'height':'25vw'},
- id ='engagement_graph'
- ),
- ], className = 'six columns'),
- ], className = 'row'),
- html.Br()
- ])
- #задаем логику дашборда
- @app.callback(
- [Output('history_absolute_visits','figure'),
- Output('pie_visits','figure'),
- Output('engagement_graph','figure'),
- ],
- [Input('item_topic_dropdown','value'),
- Input('age_dropdown', 'value'),
- Input('dt_selector', 'start_date'),
- Input('dt_selector','end_date'),
- ])
- def update_figures(selected_item_topics, selected_ages, start_date, end_date):
- #фильтрация
- filtered = dash_visits.query('item_topic.isin(@selected_item_topics) and \
- dt >= @start_date and dt <= @end_date \
- and age_segment.isin(@selected_ages)')
- filtered_2 = dash_engagement.query('item_topic.isin(@selected_item_topics) and \
- dt >= @start_date and dt <= @end_date \
- and age_segment.isin(@selected_ages)')
- #сбор таблиц для отрисовки графиков
- #таблица для графика истории событий
- events_by_minute = filtered.groupby(['item_topic','dt']).agg(
- {'visits':'sum'}).sort_values(by='visits', ascending=False).reset_index()
- #таблица для разбивки по темам источников
- events_by_source_topic = filtered.groupby('source_topic').agg(
- {'visits':'sum'}).sort_values(by='visits', ascending=False).reset_index()
- #таблица для воронки
- funnel_data = filtered_2.groupby('event').agg(
- {'unique_users':'mean'}).rename(
- columns = {'unique_users':'avg_unique_users'}).sort_values(
- by = 'avg_unique_users', ascending=False).reset_index()
- avg_shows = filtered_2.query('event == "show"')['unique_users'].mean()
- funnel_data['avg_shows'] = avg_shows
- funnel_data['share_of_shows'] = funnel_data['avg_unique_users']/funnel_data['avg_shows']
- #отрисовка графика истории событий
- events_history = []
- for item_topic in events_by_minute['item_topic'].unique():
- events_history += [go.Scatter(x = events_by_minute.query('item_topic == @item_topic')['dt'],
- y = events_by_minute.query('item_topic == @item_topic')['visits'],
- mode = 'lines',
- stackgroup = 'one',
- name = item_topic)]
- #отрисовка графика разбивки по темам источников
- events_sources = [go.Pie(
- labels = events_by_source_topic['source_topic'],
- values = events_by_source_topic['visits'])]
- #отрисовка графика глубины взаимодействия
- events_funnel = [go.Bar(
- x = funnel_data['event'],
- y = funnel_data['share_of_shows'])]
- #результат для отоброажения
- return ({
- 'data': events_history,
- 'layout': go.Layout(xaxis = {'title': 'Минута'},
- yaxis = {'title': 'Количество событий'})
- },
- {'data': events_sources,
- 'layout': go.Layout()
- },
- {'data': events_funnel,
- 'layout': go.Layout(xaxis = {'title': 'Событие'},
- yaxis = {'title': 'Средняя доля от показов'})
- },
- )
- if __name__ == '__main__':
- app.run_server(debug = True, host='0.0.0.0')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement