Advertisement
Guest User

Untitled

a guest
Mar 31st, 2020
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.42 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.  
  9. import plotly.graph_objs as go
  10.  
  11. from datetime import datetime
  12.  
  13. import pandas as pd
  14.  
  15. # задаём данные для отрисовки
  16. from sqlalchemy import create_engine
  17.  
  18. # подключение к базе данных
  19. db_config = {'user': 'my_user',
  20. 'pwd': 'my_user_password',
  21. 'host': 'localhost',
  22. 'port': 5432,
  23. 'db': 'zen'}
  24.  
  25. connection_string = 'postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
  26. db_config['pwd'],
  27. db_config['host'],
  28. db_config['port'],
  29. db_config['db'])
  30. engine = create_engine(connection_string)
  31.  
  32. # получаем сырые данные
  33. query = '''
  34. SELECT * 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. query = '''
  40. SELECT * FROM dash_engagement
  41. '''
  42. dash_engagement = pd.io.sql.read_sql(query, con = engine)
  43. dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt'])
  44.  
  45.  
  46. note = '''
  47. Этот дашборд показывает историю событий Яндекс.Дзен по минутам,
  48. разбивку событий по темам источников и воронку уникальных показов.
  49. Используйте выбор интервала даты событий, темы карточек и возрастной
  50. группы для управления дашбордом.
  51. '''
  52.  
  53. # задаём лейаут
  54. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  55. app = dash.Dash(__name__, external_stylesheets=external_stylesheets, compress=False)
  56. app.layout = html.Div(children=[
  57.  
  58. # формируем html
  59. html.H1(children = 'Яндекс.Дзен - Взаимодействие пользователей с карточками'),
  60.  
  61. html.Br(),
  62.  
  63. html.Div([
  64. html.Div([
  65.  
  66. # график истории событий по темам карточек
  67. html.Label('История событий по темам карточек:'),
  68.  
  69.  
  70. dcc.Graph(
  71. id = 'history-absolute-visits'
  72. ),
  73. ], className = 'six columns'),
  74.  
  75. html.Div([
  76. # график событий по темам источников
  77. html.Label('Разбивка всех событий по темам источников:'),
  78. dcc.Graph(
  79. id = 'pie-visits'
  80. ),
  81. ], className = 'six columns'),
  82.  
  83. ], className = 'row'),
  84.  
  85. html.Div([
  86. html.Div([
  87.  
  88. # воронка уникадльных показов
  89. html.Label('Усредненная воронка уникальных показов:'),
  90.  
  91. dcc.Graph(
  92. id = 'engagement-graph'
  93. ),
  94. ], className = 'six columns'),
  95.  
  96. ], className = 'row'),
  97.  
  98.  
  99. # пояснения
  100. html.Label(note),
  101.  
  102. html.Br(),
  103.  
  104. html.Div([
  105.  
  106. html.Div([
  107. # выбор темы карточек
  108. html.Label('Темы карточек:'),
  109. dcc.Dropdown(
  110. options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
  111. value = dash_visits['item_topic'].unique().tolist(),
  112. multi = True,
  113. id = 'item-topic-dropdown'
  114. ),
  115. ], className = 'eight columns'),
  116.  
  117. html.Div([
  118. # выбор возрастной группы
  119. html.Label('Возрастная группа:'),
  120. dcc.Dropdown(
  121. options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
  122. value = dash_visits['age_segment'].unique().tolist(),
  123. multi = True,
  124. id = 'age-dropdown'
  125. ),
  126. ], className = 'two columns'),
  127.  
  128. html.Div([
  129. # выбор временного периода
  130. html.Label('Года выпуска:'),
  131. dcc.DatePickerRange(
  132. start_date = dash_visits['dt'].dt.date.min(),
  133. end_date = dash_visits['dt'].dt.date.max(),
  134. display_format = 'YYYY-MM-DD',
  135. id = 'dt_selector',
  136. ),
  137. ], className = 'two columns'),
  138.  
  139.  
  140. ], className = 'row'),
  141.  
  142. ])
  143.  
  144. #описываем логику дашборда
  145. @app.callback(
  146. [Output('history-absolute-visits', 'figure'),
  147. Output('pie-visits', 'figure'),
  148. Output('engagement-graph', 'figure'),
  149. ],
  150. [Input('dt_selector', 'start_date'),
  151. Input('dt_selector', 'end_date'),
  152. Input('age-dropdown', 'value'),
  153. Input('item-topic-dropdown', 'value'),
  154. ])
  155. def update_figures(start_date, end_date, selected_age, selected_topic):
  156.  
  157. #применяем фильтрацию
  158. filtered_visits = dash_visits.query('dt >= @start_date and dt <= @end_date')
  159. filtered_visits = filtered.query('age_segment in @selected_age')
  160. filtered_visits = filtered.query('item_topic in @selected_topic')
  161.  
  162. filtered_engagement = dash_engagement.query('dt >= @start_date and dt <= @end_date')
  163. filtered_engagement = filtered.query('age_segment in @selected_age')
  164. filtered_engagement = filtered.query('item_topic in @selected_topic')
  165.  
  166. visits_by_item = (filtered_visits.groupby(['dt', 'item_topic'])
  167. .agg({'visits': 'sum'})
  168. .reset_index()
  169. )
  170.  
  171. visits_by_source = (filtered_visits.groupby(['source_topic'])
  172. .agg({'visits': 'sum'})
  173. .reset_index()
  174. )
  175. engagement = (filtered_engagement.groupby(['event'])
  176. .agg({'unique_users':'mean'})
  177. .reset_index()
  178. )
  179. engagement['relative_n'] = engagement['unique_users'] / engagement[engagement['event'] == '']['unique_users']
  180.  
  181.  
  182. # график
  183. data_by_item = []
  184. for item_topic in dash_visits['item_topic'].unique():
  185. data_by_item += [go.Scatter(x = visits_by_item.query('item_topic == @item_topic')['dt'],
  186. y = visits_by_item.query('item_topic == @item_topic')['visits'],
  187. mode = 'lines',
  188. stackgroup = 'one',
  189. name = item_topic)]
  190.  
  191.  
  192. # график
  193. data_by_source = [go.Pie(labels = visits_by_source['source_topic'],
  194. values = visits_by_source['visits'],
  195. name = 'source_topic')]
  196.  
  197. # столбчатая диаграмма уникальных показов
  198. data_engagement = [go.Bar(x = engagement.query('item_topic == @item_topic')['event'],
  199. y = engagement.query('item_topic == @item_topic')['unique_users'],
  200. barmode='relative',
  201. name = 'event')]
  202.  
  203. #формируем результат для отображения
  204. return (
  205. {
  206. 'data': data_by_item,
  207. 'layout': go.Layout(xaxis = {'title': 'Год'},
  208. yaxis = {'title': 'Количество событий'})
  209. },
  210. {
  211. 'data': data_by_source,
  212. 'layout': go.Layout()
  213. },
  214. {
  215. 'data': data_engagement,
  216. 'layout': go.Layout(xaxis = {'title': 'Тип события'},
  217. yaxis = {'title': 'Среднее количество событий в % от показов'})
  218. },
  219. )
  220.  
  221. if __name__ == '__main__':
  222. app.run_server(host='0.0.0.0', port=3000)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement