Home > Enterprise >  Format numbers with regex and pattern.sub in Dash, Python
Format numbers with regex and pattern.sub in Dash, Python

Time:12-08

I am using following simplified Dash app. layout to highlight some values in a datatable. I want all the numbers to be RED. However, if left like this, all the numbers are red, but in each string the numbers are replaced with first numbers (see picture). I am sure the error is in re.compile(".\d (?:\,\d )?") or pattern.sub() since I never worked with regex before. How would you modified it? Thank you in advance.

bad outcome

import pandas as pd
import numpy as np
import re
import dash
from dash import dash_table 
from dash import Dash, html, dcc, dash_table
from dash.dash_table.Format import Format, Sign
from dash.dependencies import Input, Output, State


l = ["787", "9", "65"]

df = pd.DataFrame({ 
        "col1":["ABC, 787, CDE, 654", "956, 4587, 9, 65"], 
        "col2":["21, 7, 659, 75", "0, KLO, 441"]})

user_input = dcc.Input(id = 'substance', type = 'text') 

result_table = dash_table.DataTable(
                id = 'table',
                css = [dict(selector="p", rule = "margin: 0px; text-align: center")],
                data = df.to_dict('records'),
                columns = [
                            {"name": "col1", "id": "col1", "presentation": "markdown"},
                            {"name": "col2", "id": "col2", "presentation": "markdown"},
                            ],
                markdown_options = {"html": True},
)





external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = Dash(__name__, external_stylesheets = external_stylesheets)

app.layout = html.Div([
    html.Div([
        user_input,
        html.Button(id = "button", n_clicks = 0, children = "Enter"),
    ]),
    html.Div([result_table]),
])



@app.callback(
    Output("table", "data"),
    Input('button', 'n_clicks'),
    prevent_initial_call = True)

def update_dashboard(n_clicks):
    
    
    pattern = re.compile(".\d (?:\,\d )?")
    
    def color_brackets(value):
        
        
                found = re.search(pattern, value)
                if found:
                    color = "red"
                    substituted = pattern.sub(
                        f"<span style='color: {color};'>{found.group()}</span>", value)
                    return substituted
                return value


    
    df_color = pd.DataFrame({ 
                            "col1":["ABC, 787, CDE, 654", "956, 4587, 9, 65"], 
                            "col2":["21, 7, 659, 75", "0, KLO, 441"],
    })
    
    
    df_color["col1"] = df_color["col1"].apply(color_brackets)
    df_color["col2"] = df_color["col2"].apply(color_brackets)
    
    
    df_color_data = df_color.to_dict('records')
    print(df_color_data)

        
    return df_color_data

if __name__ == '__main__':
    app.run_server(debug = True, use_reloader = False)

CodePudding user response:

the error is when you call pattern.sub() you use found.group() which returns the first result of running the regex againt the value

you can do this instead:

    def color_brackets(value):
        color = "red"
        pattern.sub(f"<span style='color: {color};'>\g<0></span>", value)

The `\g<0> indicates that the first group from you regex should enter here (you have one group that is all the regex).

The regex finds multiple matches against the string, so it will replace each one of them with its own group.

  • Related