Figure Friday 2025 - week 15

Hey Ester, nice work. This skewed at all? Trying to reconcile how this is data is reflecting such a small miles per charge? “4.1% of EVs, followed by Rivian (10.7%) and BMW (9.52%). The dashboard also shows that Land Rover models—Range Rover Sport and Range Rover—have the longest electric range, reaching nearly 60 miles on a single charge.”

I know when I owned a Tesla it was well over 200 miles. Was this for hybrid?

2 Likes

Thank you @ThomasD21M, I will check it tomorrow.

2 Likes

Here’s my dash app for figure Friday.

Spent a bit of time handling data cleaning. There are a lot of zeros for range in the data. I was able to recover many of them by applying the average of non-zero ranges for models that have multiple unique ranges. The others I simply dropped costing about 20% of the data. Because we are exploring range, I decided that EVs with no listed range wasn’t helping matters.

I stratified the data by year selectable with a slider and by EV type (BEV vs PHEV) with a multi-value dropdown.

The map shows what percentage of the statewide total EV type for a given county and year. I used a log color scale to allow differentiation of the less populous counties. The sunburst plot responds to the year selected, the EV type and the county by clicking on the map. It breaks the data down by manu and model. I find it interesting to see the dominance of Tesla beginning in the late 20-teens.

Scroll down to the bottom to see how the range has changed by model year via a box plot. The boxplot responds to the selected EV type and shows that range has been increasing over the years for BEVs, but not much for PHEVs.

I used some styling elements from @Avacsiglo21 's app because CSS and web dev isn’t at all my forte and their app looked so danged good.

I’ll toss the code on github.

If you want to play with it, It’s hosted here (with limited resources, so it will be slow):

5 Likes

Excellent work. The combination interactivity of the map/sunburst is beatiful :muscle:

3 Likes

That’s a nice looking app. I like how you made the figure headings into questions. And the icon in the middle of the pie chart is :pinched_fingers:

3 Likes

I recently started using Coolors.co to help me generate palette ideas! Starting to experiment with a standard theme and using asset folder in my directory. more advanced builds than I previously made. Apparently it has a feature where you can upload a website page and it replicates the color scheme too. Haven’t tried that yet.

2 Likes

Thank you @ThomasD21M ! I’ll check it out.

2 Likes

The EV dataset has significant limitations. Two thirds of the range values were 0. The Base MSRP values were 0 for over 99% of the entries, and the data is restricted to Washington State.

I excluded the dominant EV brand, to serve potential buyers who seek an alternative.

I ran an analysis to show the 5 most popular alternative EV car makers based on the number of appearances in the data set, grouped by make over the range of 2021 to 2025. I came up with 5 brands representing USA, Germany, Korea, Sweden and Japan. All of these brands have grown in 2025.

Here is the visualization:

Here is the code:

import polars as pl
import polars.selectors as cs
import plotly.express as px

# dataset issue:
#   99.8% of dataset is from Washington State. I dropped all other locations.
#   Base MSRP is 0 for 99.5% of the entries, dropped this too
#   Utility company info is long and messy, dropped it to
#   Vehicle Indentification Numbers (VIN) dropped, no interest
#   Range data is not credible with 2/3 of values as 0, dropped it too

df = (
    pl.scan_csv('Electric_Vehicle_Population_Data.csv')  # lazyframe
    .select(
        STATE = pl.col('State'),
        YEAR = pl.col('Model Year'),
        MAKE = pl.col('Make'),
    )
    .filter(pl.col('STATE') == 'WA')
    .filter(pl.col('MAKE') != 'TESLA')
    .select(
        'YEAR', 'MAKE', # 'MODEL',
        YEAR_MAKE_TOT = pl.col('STATE').count().over(['YEAR', 'MAKE']),
        YEAR_TOT = pl.col('STATE').count().over('YEAR'),
    )
    .unique(['YEAR', 'MAKE'])
    .with_columns(
        PCT_SHARE = 100*(pl.col('YEAR_MAKE_TOT')/pl.col('YEAR_TOT'))
    )
    .collect()  # convert to dataframe for pivot
    .pivot(
        on='MAKE',
        index='YEAR',
        values='PCT_SHARE'
    )
    .lazy()     # back to lazyframe
    .filter(pl.col('YEAR') > 2020)
    .sort('YEAR')
    .with_columns(
        PCT_TOT = pl.sum_horizontal(cs.exclude(pl.col('YEAR')))
    )
    .with_columns(
        PCT_TOT = pl.when(pl.col('PCT_TOT') >= 5)
                    .then('PCT_TOT')
                    .otherwise(pl.lit(0.0))
    )
    .with_columns(
        pl.col('YEAR').cast(pl.String)
    )
    .collect()  # lazyframe to data frame from here to the end of script
)

#----- EXCLUDE MAKES WITH 1 OR MORE NULL VALUES, ALPHABETIC SORT ---------------
sorted_cols_null_filter = sorted(
    [
        c for c in df.columns 
        if (df[c].is_null().sum() <= 1) and
        (c not in ['YEAR', 'PCT_TOT'])
    ]
)

#----- MAKE LIST OF TOP 5 MAKES in 2025 ----------------------------------------
top_5_makes = (
    df
    .select(['YEAR'] + sorted_cols_null_filter + ['PCT_TOT'] )
    .transpose(
        include_header=True,
        header_name='MAKE',
        column_names='YEAR',
    )
    .sort('2025', descending=True)
    .head(6)    # make a list of the top 6 makes
    .tail(5)    # then exclude the top brand
    .select('MAKE')
    .to_series()
    .to_list()
)

#----- COLOR DICTIONARY FOR THE GRAPHS AND ANNOTATED LABELS --------------------
my_color_dict = dict(
    zip(top_5_makes,px.colors.qualitative.Vivid[:5] )
)

#----- PLOT SHARE OF TOP 5 ALTERNATIVE EVS--------------------------------------
my_subtitle = (
    'Companies not led by ' +
    '<b>M</b>ostly <b>U</b>nhinged <b>S</b>pace <b>K</b>ings'
)
fig=px.line(
    df,
    'YEAR',
    top_5_makes,
    # Just found out from plotly youtube that markers can be enabled in px.line
    markers=True, 
    title="WASHINGTON STATE'S TOP 5 ALTERNATE ELECTRIC VEHICLES",
    subtitle=my_subtitle,
    template='simple_white',
    line_shape='spline',
    color_discrete_map=my_color_dict,
    height=500, width=800
)
for make in top_5_makes:
    fig.add_annotation(
            x=0.96, xref='paper',
            y=df[make].to_list()[-1], yref='y',
            text=f'<b>{make}</b>',
            showarrow=False,
            xanchor='left',
            font=dict(color=my_color_dict.get(make))
        )
    
data_source = 'https://catalog.data.gov/dataset/electric-vehicle-population-data'
fig.update_layout(
    showlegend=False,
    xaxis=dict(
        title=dict(text=f'Data source: {data_source}', font=dict(color='gray')),
    ),
    yaxis=dict(
        title=dict(
            text='ALTERNATE EV SHARE', 
            font=dict(color='gray'),
        ),
        ticksuffix = "%",
    ),
    hovermode='x unified'
)
fig.show()
4 Likes

@ThomasD21M The problem was that the Range column had a lot of 0 values, but everything is there in 2020, so I narrowed it down, so maybe the data is real. But at least it fits on Pycafe. :slight_smile: Tesla leads.

This Dash web application, titled “Washington Electric Vehicle Dashboard (2020),” provides an interactive platform for exploring electric vehicle data specifically for the year 2020. Users can select a specific vehicle make or choose “All” to view data for all makes. The dashboard includes a pie chart displaying the top 10 manufacturers by count and a bar chart for the top 10 models by electric range. Additionally, it features an **AG Grid ** with all available vehicle data, which users can sort and filter.

2 Likes

Your data selection is no surprise :sweat_smile:

2 Likes

Nice catch!

2 Likes

Mike, I didn’t know Rivian is that popular.
Do you see it a lot in California?

1 Like

Nice usage of the box plot, @ranknovice . I wonder why the median value hasn’t changed since 2020? It seems to be stuck around 275.

1 Like

Hey everyone,
A reminder that our figure friday session starts in one hour.

Looking forward to reviewing all apps and sharing insights.

1 Like

Yes, I have friends and neighbors who drive Rivians, despite being expensive. That said, while the alternative makes are growing, I wouldn’t call any of them popular yet. While Tesla is losing share, they are still the most dominant model of any brand I see around here, and that includes the gas-powered cars.

Hey Mike, something stuck with me on this week 15 project. I appreciated your approach subtracting Tesla from the data as it skewed it in such a way it was not useful. I saw this chart and it immediately made it recall this challenge. I think this was an interesting, yet still aesthetically simple approach to this challenge. Like a chart in a chart?

SpaceX and other nation state actors skew the data so much it made since to breakout the other contributions. Stumbled across the chart on social, not sure how to original author was.

1 Like

Thank you @ThomasD21M. I like your chart.

1 Like