Conditional Formatting

Conditional formatting is provided through the style_data_conditional
property. The if keyword provides a set of conditional formatting
statements and the rest of the keywords are camelCased CSS properties.

The if syntax supports several operators, row_index, column_id,
filter_query, column_type, column_editable, and state.

filter_query is the most flexible option when dealing with data.

Here is an example of all operators:

using Dash 

using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[
        Dict("name" => "Date", "id" => "Date", "type" => "datetime", "editable" => false),
        Dict("name" => "Delivery", "id" => "Delivery", "type" => "datetime"),
        Dict("name" => "Region", "id" => "Region", "type" => "text"),
        Dict("name" => "Temperature", "id" => "Temperature", "type" => "numeric"),
        Dict("name" => "Humidity", "id" => "Humidity", "type" => "numeric"),
        Dict("name" => "Pressure", "id" => "Pressure", "type" => "any"),
    ],
    editable=true,
    style_data_conditional=[
        Dict(
            "if" => Dict(
                "column_id" => "Region",
            ),
            "backgroundColor" => "dodgerblue",
            "color" => "white"
        ),
        Dict(
            "if" => Dict(
                "filter_query" => "{Humidity} > 19 && {Humidity} < 41",
                "column_id" => "Humidity"
            ),
            "backgroundColor" => "tomato",
            "color" => "white"
        ),

        Dict(
            "if" => Dict(
                "column_id" => "Pressure",

                # since using .format, escape { with {{
                "filter_query" => "{Pressure} = $(maximum(df[!,"Pressure"]))"
            ),
            "backgroundColor" => "#85144b",
            "color" => "white"
        ),

        Dict(
            "if" => Dict(
                "row_index" => 5,  # number | "odd" | "even"
                "column_id" => "Region"
            ),
            "backgroundColor" => "hotpink",
            "color" => "white"
        ),

        Dict(
            "if" => Dict(
                "filter_query" => "{id} = 4",  # matching rows of a hidden column with the id, `id`
                "column_id" => "Region"
            ),
            "backgroundColor" => "RebeccaPurple"
        ),

        Dict(
            "if" => Dict(
                "filter_query" => "{Delivery} > {Date}", # comparing columns to each other
                "column_id" => "Delivery"
            ),
            "backgroundColor" => "#3D9970"
        ),

        Dict(
            "if" => Dict(
                "column_editable" => false  # True | False
            ),
            "backgroundColor" => "rgb(240, 240, 240)",
            "cursor" => "not-allowed"
        ),

        Dict(
            "if" => Dict(
                "column_type" => "text"  # "text" | "any" | "datetime" | "numeric"
            ),
            "textAlign" => "left"
        ),

        Dict(
            "if" => Dict(
                "state" => "active"  # "active" | "selected"
            ),
           "backgroundColor" => "rgba(0, 116, 217, 0.3)",
           "border" => "1px solid rgb(0, 116, 217)"
        )

    ],

)

run_server(app, "0.0.0.0", debug=true)

Notes:
- filter_query supports different operators depending on the data type
of the column:

Alternative Highlighting Styles

Instead of highlighting the background cell, you can change the color
of the text, bold the text, add underlines, or style it using any
other CSS property.

using Dash 

using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df)],
    style_data_conditional=[
        Dict(
            "if" =>  Dict(
                "filter_query" =>  "{Humidity} > 19 && {Humidity} < 41",
                "column_id" =>  "Humidity"
            ),
            "color" =>  "tomato",
            "fontWeight" =>  "bold"
        ),
        Dict(
            "if" =>  Dict(
                "filter_query" =>  "{Pressure} > 19",
                "column_id" =>  "Pressure"
            ),
            "textDecoration" =>  "underline"
        )
    ]

)

run_server(app, "0.0.0.0", debug=true)

Special Characters like Emojis, Stars, Checkmarks, Circles

You can copy and paste emoji unicode characters directly into your code.
We recommend copying values from emojipedia, e.g.
https://emojipedia.org/star/.

New unicode emoji characters are released every year and may not be
available in the character sets of your audience’s machines.
The appearance of these icons differs on most operating systems.

This example has not been ported to Julia yet - showing the Python version instead.

