Advertisement
Guest User

Untitled

a guest
Dec 6th, 2019
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.06 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. # пример подключения к базе данных для Postresql
  19. #db_config = {'user': 'my_user',
  20. #             'pwd': 'my_user_password',
  21. #             'host': 'localhost',
  22. #             'port': 5432,
  23. #             'db': 'games'}
  24. #engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
  25. #                                                            db_config['pwd'],
  26. #                                                            db_config['host'],
  27. #                                                            db_config['port'],
  28. #                                                            db_config['db']))
  29. # пример подключения к базе данных для Sqlite
  30. engine = create_engine('sqlite:////db/games.db', echo = False)
  31.  
  32. # получаем сырые данные
  33. query = '''
  34.            SELECT * FROM agg_games_year_genre_platform
  35.        '''
  36. agg_games_year_genre_platform = pd.io.sql.read_sql(query, con = engine)
  37. agg_games_year_genre_platform["year_of_release"] = pd.to_datetime(agg_games_year_genre_platform["year_of_release"])
  38. query = '''
  39.            SELECT * FROM agg_games_year_score
  40.        '''
  41. agg_games_year_score = pd.io.sql.read_sql(query, con = engine)
  42. # игнорируем записи без оценок
  43. agg_games_year_score = agg_games_year_score.query('avg_user_score > 0 and avg_critic_score > 0')
  44.  
  45. note = '''
  46.          Этот дашборд показывает историю игрового рынка (исключая мобильные устройства).
  47.          Используйте выбор интервала даты выпуска, жанра и платформы для управления дашбордом.
  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.     html.Div([
  63.         html.Div([
  64.  
  65.             # график выпуска игр по годам и жанрам
  66.             html.Label('Выпуск игр по жанрам:'),    
  67.  
  68.             dcc.RadioItems(
  69.                 options = [
  70.                     {'label': 'Абсолютные значения', 'value': 'absolute_values'},
  71.                     {'label': '% от общего выпуска', 'value': 'relative_values'},
  72.                 ],
  73.                 value = 'absolute_values',
  74.                 id = 'mode_selector'
  75.             ),
  76.  
  77.        
  78.             dcc.Graph(
  79.                 id = 'launches_by_year'
  80.             ),  
  81.         ], className = 'eight columns'),            
  82.  
  83.         html.Div([
  84.             # график выпуска игр по платформам
  85.              html.Label('Выпуск игр по платформам:'),
  86.             dcc.Graph(
  87.                 id = 'launches_by_platform'
  88.             ),    
  89.         ], className = 'four columns'),
  90.  
  91.     ], className = 'row'),
  92.  
  93.     html.Div([
  94.         html.Div([
  95.  
  96.             # график выпуска игр по годам и жанрам
  97.             html.Label('Продажи игр по жанрам:'),    
  98.        
  99.             dcc.Graph(
  100.                 id = 'sales_by_year'
  101.             ),  
  102.         ], className = 'eight columns'),            
  103.  
  104.         html.Div([
  105.             # график средних оценок по
  106.             html.Label('Средние оценки по жанрам:'),    
  107.        
  108.             dcc.Graph(
  109.                 id = 'score_scatter'
  110.             ),  
  111.         ], className = 'four columns'),
  112.        
  113.     ], className = 'row'),  
  114.  
  115.  
  116.     # пояснения
  117.     html.Label(note),    
  118.  
  119.     html.Br(),    
  120.  
  121.     html.Div([  
  122.  
  123.         html.Div([
  124.             # выбор временного периода
  125.             html.Label('Года выпуска:'),
  126.             dcc.DatePickerRange(
  127.                 start_date = agg_games_year_genre_platform['year_of_release'].dt.date.min(),
  128.                 end_date = datetime(2016,1,1).strftime('%Y-%m-%d'),
  129.                 display_format = 'YYYY-MM-DD',
  130.                 id = 'dt_selector',      
  131.             ),
  132.         ], className = 'two columns'),
  133.  
  134.         html.Div([    
  135.             # выбор жанра
  136.             html.Label('Жанры:'),
  137.             dcc.Dropdown(
  138.                 options = [{'label': x, 'value': x} for x in agg_games_year_genre_platform['genre'].unique()],
  139.                 value = agg_games_year_genre_platform['genre'].unique().tolist(),
  140.                 multi = True,
  141.                 id = 'genre_selector'
  142.             ),                  
  143.         ], className = 'four columns'),    
  144.  
  145.         html.Div([        
  146.             # выбор платформы
  147.             html.Label('Платформы:'),
  148.             dcc.Dropdown(
  149.                 options = [{'label': x, 'value': x} for x in agg_games_year_genre_platform['platform'].unique()],
  150.                 value = agg_games_year_genre_platform['platform'].unique().tolist(),
  151.                 multi = True,
  152.                 id = 'platform_selector'
  153.             ),                
  154.         ], className = 'six columns'),
  155.  
  156.     ], className = 'row'),        
  157.  
  158. ])
  159.  
  160. #описываем логику дашборда
  161. @app.callback(
  162.     [Output('launches_by_year', 'figure'),
  163.      Output('sales_by_year', 'figure'),
  164.      Output('launches_by_platform', 'figure'),
  165.      Output('score_scatter', 'figure'),
  166.     ],
  167.     [Input('dt_selector', 'start_date'),
  168.      Input('dt_selector', 'end_date'),
  169.      Input('mode_selector', 'value'),
  170.      Input('genre_selector', 'value'),
  171.      Input('platform_selector', 'value'),
  172.     ])
  173. def update_figures(start_date, end_date, mode, selected_genres, selected_platforms):
  174.    
  175.     #приводим входные параметры к нужным типам
  176.     start_date = datetime.strptime(start_date, '%Y-%m-%d')
  177.     end_date = datetime.strptime(end_date, '%Y-%m-%d')
  178.  
  179.     #применяем фильтрацию
  180.     filtered = agg_games_year_genre_platform.query('year_of_release >= @start_date and year_of_release <= @end_date')
  181.     filtered = filtered.query('genre in @selected_genres')
  182.     filtered = filtered.query('platform in @selected_platforms')
  183.    
  184.     filtered_score = agg_games_year_score.query('year_of_release >= @start_date and year_of_release <= @end_date')
  185.     filtered_score = filtered_score.query('genre in @selected_genres')
  186.     filtered_score = filtered_score.query('platform in @selected_platforms')
  187.  
  188.     games_by_genre = (filtered.groupby(['year_of_release', 'genre'])
  189.                       .agg({'games': 'sum', 'total_copies_sold': 'sum'})
  190.                       .reset_index()
  191.                      )
  192.  
  193.     games_by_platform = (filtered.groupby(['platform'])
  194.                          .agg({'games': 'sum'})
  195.                          .reset_index()
  196.                         )
  197.     # все платформы с малым количеством игр помещаем в одну категорию
  198.     games_by_platform['percent'] = games_by_platform['games'] / games_by_platform['games'].sum()
  199.     games_by_platform.loc[games_by_platform['percent'] < 0.05, 'platform'] = 'Другие'
  200.     # и еще раз группируем
  201.     games_by_platform = (games_by_platform.groupby(['platform'])
  202.                          .agg({'games': 'sum'})
  203.                          .reset_index()
  204.                         )
  205.  
  206.     #трансформируем в соотв. с выбранным режимом отображения
  207.     y_label = 'Выпущенные игры'
  208.     y_label_sales = 'Прожажи игр, млн копий'
  209.     if mode == 'relative_values':
  210.         y_label = '% выпущенных игр'
  211.         y_label_sales = '% прожаж игр'
  212.         total = (games_by_genre.groupby('year_of_release')
  213.                  .agg({'games': 'sum', 'total_copies_sold': 'sum'})
  214.                  .rename(columns = {'games': 'total_launches',
  215.                                     'total_copies_sold': 'total_sales'})
  216.                 )
  217.         games_by_genre = (games_by_genre.set_index('year_of_release')
  218.                           .join(total)
  219.                           .reset_index())
  220.         games_by_genre['games'] = games_by_genre['games'] / games_by_genre['total_launches']
  221.         games_by_genre['total_copies_sold'] = games_by_genre['total_copies_sold'] / games_by_genre['total_sales']
  222.  
  223.         # графики выпуска и продаж игр по жанру
  224.         data_by_genre = []
  225.         sales_by_genre = []
  226.         for genre in games_by_genre['genre'].unique():
  227.             data_by_genre += [go.Scatter(x = games_by_genre.query('genre == @genre')['year_of_release'],
  228.                                          y = games_by_genre.query('genre == @genre')['games'],
  229.                                          mode = 'lines',
  230.                                          stackgroup = 'one',
  231.                                          name = genre)]
  232.             sales_by_genre += [go.Bar(x = games_by_genre.query('genre == @genre')['year_of_release'],
  233.                                       y = games_by_genre.query('genre == @genre')['total_copies_sold'],
  234.                                       name = genre)]
  235.  
  236.             # график выпуска игр по платформам    
  237.             data_by_platform = [go.Pie(labels = games_by_platform['platform'],
  238.                                        values = games_by_platform['games'],
  239.                                        name = 'platfroms')]
  240.  
  241.             # точечная диаграмма оценок по жанрам и годам
  242.             scores_by_genre = []
  243.             for genre in filtered_score['genre'].unique():
  244.                 scores_by_genre += [go.Scatter(x = filtered_score.query('genre == @genre')['avg_user_score'],
  245.                                                y = filtered_score.query('genre == @genre')['avg_critic_score'],
  246.                                                mode = 'markers',
  247.                                                name = genre)]
  248.  
  249.                 #формируем результат для отображения
  250.                 return (
  251.                     {
  252.                         'data': 'launches_by_year',
  253.                         'layout': go.Layout(xaxis = {'title': 'Год'},
  254.                                             yaxis = {'title': y_label})
  255.                     },
  256.                     {
  257.                         'data': 'sales_by_year',
  258.                         'layout': go.Layout(xaxis = {'title': 'Год'},
  259.                                             yaxis = {'title': y_label_sales},
  260.                                             barmode = 'stack',
  261.                                            )
  262.                     },            
  263.                     {
  264.                         'data': 'launches_by_platform',
  265.                         'layout': go.Layout()
  266.                     },
  267.                     {
  268.                         'data': 'score_scatter',
  269.                         'layout': go.Layout(xaxis = {'title': 'Средняя оценка пользователей'},
  270.                                             yaxis = {'title': 'Оредняя оценка критиков'})
  271.                     },            
  272.  
  273.                 )  
  274.  
  275. if __name__ == '__main__':
  276.     app.run_server(host='0.0.0.0', port=3000)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement