SHARE
TWEET

Untitled

a guest Jan 24th, 2020 83 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. # импорт необходимых библиотек
  5. import dash
  6. import dash_core_components as dcc
  7. import dash_html_components as html
  8. from dash.dependencies import Input, Output
  9.  
  10. import plotly.graph_objs as go
  11.  
  12. from datetime import datetime
  13.  
  14. import pandas as pd
  15.  
  16. # задание данных для отрисовки
  17. from sqlalchemy import create_engine
  18.  
  19. # подключение к базе данных zen
  20. db_config = {'user': 'my_user',
  21.              'pwd': 'my_user_password',
  22.              'host': 'localhost',
  23.              'port': 5432,
  24.              'db': 'zen'}
  25. engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
  26.                                                             db_config['pwd'],
  27.                                                             db_config['host'],
  28.                                                             db_config['port'],
  29.                                                             db_config['db']))
  30.  
  31. # получение сырых данных
  32. # датафрейм событий (dash_visits)
  33. query = ''' SELECT *
  34.             FROM dash_visits;
  35.         '''
  36. dash_visits = pd.io.sql.read_sql(query, con = engine)
  37. dash_visits['dt'] = pd.to_datetime(dash_visits['dt'])
  38.  
  39. # датафрейм воронки (dash_engagement)
  40. query = ''' SELECT *
  41.             FROM dash_engagement;
  42.         '''
  43. dash_engagement = pd.io.sql.read_sql(query, con = engine)
  44. dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt'])
  45.  
  46. # формирование текста описания дашборда
  47. note = '''
  48.           Этот дашборд показывает пользовательское взаимодействие с карточками статей в Яндекс.Дзене.
  49.           Используйте выбор интервала даты, тем карточек и возрастной категории пользователей для управления дашбордом.
  50.        '''
  51.  
  52. # задание лейаута
  53. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  54. app = dash.Dash(__name__, external_stylesheets=external_stylesheets, compress=False)
  55. app.layout = html.Div(children=[  
  56.    
  57.     # формирование html
  58.     html.H1(children = 'Дашборд для Яндекс.Дзен'),
  59.  
  60.     html.Br(),  
  61.  
  62.     # пояснения
  63.     html.Label(note),
  64.  
  65.     html.Br(),  
  66.  
  67.     # Input
  68.     html.Div([  
  69.  
  70.         html.Div([
  71.  
  72.             html.Div([
  73.             # выбор даты
  74.             html.Label('Дата:'),
  75.             dcc.DatePickerRange(
  76.                 start_date = dash_visits['dt'].min(),
  77.                 end_date = dash_visits['dt'].max(),
  78.                 display_format = 'YYYY-MM-DD',
  79.                 id = 'dt_selector',      
  80.                 ),
  81.             ]),
  82.  
  83.             html.Div([        
  84.             # выбор возрастных категорий
  85.             html.Label('Возрастные категории:'),
  86.             dcc.Dropdown(
  87.                 options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
  88.                 value = dash_visits['age_segment'].unique().tolist(),
  89.                 multi = True,
  90.                 id = 'age-dropdown'
  91.                 ),    
  92.             ]),
  93.  
  94.         ], className = 'six columns'),
  95.  
  96.         html.Div([    
  97.             # выбор темы карточки
  98.             html.Label('Темы карточек:'),
  99.             dcc.Dropdown(
  100.                 options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
  101.                 value = dash_visits['item_topic'].unique().tolist(),
  102.                 multi = True,
  103.                 id = 'item-topic-dropdown'
  104.             ),                
  105.         ], className = 'six columns'),
  106.  
  107.        
  108.     ], className = 'row'),
  109.  
  110.     html.Br(),      
  111.  
  112.     # Output
  113.     html.Div([
  114.         html.Div([
  115.             # график истории событий по темам карточек
  116.             html.Label('События по темам карточек:'),    
  117.             dcc.Graph(
  118.                 style = {'height': '50vw'},
  119.                 id = 'history_absolute_visits'
  120.             ),    
  121.         ], className = 'six columns'),
  122.     ]),
  123.  
  124.     html.Div([
  125.  
  126.         html.Div([
  127.             # график разбивки событий по темам источников
  128.             html.Label('События по темам источников:'),    
  129.             dcc.Graph(
  130.                 style = {'height': '25vw'},
  131.                 id = 'pie_visits'
  132.             ),  
  133.         ], className = 'six columns'),            
  134.  
  135.         html.Div([
  136.             # график средней глубины взаимодействия с карточками статей
  137.             html.Label('Средняя глубина взаимодействия с карточками статей:'),    
  138.             dcc.Graph(
  139.                 style = {'height': '25vw'},
  140.                 id = 'engagement_graph'
  141.             ),  
  142.         ], className = 'six columns'),
  143.        
  144.     ], className = 'row'),  
  145.    
  146.  
  147.     html.Br()    
  148.  
  149. ])
  150.  
  151. # описание логики дашборда
  152. @app.callback(
  153.     [Output('history_absolute_visits', 'figure'),
  154.      Output('pie_visits', 'figure'),
  155.      Output('engagement_graph', 'figure'),
  156.     ],
  157.     [Input('dt_selector', 'start_date'),
  158.      Input('dt_selector', 'end_date'),
  159.      Input('item-topic-dropdown', 'value'),
  160.      Input('age-dropdown', 'value'),
  161.     ])
  162. def update_figures(start_date, end_date, selected_item_topics, selected_ages):
  163.  
  164.     # применение фильтрации
  165.     filtered_visits = dash_visits.query('item_topic.isin(@selected_item_topics) and \
  166.                                         dt >= @start_date and dt <= @end_date and \
  167.                                         age_segment.isin(@selected_ages)')
  168.  
  169.     filtered = dash_engagement.query('item_topic.isin(@selected_item_topics) and \
  170.                                         dt >= @start_date and dt <= @end_date and \
  171.                                         age_segment.isin(@selected_ages)')
  172.  
  173.     # создание вспомогательных таблиц
  174.     visits_by_item_topic = (filtered_visits.groupby(['dt', 'item_topic'])
  175.                             .agg({'visits': 'sum'})
  176.                             .reset_index()
  177.                       )
  178.  
  179.  
  180.     visits_by_source_topic = (filtered_visits.groupby(['source_topic'])
  181.                             .agg({'visits': 'sum'})
  182.                             .reset_index()
  183.                       )
  184.  
  185.  
  186.     engagement_by_event = (filtered.groupby(['event'])
  187.                             .agg({'unique_users': 'mean'})
  188.                             .reset_index()
  189.                             .rename(columns = {'unique_users': 'avg_unique_users'})
  190.                             .sort_values(by = 'avg_unique_users', ascending = False)  
  191.                       )
  192.  
  193.     # график истории событий по темам карточек
  194.     history_absolute_visits = []
  195.     for item_topic in visits_by_item_topic['item_topic'].unique():
  196.         history_absolute_visits += [go.Scatter(x = visits_by_item_topic.query('item_topic == @item_topic')['dt'],
  197.                                    y = visits_by_item_topic.query('item_topic == @item_topic')['visits'],
  198.                                    mode = 'lines',
  199.                                    stackgroup = 'one',
  200.                                    name = item_topic)]
  201.  
  202.     # график разбивки событий по темам источников €
  203.     pie_visits = []
  204.     pie_visits = [go.Pie(labels = visits_by_source_topic['source_topic'],
  205.                              values = visits_by_source_topic['visits'])]
  206.  
  207.     # график средней глубины взаимодействия с карточками статей
  208.     engagement_graph = []
  209.     engagement_graph = [go.Bar(x = engagement_by_event['event'],
  210.                             y = engagement_by_event['avg_unique_users'])]
  211.  
  212.     # формирование результата для отображения
  213.     return (
  214.             {
  215.                 'data': history_absolute_visits,
  216.                 'layout': go.Layout(xaxis = {'title': 'Время'},
  217.                                     yaxis = {'title': 'Количество событий'})
  218.              },          
  219.             {
  220.                 'data': pie_visits,
  221.                 'layout': go.Layout()
  222.              },
  223.             {
  224.                 'data': engagement_graph,
  225.                 'layout': go.Layout(xaxis = {'title': 'Способ взаимодействия с системой'},
  226.                                     yaxis = {'title': 'Количество взаимодействий'},
  227.                                     barmode = 'stack',
  228.                                     )
  229.              },            
  230.             )  
  231.  
  232. # основная часть исполняемого кода
  233. if __name__ == '__main__':
  234.     app.run_server(debug = True, host = '0.0.0.0',  port = 3005)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top