Visit the old docs site for Julia at: https://community.plotly.com/c/dash/julia/20


from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict

data = OrderedDict(
    [
        ("Date", ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"]),
        ("Region", ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"]),
        ("Temperature", [1, -20, 3.512, 4, 10423, -441.2]),
        ("Humidity", [10, 20, 30, 40, 50, 60]),
        ("Pressure", [2, 10924, 3912, -10, 3591.2, 15]),
    ]
)

df = pd.DataFrame(data)

df['Rating'] = df['Humidity'].apply(lambda x:
    '⭐⭐⭐' if x > 30 else (
    '⭐⭐' if x > 20 else (
    '⭐' if x > 10 else ''
)))
df['Growth'] = df['Temperature'].apply(lambda x: '↗️' if x > 0 else '↘️')
df['Status'] = df['Temperature'].apply(lambda x: '🔥' if x > 0 else '🚒')

app = Dash()

app.layout = dash_table.DataTable(
    data=df.to_dict('records'),
    columns=[
        {"name": i, "id": i} for i in df.columns
    ],
)

if __name__ == '__main__':
    app.run(debug=True)

Filtering and Conditional Formatting Recipes

Highlighting the Max Value in a Column

using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    columns=[Dict("name" =>c, "id" => c) for c in names(df)],
    style_data_conditional=[
        Dict(
            "if" =>  Dict(
                "filter_query" =>  "{Pressure} = $(maximum(df[!,"Pressure"]))",
                "column_id" =>  "Pressure"
            ),
            "backgroundColor" =>  "#FF4136",
            "color" =>  "white"
        ),
    ]

)

run_server(app, "0.0.0.0", debug=true)

Highlighting a Row with the Min Value

using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 


app = dash()

app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    columns=[Dict("name" =>c, "id" => c) for c in names(df)],
    style_data_conditional=[
        Dict(
            "if" =>  Dict(
                "filter_query" =>  "{Temperature} = $(minimum(df[!,"Temperature"]))"
            ),
            "backgroundColor" =>  "#FF4136",
            "color" =>  "white"
        ),
    ]

)

run_server(app, "0.0.0.0", debug=true)

Highlighting the Top Three or Bottom Three Values in a Column

using Dash 
using DataStructures   
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 


app = dash()

app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    columns=[Dict("name" =>c, "id" => c) for c in names(df)],
    style_data_conditional=vcat(
      [
          Dict(
              "if" =>  Dict(
                  "filter_query" =>  "{Temperature} = $i",
                  "column_id" =>  "Temperature",
              ),
              "backgroundColor" =>  "#0074D9",
              "color" =>  "white"
          )
          for i in nlargest(3,df[!,"Temperature"])
      ],
      [
          Dict(
              "if" =>  Dict(
                  "filter_query" =>  "{Pressure} = $i",
                  "column_id" =>  "Pressure",
              ),
              "backgroundColor" =>  "#7FDBFF",
              "color" =>  "white"
          )
          for i in nsmallest(3, df[!,"Pressure"])
      ]
    )

)

run_server(app, "0.0.0.0", debug=true)

Highlighting the Max Value in Every Row

using Base: Number
using CSV: eltype
using Dash 

using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

df[!,"id"] = 1:size(df)[1]
app = dash()

function highlight_max_row(df)
  df1 = select(df, Not(:id))
  nm = names(df1)
  new_nm = String[]
  for (idx, ec) in enumerate(eachcol(df1))
    if (eltype(ec) <: Number)
      push!(new_nm,nm[idx])
    end
  end
    df_numeric_columns = df[!,new_nm]
  locs = let x = Symbol[]
    map(eachrow(df_numeric_columns)) do rw
      push!(x, argmax(rw))
    end
    x
  end
    return [
        Dict(
            "if" =>  Dict(
                "filter_query" =>  "{id} = $idx",
                "column_id" =>  col
            ),
            "backgroundColor" =>  "#3D9970",
            "color" =>  "white"
        )
        for (idx,col) in enumerate(locs)
    ]
end
app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c!= "id"],
    style_data_conditional=highlight_max_row(df)

)

run_server(app, "0.0.0.0", debug=true)

Highlighting the Top Two Values in a Row

using Base: Number
using CSV: eltype
using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

df[!,"id"] = 1:size(df)[1]
app = dash()

function style_row_by_top_values(df, nlg=2)
  df1 = select(df, Not(:id))
  nm = names(df1)
  new_nm = String[]
  for (idx, ec) in enumerate(eachcol(df1))
    if (eltype(ec) <: Number)
      push!(new_nm,nm[idx])
    end
  end
  df_numeric_columns = df[!,new_nm]
  styles = Dict[]
  for i in 1:nrow(df_numeric_columns)
    row_loc = sortperm(Array(df_numeric_columns[i, new_nm]), rev=true)
    for j in 1:nlg
      val = Dict(
        "if" => Dict(
            "filter_query" => "{id} = $i",
            "column_id" => new_nm[row_loc[j]]
        ),
        "backgroundColor" => "#39CCCC",
        "color" => "white"
      )
      push!(styles,val)
    end
  end

  return styles
end
app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c != "id"],
    style_data_conditional=style_row_by_top_values(df)

)

run_server(app, "0.0.0.0", debug=true)

Highlighting the Maximum Value in the Table

using Dash
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

df[!,"id"] = 1:nrow(df)
app = dash()

function style_table_by_max_value(df)
  df1 = select(df, Not(:id))
  nm = names(df1)
  new_nm = names(df1,Number)
  df_numeric_columns = df[!,new_nm]
  df_numeric_columns_mat = Array(df_numeric_columns)
  max_val, max_idx = findmax(df_numeric_columns_mat, dims=2)
  max_across_table = maximum(max_val)
  styles = Dict[]
  for (idx,col) in enumerate(max_val)
    if col == max_across_table
      push!(styles,
        Dict(
          "if" =>  Dict(
              "filter_query" =>  "{id} = $idx",
              "column_id" =>  new_nm[idx]
            ),
          "backgroundColor" =>  "#39CCCC",
          "color" =>  "white"
        )
      )
    end
  end  
  return styles
end
app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c != "id"],
    style_data_conditional=style_table_by_max_value(df)

)

run_server(app, "0.0.0.0", debug=true)

Highlighting a Range of Values

using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()


app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c!= "id"],
    style_data_conditional=[
        Dict(
            "if" =>  Dict(
                "filter_query" =>  "{2018} >= 5 && {2018} < 10",
                "column_id" =>  "2018"
            ),
            "backgroundColor" =>  "#B10DC9",
            "color" =>  "white"
        )
    ]

)

run_server(app, "0.0.0.0", debug=true)
using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()


app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c!= "id"],
    style_data_conditional=[
      Dict(
          "if" =>  Dict(
              "filter_query" =>  "{$col} >= 5 && {$col} < 10",
              "column_id" =>  col
          ),
          "backgroundColor" =>  "#B10DC9",
          "color" =>  "white"
      ) for col in names(df)
  ]

)

run_server(app, "0.0.0.0", debug=true)

Let’s break down \{{\{col}}}. We want the final expression to look something like
{2017} > 5 & {2017} < 10 where 2017 is the name of the column.
Since we’re using .format(), we need to escape the brackets,
so {2017} would be {{2017}}. Then, we need to replace 2017 with {col}
for the find-and-replace, so becomes\{{\{col}}}.format(col=col)

Highlighting Top 10% or Bottom 10% of Values by Column

using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

nm = names(df)
new_nm = names(df,Number)
df_numeric_columns = df[!,new_nm]
val_quant = [quantile(Array(df_numeric_columns[!,n]), 0.9) for n in names(df_numeric_columns)]


app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c!= "id"],
    style_data_conditional=[
      Dict(
          "if" =>  Dict(
              "filter_query" =>  "{$(new_nm[idx])} >= $value",
              "column_id" =>  new_nm[idx]
              ),
          "backgroundColor" =>  "#B10DC9",
          "color" =>  "white"
      ) for (idx, value) in enumerate(val_quant)
  ]

)

run_server(app, "0.0.0.0", debug=true)
using Dash 
using Statistics
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

nm = names(df)
new_nm = names(df,Number)
df_numeric_columns = df[!,new_nm]
val_quant = [quantile(Array(df_numeric_columns[!,n]), 0.1) for n in names(df_numeric_columns)]


app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c!= "id"],
    style_data_conditional=[
      Dict(
          "if" =>  Dict(
              "filter_query" =>  "{$(new_nm[idx])} <= $value",
              "column_id" =>  new_nm[idx]
              ),
          "backgroundColor" =>  "#B10DC9",
          "color" =>  "white"
      ) for (idx, value) in enumerate(val_quant)
  ]

)

run_server(app, "0.0.0.0", debug=true)

Highlighting Values above Average and Below Average

Here, the highlighting is done per column.

using Dash 
using Statistics
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

nm = names(df)
new_nm = names(df,Number)
df_numeric_columns = df[!,new_nm]
val_quant_5 = [quantile(Array(df_numeric_columns[!,n]), 0.5) for n in names(df_numeric_columns)]
val_quant_1 = [quantile(Array(df_numeric_columns[!,n]), 0.1) for n in names(df_numeric_columns)]


app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c!= "id"],
    style_data_conditional=vcat(
      [
          Dict(
              "if" =>  Dict(
                  "filter_query" =>  "{$(new_nm[col])} > $value",
                  "column_id" =>  new_nm[col]
              ),
              "backgroundColor" =>  "#3D9970",
              "color" =>  "white"
              ) for (col, value) in enumerate(val_quant_1)
      ],
      [
          Dict(
              "if" =>  Dict(
                  "filter_query" =>  "{$(new_nm[col])} <= $value",
                  "column_id" =>  new_nm[col]
              ),
              "backgroundColor" =>  "#FF4136",
              "color" =>  "white"
              ) for (col, value) in enumerate(val_quant_5)
      ]
  )

)

run_server(app, "0.0.0.0", debug=true)

Here, the highlighting is done per table.

using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

nm = names(df)
new_nm = names(df,Number)
df_numeric_columns = df[!,new_nm]
df_mean = mean([mean(df[!,n]) for n in names(df, Number)])


app.layout = dash_datatable(
    data = map(eachrow(df)) do r
      Dict(names(r) .=> values(r))
    end,
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df) if c!= "id"],
    style_data_conditional=vcat(
      [
          Dict(
              "if" =>  Dict(
                  "filter_query" =>  "{$col} > $df_mean",
                  "column_id" =>  col
              ),
              "backgroundColor" =>  "#3D9970",
              "color" =>  "white"
              ) for col in names(df)
      ],
      [
          Dict(
              "if" =>  Dict(
                  "filter_query" =>  "{$col} <= $df_mean",
                  "column_id" =>  col
              ),
              "backgroundColor" =>  "#FF4136",
              "color" =>  "white"
              ) for col in names(df)
      ]
  )

)

run_server(app, "0.0.0.0", debug=true)

Highlighting None, NaN, or Empty String Values

Three filter queries help with empty or blank values:
- {my_column} is nil will match None values
- {my_column} is blank will match None values and empty strings
- {my_column} = "" will match empty strings

using Dash

using DataFrames   

data_with_none = [
    Dict("Firm" =>  "Acme", "2017" =>  "", "2018" =>  5, "2019" =>  10, "2020" =>  4),
    Dict("Firm" =>  "Olive", "2017" =>  nothing, "2018" =>  3, "2019" =>  13, "2020" =>  3),
    Dict("Firm" =>  "Barnwood", "2017" =>  NaN, "2018" =>  7, "2019" =>  3, "2020" =>  6),
    Dict("Firm" =>  "Henrietta", "2017" =>  14, "2018" =>  1, "2019" =>  13, "2020" =>  1),
]

df = vcat(DataFrame.(data_with_none)...)

df2 = ifelse.(ismissing.(df) .| (df .∈ Ref(["nothing", "None"])), missing, df)
app = dash()

app.layout = html_div([
  html_pre(string(df)),
  dash_datatable(
      data=Dict.(pairs.(eachrow(df2))),
      columns=[Dict("name" =>c, "id" => c) for c in names(df)],
      style_data_conditional=(
          [
              Dict(
                  "if" =>  Dict(
                      "filter_query" =>  "{$col} is blank",
                      "column_id" =>  col
                  ),
                  "backgroundColor" =>  "tomato",
                  "color" =>  "white"
              ) for col in names(df)
          ]
      )
  )
])

