Advertisement
Guest User

Untitled

a guest
Feb 21st, 2020
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.17 KB | None | 0 0
  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. import pandas as pd
  13. from datetime import datetime
  14.  
  15. from sqlalchemy import create_engine
  16.  
  17. #задаем параметры подключения к БД
  18. db_config = {'user': 'my_user',
  19. 'pwd': 'my_user_password',
  20. 'host': 'localhost',
  21. 'port': 5432,
  22. 'db': 'zen'}
  23.  
  24. #подключаемся к БД
  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. #SQL запросы к БД, результаты сохраняем в таблицы и преобразуем данные к нужным типам
  32. query = '''
  33. SELECT * FROM dash_visits
  34. '''
  35. dash_visits = pd.io.sql.read_sql(query, con=engine)
  36. dash_visits['dt'] = pd.to_datetime(dash_visits['dt'])
  37. dash_visits['age_segment'] = dash_visits['age_segment'].fillna('Нет информации')
  38. dash_visits['item_topic'] = dash_visits['item_topic'].fillna('Нет информации')
  39.  
  40. query = '''
  41. SELECT * 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. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  48. app = dash.Dash(__name__, external_stylesheets = external_stylesheets, compress=False)
  49. app.layout = html.Div(children=[
  50. #заголовок
  51. html.H1(children = 'Дашборд Яндекс.Дзен'),
  52. #описание
  53. html.Div(children =
  54. '''Дашборд характеризует взаимодействие пользователей с карточками Яндекс.Дзен'''),
  55. html.Br(),
  56.  
  57. #первый ряд - фильтры
  58. html.Div([
  59.  
  60. #первая колонка из двух фильтров
  61. html.Div([
  62.  
  63. #фильтр по дате
  64. html.Div([
  65. html.Label('Фильтр по дате'),
  66. dcc.DatePickerRange(
  67. start_date = dash_visits['dt'].min(),
  68. end_date = dash_visits['dt'].max(),
  69. display_format = 'YYYY-MM-DD HH:SS',
  70. id = 'dt_selector'),
  71. ], className = 'row container-display'),
  72. #фильтр по возрастным сегментам
  73. html.Div([
  74. html.Label('Фильтр по возрастным сегментам'),
  75. dcc.Dropdown(
  76. options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
  77. value = dash_visits['age_segment'].unique().tolist(),
  78. multi = True,
  79. id = 'age_dropdown'),
  80. ], className = 'row container-display'),
  81. ], className = 'six columns'
  82. ),
  83. #вторая колонка из фильтма по темам
  84. #фильтр по темам карточек
  85. html.Div([
  86. html.Label('Фильтр по темам карточек'),
  87. dcc.Dropdown(
  88. options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
  89. value = dash_visits['item_topic'].unique().tolist(),
  90. multi = True,
  91. id = 'item_topic_dropdown'
  92. ),
  93. ], className = 'six columns'),
  94. ], className = 'row',
  95. ),
  96.  
  97. #второй ряд - графики
  98. html.Br(),
  99. html.Div([
  100.  
  101. #график истории событий, stacked area
  102. html.Div([
  103. html.Label('График истории событий по темам карточек'),
  104. dcc.Graph(
  105. style = {'height': '50vw'},
  106. id = 'history_absolute_visits'
  107. ),
  108. ], className = 'six columns'),
  109.  
  110. #график событий по темам, pie chart
  111. html.Div([
  112. html.Label('События по темам источников'),
  113. dcc.Graph(
  114. style = {'height':'25vw'},
  115. id = 'pie_visits'
  116. ),
  117. ], className = 'six columns'),
  118.  
  119. #график воронки, bar chart
  120. html.Div([
  121. html.Label('Глубина взаимодействия'),
  122. dcc.Graph(
  123. style = {'height':'25vw'},
  124. id ='engagement_graph'
  125. ),
  126. ], className = 'six columns'),
  127. ], className = 'row'),
  128. html.Br()
  129. ])
  130.  
  131. #задаем логику дашборда
  132. @app.callback(
  133. [Output('history_absolute_visits','figure'),
  134. Output('pie_visits','figure'),
  135. Output('engagement_graph','figure'),
  136. ],
  137. [Input('item_topic_dropdown','value'),
  138. Input('age_dropdown', 'value'),
  139. Input('dt_selector', 'start_date'),
  140. Input('dt_selector','end_date'),
  141. ])
  142.  
  143. def update_figures(selected_item_topics, selected_ages, start_date, end_date):
  144.  
  145. #фильтрация
  146. filtered = dash_visits.query('item_topic.isin(@selected_item_topics) and \
  147. dt >= @start_date and dt <= @end_date \
  148. and age_segment.isin(@selected_ages)')
  149.  
  150. filtered_2 = dash_engagement.query('item_topic.isin(@selected_item_topics) and \
  151. dt >= @start_date and dt <= @end_date \
  152. and age_segment.isin(@selected_ages)')
  153.  
  154. #сбор таблиц для отрисовки графиков
  155.  
  156. #таблица для графика истории событий
  157. events_by_minute = filtered.groupby(['item_topic','dt']).agg(
  158. {'visits':'sum'}).sort_values(by='visits', ascending=False).reset_index()
  159.  
  160. #таблица для разбивки по темам источников
  161. events_by_source_topic = filtered.groupby('source_topic').agg(
  162. {'visits':'sum'}).sort_values(by='visits', ascending=False).reset_index()
  163.  
  164. #таблица для воронки
  165. funnel_data = filtered_2.groupby('event').agg(
  166. {'unique_users':'mean'}).rename(
  167. columns = {'unique_users':'avg_unique_users'}).sort_values(
  168. by = 'avg_unique_users', ascending=False).reset_index()
  169. avg_shows = filtered_2.query('event == "show"')['unique_users'].mean()
  170. funnel_data['avg_shows'] = avg_shows
  171. funnel_data['share_of_shows'] = funnel_data['avg_unique_users']/funnel_data['avg_shows']
  172.  
  173. #отрисовка графика истории событий
  174. events_history = []
  175. for item_topic in events_by_minute['item_topic'].unique():
  176. events_history += [go.Scatter(x = events_by_minute.query('item_topic == @item_topic')['dt'],
  177. y = events_by_minute.query('item_topic == @item_topic')['visits'],
  178. mode = 'lines',
  179. stackgroup = 'one',
  180. name = item_topic)]
  181.  
  182. #отрисовка графика разбивки по темам источников
  183. events_sources = [go.Pie(
  184. labels = events_by_source_topic['source_topic'],
  185. values = events_by_source_topic['visits'])]
  186.  
  187. #отрисовка графика глубины взаимодействия
  188. events_funnel = [go.Bar(
  189. x = funnel_data['event'],
  190. y = funnel_data['share_of_shows'])]
  191.  
  192. #результат для отоброажения
  193. return ({
  194. 'data': events_history,
  195. 'layout': go.Layout(xaxis = {'title': 'Минута'},
  196. yaxis = {'title': 'Количество событий'})
  197. },
  198. {'data': events_sources,
  199. 'layout': go.Layout()
  200. },
  201. {'data': events_funnel,
  202. 'layout': go.Layout(xaxis = {'title': 'Событие'},
  203. yaxis = {'title': 'Средняя доля от показов'})
  204. },
  205. )
  206.  
  207. if __name__ == '__main__':
  208. app.run_server(debug = True, host='0.0.0.0')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement