【问题标题】:python dash table conditional formatting color scalepython dash table条件格式色标
【发布时间】:2020-08-12 08:01:34
【问题描述】:

我想根据值从高到小用色标为列着色 像这样

目前,我在函数中创建破折号表,并为每一列循环发送它;

def make_table_in_div(df, column_name):
    pv = pd.pivot_table(df, index=[column_name], values=['val1'], aggfunc=['mean', 'count']).reset_index()
    pv.columns = [column_name, 'val1', 'count']
    print(column_name)
    div = html.Div([html.H1(column_name), dash_table.DataTable(
        columns=[{"name": i, "id": i} for i in pv.columns],
        data=pv.to_dict('records'),
    )], style={'height': 30, 'margin-right': 'auto', 'margin-left': 'auto', 'width': '800px'})  # 'width': '50%',
    return div

div = [make_table_in_div(df, column_name) for column_name in ['column_name']]
return div

dash table 看起来像流动的图片,我想给 value 列着色

【问题讨论】:

    标签: python-3.x plotly-dash


    【解决方案1】:

    感谢The answer of Kristian Haga。 - 效果很好。

    我想总结一下未来有相同问题的用户和我的选项。当我们想在多列上运行它时,有两种选择:

    1. 原始函数将以相同的比例(最小值和最大值)为所有列着色,因此如果我使用多个列(来自示例:值和计数)运行,它会返回基于最小值和最大值范围着色的表格样式所有列(来自示例:0.193,109)。
      discrete_background_color_bins(df, columns=['value','count'])

      def discrete_background_color_bins(df, n_bins=7, columns='all'):
      
       bounds = [i * (1.0 / n_bins) for i in range(n_bins+1)]
       if columns == 'all':
           if 'id' in df:
               df_numeric_columns = df.select_dtypes('number').drop(['id'], axis=1)
           else:
               df_numeric_columns = df.select_dtypes('number')
       else:
           df_numeric_columns = df[columns]
       df_max = df_numeric_columns.max().max()
       df_min = df_numeric_columns.min().min()
       ranges = [
           ((df_max - df_min) * i) + df_min
           for i in bounds
       ]
       styles = []
       legend = []
       for i in range(1, len(bounds)):
           min_bound = ranges[i - 1]
           max_bound = ranges[i]
           backgroundColor = colorlover.scales[str(n_bins+4)]['div']['RdYlGn'][2:-2][i - 1]
           color = 'black'
      
           for column in df_numeric_columns:
               styles.append({
                   'if': {
                       'filter_query': (
                           '{{{column}}} >= {min_bound}' +
                           (' && {{{column}}} < {max_bound}' if (i < len(bounds) - 1) else '')
                       ).format(column=column, min_bound=min_bound, max_bound=max_bound),
                       'column_id': column
                   },
                   'backgroundColor': backgroundColor,
                   'color': color
               })
           legend.append(
               html.Div(style={'display': 'inline-block', 'width': '60px'}, children=[
                   html.Div(
                       style={
                           'backgroundColor': backgroundColor,
                           'borderLeft': '1px rgb(50, 50, 50) solid',
                           'height': '10px'
                       }
                   ),
                   html.Small(round(min_bound, 2), style={'paddingLeft': '2px'})
               ])
           )
      
       return (styles, html.Div(legend, style={'padding': '5px 0 5px 0'}))
      
    2. 如果我们想根据每列的最小值和最大值分别为其着色, 我们将使用以下函数:
      (非常相似,但首先在列上运行)

       def discrete_background_color_bins(df, n_bins=7, columns='all'):
      
           bounds = [i * (1.0 / n_bins) for i in range(n_bins+1)]
           if columns == 'all':
               if 'id' in df:
                   df_numeric_columns = df.select_dtypes('number').drop(['id'], axis=1)
               else:
                   df_numeric_columns = df.select_dtypes('number')
           else:
               df_numeric_columns = df[columns]
           df_max = df_numeric_columns.max().max()
           df_min = df_numeric_columns.min().min()
           ranges = [
               ((df_max - df_min) * i) + df_min
               for i in bounds
           ]
           styles = []
           legend = []
           for i in range(1, len(bounds)):
               min_bound = ranges[i - 1]
               max_bound = ranges[i]
               backgroundColor = colorlover.scales[str(n_bins+4)]['div']['RdYlGn'][2:-2][i - 1]
               color = 'black'
      
               for column in df_numeric_columns:
                   styles.append({
                       'if': {
                           'filter_query': (
                               '{{{column}}} >= {min_bound}' +
                               (' && {{{column}}} < {max_bound}' if (i < len(bounds) - 1) else '')
                           ).format(column=column, min_bound=min_bound, max_bound=max_bound),
                           'column_id': column
                       },
                       'backgroundColor': backgroundColor,
                       'color': color
                   })
               legend.append(
                   html.Div(style={'display': 'inline-block', 'width': '60px'}, children=[
                       html.Div(
                           style={
                               'backgroundColor': backgroundColor,
                               'borderLeft': '1px rgb(50, 50, 50) solid',
                               'height': '10px'
                           }
                       ),
                       html.Small(round(min_bound, 2), style={'paddingLeft': '2px'})
                   ])
               )
      
           return (styles, html.Div(legend, style={'padding': '5px 0 5px 0'}))
      

    【讨论】:

      【解决方案2】:

      这是可能的。你应该看看这个链接:https://dash.plotly.com/datatable/conditional-formatting 特别是“在单列上使用色标突出显示”部分

      我为你写了一个简单的例子:

      import dash
      import dash_table
      import pandas as pd
      import dash_html_components as html
      import colorlover
      from jupyter_dash import JupyterDash
      
      # Dash Application
      df = pd.DataFrame(list(zip(
          [5,6,7,8,9,10,11,12,13,14],
          [0.328, 0.323, 0.193, 0.231, 0.216, 0.284, 0.250, 0.258, 0.394, 0.455],
          [67, 99, 109, 104, 88, 74, 32, 31, 33, 22]
      )), columns=['column_name', 'value', 'count'])
      
      app = JupyterDash(__name__)
      
      # Function for styling table, defined below
      cols = ['value']
      (styles, legend) = discrete_background_color_bins(df, columns = cols)
      
      app.layout = html.Div([
          legend,
          dash_table.DataTable(
              id = 'table',
              columns = [{"name": i, "id": i} for i in df.columns],
              data = df.to_dict('records'),
              style_data_conditional = styles
          )
      ])
      
      app.run_server(mode='inline')
      

      此函数使用给定的色标返回指定列的每一行的样式列表。

      要获得色阶,您需要使用 pip install colorlover 安装 colorlover

      可在此处找到其他色阶:https://github.com/plotly/colorlover

      # Function for styling the table
      def discrete_background_color_bins(df, n_bins=7, columns='all'):
      
          bounds = [i * (1.0 / n_bins) for i in range(n_bins+1)]
          if columns == 'all':
              if 'id' in df:
                  df_numeric_columns = df.select_dtypes('number').drop(['id'], axis=1)
              else:
                  df_numeric_columns = df.select_dtypes('number')
          else:
              df_numeric_columns = df[columns]
          df_max = df_numeric_columns.max().max()
          df_min = df_numeric_columns.min().min()
          ranges = [
              ((df_max - df_min) * i) + df_min
              for i in bounds
          ]
          styles = []
          legend = []
          for i in range(1, len(bounds)):
              min_bound = ranges[i - 1]
              max_bound = ranges[i]
              backgroundColor = colorlover.scales[str(n_bins+4)]['div']['RdYlGn'][2:-2][i - 1]
              color = 'black'
      
              for column in df_numeric_columns:
                  styles.append({
                      'if': {
                          'filter_query': (
                              '{{{column}}} >= {min_bound}' +
                              (' && {{{column}}} < {max_bound}' if (i < len(bounds) - 1) else '')
                          ).format(column=column, min_bound=min_bound, max_bound=max_bound),
                          'column_id': column
                      },
                      'backgroundColor': backgroundColor,
                      'color': color
                  })
              legend.append(
                  html.Div(style={'display': 'inline-block', 'width': '60px'}, children=[
                      html.Div(
                          style={
                              'backgroundColor': backgroundColor,
                              'borderLeft': '1px rgb(50, 50, 50) solid',
                              'height': '10px'
                          }
                      ),
                      html.Small(round(min_bound, 2), style={'paddingLeft': '2px'})
                  ])
              )
      
          return (styles, html.Div(legend, style={'padding': '5px 0 5px 0'}))
      

      【讨论】:

      • 谢谢。当我在多个列上使用该函数时出现一个小错误,我会尝试修复它。感谢你的回答!!! i.imgur.com/bDrd8q1.png
      • 您要使用相同的比例为列着色,还是仅根据每列中的值着色?
      • 仅根据每列中的值对它们进行着色。解决了这个问题。再次谢谢你:) i.imgur.com/FxNLv42.png
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-13
      • 2022-08-12
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      • 2022-01-07
      • 2021-10-27
      相关资源
      最近更新 更多