run_server(app, "0.0.0.0", debug=true)
        Firm  2017  2018  2019  2020
0       Acme           5    10     4
1      Olive  None     3    13     3
2   Barnwood   NaN     7     3     6
3  Henrietta    14     1    13     1

Displaying Special Values for NaN or None Values

This example has not been ported to Julia yet - showing the Python version instead.

Visit the old docs site for Julia at: https://community.plotly.com/c/dash/julia/20

from dash import Dash, dash_table, html
import pandas as pd
import numpy as np
from dash.dash_table.Format import Format

data_with_none = [
    {'Firm': 'Acme', '2017': '', '2018': 5, '2019': 10, '2020': 4},
    {'Firm': 'Olive', '2017': None, '2018': 3, '2019': 13, '2020': 3},
    {'Firm': 'Barnwood', '2017': np.NaN, '2018': 7, '2019': 3, '2020': 6},
    {'Firm': 'Henrietta', '2017': 14, '2018': 1, '2019': 13, '2020': 1},
]
df = pd.DataFrame(data_with_none)

app = Dash()

app.layout = html.Div([
    html.Pre(repr(df)),
    dash_table.DataTable(
        data=df.to_dict('records'),
        columns=[
            {
                'name': i,
                'id': i,
                'type': 'numeric',
                'format': Format(
                    nully='N/A'
                )
            } for i in df.columns
        ],
        editable=True
    )
])

if __name__ == '__main__':
    app.run(debug=True)
        Firm  2017  2018  2019  2020
0       Acme           5    10     4
1      Olive  None     3    13     3
2   Barnwood   NaN     7     3     6
3  Henrietta    14     1    13     1

Limitations:
- Format(nully=) does not yet match for empty strings, only
None values. See plotly/dash-table#763
for updates.
- 'type': 'numeric' needs to be set, see plotly/dash-table#762
for updates.

An alternative method would be to fill in e.g. “N/A” in the data before rendering:

using Dash

using CSV, DataFrames   

data_with_none = [
    Dict("Firm" =>  "Acme", "2017" =>  "", "2018" =>  5, "2019" =>  10, "2020" =>  4),
    Dict("Firm" =>  "Olive", "2017" =>  nothing, "2018" =>  3, "2019" =>  13, "2020" =>  3),
    Dict("Firm" =>  "Barnwood", "2017" =>  NaN, "2018" =>  7, "2019" =>  3, "2020" =>  6),
    Dict("Firm" =>  "Henrietta", "2017" =>  14, "2018" =>  1, "2019" =>  13, "2020" =>  1),
]

df = vcat(DataFrame.(data_with_none)...)

df[!,"2017"] = replace(df[!,"2017"], NaN => "N/A")
df[!,"2017"] = replace(df[!,"2017"], missing => "N/A")

app = dash()

app.layout = html_div([
  html_pre(string(df)),
  dash_datatable(
      data=Dict.(pairs.(eachrow(df))),
      columns=[Dict("name" =>c, "id" => c) for c in names(df)],
      style_data_conditional=(
          [
              Dict(
                  "if" =>  Dict(
                      "filter_query" =>  "{$col} = $(string("N/A"))",
                      "column_id" =>  col
                  ),
                  "backgroundColor" =>  "tomato",
                  "color" =>  "white"
              ) for col in names(df)
          ]
      )
  )
])

run_server(app, "0.0.0.0", debug=true)
        Firm 2017  2018  2019  2020
0       Acme  N/A     5    10     4
1      Olive  N/A     3    13     3
2   Barnwood  N/A     7     3     6
3  Henrietta   14     1    13     1

Limitation: If your table is editable, then if a user deletes the
contents of a cell, “N/A” will no longer be displayed.
This is unlike the example with Format where the DataTable will
automatically display N/A for any empty cells, even after editing.

Highlighting Text that Contains a Value

using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()


