Advertisement
Guest User

zen_dash

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