app.layout = dash_datatable(
    data = Dict.(pairs.(eachrow(df))),
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df)],
    style_data_conditional=[
      Dict(
          "if" => Dict(
              "filter_query" => "{Region} contains $("New")"
          ),
          "backgroundColor" => "#0074D9",
          "color" => "white"
      )
  ]

)

run_server(app, "0.0.0.0", debug=true)

Highlighting Text that Equals a Value

using Dash 
using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()


app.layout = dash_datatable(
    data = Dict.(pairs.(eachrow(df))),
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df)],
    style_data_conditional=[
      Dict(
          "if" => Dict(
              "filter_query" => "{Region} = $("London")"
          ),
          "backgroundColor" => "#0074D9",
          "color" => "white"
      )
  ]

)

run_server(app, "0.0.0.0", debug=true)

Highlighting Cells by Value with a Colorscale Like a Heatmap

This recipe shades cells with style_data_conditional and creates a
legend with HTML components. You’ll need to pip install colorlover
to get the colorscales.

using Dash

using DataFrames, Colors   

wide_data = [
    Dict("Firm" =>  "Acme", "2017" =>  13, "2018" =>  5, "2019" =>  10, "2020" =>  4),
    Dict("Firm" =>  "Olive", "2017" =>  3, "2018" =>  3, "2019" =>  13, "2020" =>  3),
    Dict("Firm" =>  "Barnwood", "2017" =>  6, "2018" =>  7, "2019" =>  3, "2020" =>  6),
    Dict("Firm" =>  "Henrietta", "2017" =>  -3, "2018" =>  -10, "2019" =>  -5, "2020" =>  -6),
]

df = vcat(DataFrame.(wide_data)...)

app = dash()

function discrete_background_color_bins(df; n_bins=5, columns="all")
  bounds = [(i-1) * (1.0 / n_bins) for i in 1:n_bins+1]
  nme = names(df, Number)
  if columns == "all"        
      df_numeric_columns = df[!,nme]
  else
      df_numeric_columns = df[!,columns]
  end
  df_max = maximum(Array(df_numeric_columns))
  df_min = minimum(Array(df_numeric_columns))
  ranges = [
      ((df_max - df_min) * i) + df_min
      for i in bounds
  ]
  styles = Dict[]
  legend = Component[]
  for i in 1:length(bounds)-1
      min_bound = ranges[i]
      max_bound = ranges[i+1]
      backgroundColor = string("#",lowercase(hex.(colormap("Blues",n_bins))[i]))
      color = i > (length(bounds) / 2.) ? "white" : "inherit"
      for column in names(df_numeric_columns)
        chk = i < (length(bounds) - 1) ? " && {$column} < $max_bound" : ""
          push!(styles, Dict(               
             "if" => Dict(  
                  "filter_query" => string("{$column} >= $min_bound", chk),
                  "column_id"=> column
              ),
              "backgroundColor" => backgroundColor,
              "color"=> color
          )
      )
      end
      push!(legend,
          html_div(style=Dict("display"=> "inline-block", "width"=> "60px"), children=[
              html_div(
                  style=Dict(
                      "backgroundColor"=> backgroundColor,
                      "borderLeft"=> "1px rgb(50, 50, 50) solid",
                      "height"=> "10px"
                  )
              ),
              html_small(round(min_bound, digits=2), style=Dict("paddingLeft"=> "2px"))
          ])
      )
    end

  return (styles, html_div(legend, style=Dict("padding"=> "5px 0 5px 0")))
end
(styles, legend) = discrete_background_color_bins(df, n_bins=5, columns=["2018"])
app.layout = html_div([
    html_div(children=[legend], style=Dict("float" => "right")),
    dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        sort_action="native",
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        style_data_conditional=styles
    ),
])

run_server(app, "0.0.0.0", debug=true)
-10.0
-5.4
-0.8
3.8
8.4

Highlighting with a Colorscale on a Single Column

using Dash

using CSV, DataFrames, Colors   

wide_data = [
    Dict("Firm" =>  "Acme", "2017" =>  13, "2018" =>  5, "2019" =>  10, "2020" =>  4),
    Dict("Firm" =>  "Olive", "2017" =>  3, "2018" =>  3, "2019" =>  13, "2020" =>  3),
    Dict("Firm" =>  "Barnwood", "2017" =>  6, "2018" =>  7, "2019" =>  3, "2020" =>  6),
    Dict("Firm" =>  "Henrietta", "2017" =>  -3, "2018" =>  -10, "2019" =>  -5, "2020" =>  -6),
]

df = vcat(DataFrame.(wide_data)...)

app = dash()

function discrete_background_color_bins(df; n_bins=5, columns="all")
  bounds = [(i-1) * (1.0 / n_bins) for i in 1:n_bins+1]
  nme = names(df, Number)
  if columns == "all"        
      df_numeric_columns = df[!,nme]
  else
      df_numeric_columns = df[!,columns]
  end
  df_max = maximum(Array(df_numeric_columns))
  df_min = minimum(Array(df_numeric_columns))
  ranges = [
      ((df_max - df_min) * i) + df_min
      for i in bounds
  ]
  styles = Dict[]
  legend = Component[]
  for i in 1:length(bounds)-1
      min_bound = ranges[i]
      max_bound = ranges[i+1]
      backgroundColor = string("#",lowercase(hex.(colormap("Blues",n_bins))[i]))
      color = i > (length(bounds) / 2.) ? "white" : "inherit"
      for column in nme
        chk = i < (length(bounds) - 1) ? " && {$column} < $max_bound" : ""
          push!(styles, Dict(               
             "if" => Dict(  
                  "filter_query" => string("{$column} >= $min_bound", chk),
                  "column_id"=> column
              ),
              "backgroundColor" => backgroundColor,
              "color"=> color
          )
      )
      end
      push!(legend,
          html_div(style=Dict("display"=> "inline-block", "width"=> "60px"), children=[
              html_div(
                  style=Dict(
                      "backgroundColor"=> backgroundColor,
                      "borderLeft"=> "1px rgb(50, 50, 50) solid",
                      "height"=> "10px"
                  )
              ),
              html_small(round(min_bound, digits=2), style=Dict("paddingLeft"=> "2px"))
          ])
      )
    end

  return (styles, html_div(legend, style=Dict("padding"=> "5px 0 5px 0")))
end
(styles, legend) = discrete_background_color_bins(df)
app.layout = html_div([
    html_div(children=[legend], style=Dict("float" => "right")),
    dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        sort_action="native",
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        style_data_conditional=styles
    ),
])

run_server(app, "0.0.0.0", debug=true)
-10.0
-6.6
-3.2
0.2
3.6

Displaying Data Bars

These recipes display a creative use of background linear-gradient
colors to display horizontal bar charts within the table.
Your mileage may vary! Feel free to modify these recipes for your own
use.

using Dash

using CSV, DataFrames, Colors   

df_gapminder = CSV.read(download("https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv"), DataFrame)
df = df_gapminder[1:500,:]

app = dash()

function data_bars(df, column)
    n_bins = 100
    bounds = [(i-1) * (1.0 / n_bins) for i in 1:n_bins+1]
    df_max = maximum(Array(df[!,column]))
    df_min = minimum(Array(df[!,column]))
    ranges = [
        ((df_max - df_min) * i) + df_min
        for i in bounds
    ]
    styles = Dict[]
    for i in 1:length(bounds)-1
      min_bound = ranges[i]
      max_bound = ranges[i+1]
      max_bound_percentage = bounds[i+1] * 100
      chk = i < (length(bounds) - 1) ? " && {$column} < $max_bound" : ""
        push!(styles, Dict(
            "if" => Dict(
                "filter_query" => string("{$column} >= $min_bound", chk),
                "column_id" => column
            ),
            "background" => (
                """
                    linear-gradient(90deg,
                    #0074D9 0%,
                    #0074D9 $(max_bound_percentage)%,
                    white $(max_bound_percentage)%,
                    white 100%)
                """
            ),
            "paddingBottom" => 2,
            "paddingTop" => 2
        )
      )
    end

    return styles
end
app.layout =  dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        sort_action="native",
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        style_data_conditional=vcat(
          data_bars(df, "lifeExp"),data_bars(df, "gdpPercap")
        ),
      style_cell=Dict(
          "width" => "100px",
          "minWidth" => "100px",
          "maxWidth" => "100px",
          "overflow" => "hidden",
          "textOverflow" => "ellipsis",
      ),
      page_size=20
    )

run_server(app, "0.0.0.0", debug=true)

Data Bars without Text

Display the data bars without text by creating a new column and making
the text transparent.

using Dash

using CSV, DataFrames, Colors   

df_gapminder = CSV.read(download("https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv"), DataFrame)
df = df_gapminder[1:500,:]

app = dash()

function data_bars(df, column)
    n_bins = 100
    bounds = [(i-1) * (1.0 / n_bins) for i in 1:n_bins+1]
    df_max = maximum(Array(df[!,column]))
    df_min = minimum(Array(df[!,column]))
    ranges = [
        ((df_max - df_min) * i) + df_min
        for i in bounds
    ]
    styles = Dict[]
    for i in 1:length(bounds)-1
      min_bound = ranges[i]
      max_bound = ranges[i+1]
      max_bound_percentage = bounds[i+1] * 100
      chk = i < (length(bounds) - 1) ? " && {$column} < $max_bound" : ""
        push!(styles, Dict(
            "if" => Dict(
                "filter_query" => string("{$column} >= $min_bound", chk),
                "column_id" => column
            ),
            "background" => (
                """
                    linear-gradient(90deg,
                    #0074D9 0%,
                    #0074D9 $(max_bound_percentage)%,
                    white $(max_bound_percentage)%,
                    white 100%)
                """
            ),
            "paddingBottom" => 2,
            "paddingTop" => 2
        )
      )
    end

    return styles
end
df[!,"gdpPercap relative values"] = df[!,"gdpPercap"]
app.layout =  dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        sort_action="native",
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        style_data_conditional= vcat(
          data_bars(df, "gdpPercap relative values"),
          [Dict(
            "if" => Dict("column_id" => "gdpPercap relative values"),
            "color" => "transparent"
          )]
        ),
      style_cell=Dict(
          "width" => "100px",
          "minWidth" => "100px",
          "maxWidth" => "100px",
          "overflow" => "hidden",
          "textOverflow" => "ellipsis",
      ),
      page_size=20
    )

run_server(app, "0.0.0.0", debug=true)

Diverging Data Bars

The data_bars_diverging function splits up the data into two quadrants
by the midpoint.
Alternative representations of data bars may split up the data by
positive and negative numbers or by the average values.
Your mileage may vary! Feel free to modify the data_bars_diverging
function to your own visualization needs. If you create something new,
please share your work on the Dash Community Forum.

using Dash

using CSV, DataFrames 

df_gapminder = CSV.read(download("https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv"), DataFrame)
df = df_gapminder[1:500,:]

app = dash()

app.layout =  dash_datatable(
        data=Dict.(pairs.(eachrow(df))),
        sort_action="native",
        columns=[Dict("name" =>c, "id" => c) for c in names(df)],
        style_data_conditional=[Dict(
          "if" =>  Dict("filter_query" =>  "{Date} datestartswith $(string("2015-10"))"),
          "backgroundColor" =>  "#85144b",
          "color" =>  "white"
          )]
    )

run_server(app, "0.0.0.0", debug=true)

Highlighting Dates

using Dash

using OrderedCollections, DataFrames   

data = OrderedDict(
      "Date" => ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"],
      "Region" => ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"],
      "Temperature" => [1, -20, 3.512, 4, 10423, -441.2],
      "Humidity" => [10, 20, 30, 40, 50, 60],
      "Pressure" => [2, 10924, 3912, -10, 3591.2, 15],
)

df = DataFrame(data) 

app = dash()

app.layout =  dash_datatable(
    data=Dict.(pairs.(eachrow(df))),
    sort_action="native",
    columns=[Dict("name" =>c, "id" => c) for c in names(df)],
    style_data_conditional=[Dict(
        "if" =>  Dict("filter_query" =>  "{Date} datestartswith $(string("2015-10"))"),
        "backgroundColor" =>  "#85144b",
        "color" =>  "white"
        )]
)

run_server(app, "0.0.0.0", debug=true)