Histograms with Plotly Express
By: Darío Weitz
Tags: Data Science, Python, Histograms, Charts, Data Visualization

Histograms with Plotly Express

Image by Jayson Hinrichsen from Unsplash

Plotly Express

Plotly Express (PE) is a high-level wrapper for Plotly.py fully compatible with the rest of the Plotly ecosystem. Based on the JavaScript library D3.js., it also has API wrappers for R, Julia, and many other programming languages. It’s free and can be used in commercial applications and products. The library includes functions to plot standard charts and maps, as well as to perform faceting and animations with a single function call. With Plotly Express you can make interactive graphics online but you can also save them offline.

Plotly Express is appropriate for quickly generating exploratory plots. Also, the chart can be quickly styled by using pre-defined themes or templates. According to Plotly main website “Theming generally refers to the process of defining default styles for visual elements. Themes in plotly are implemented using objects called templates. Templates are slightly more general than traditional themes because in addition to defining default styles, templates can pre-populate a figure with visual elements like annotations, shapes, images, and more.” [1].

The built-in themes can be viewed through the following statement:

There are 11 templates: ggplot2, seaborn, plotly, plotly_white, plotly_dark, simple_white, gridon, xgridoff, ygridoff, presentation, and none. The ggplot2 theme is inspired by the R data visualization package ggplot2, whilst the seaborn theme is inspired by the Python data visualization library Seaborn. plotly, plotly_white, and plotly_dark are original plotly.express themes. As indicated above, plotly is the default template, while plotly_dark is inspired by the JupyterLab’s dark theme. The following three themes are related to the presence or absence of grids: gridon, xgridoff, ygridoff . simple_white is a minimalist template for a clear and uncluttered chart. The presentation theme increases the size of fonts, markers, and line widths so that they can be viewed from a greater distance. This theme can be combined with any other (See Fig. 6).

Each one of the above themes can be used as the template argument of any plotly.express function. So, a smart strategy is to iteratively test with the 11 themes until you find the one that best fits your storytelling.

Histograms

A histogram is a graphical representation of the distribution of a dataset. Although its appearance is similar to that of a standard bar graph, instead of making comparisons between different items or categories or showing trends over time, a histogram is a plot that lets you show the underlying frequency distribution or the probability distribution of a single continuous numerical variable.

Histograms are two-dimensional plots with two axes; the vertical axis is a frequency axis whilst the horizontal axis is divided into a range of numeric values (intervals or bins) or time intervals. The frequency of each bin is shown by the area of vertical rectangular bars. Each bar covers a range of continuous numeric values of the variable under study. The vertical axis shows frequency values derived from counts for each bin.

Storytelling: a histogram is an appropriate graph for the initial exploration of a continuous variable. Through a set of vertical bars, it shows how the numerical values ​​of that variable are distributed. The histogram allows us to calculate the probability of representation of any value of the continuous variable under study, which is of great importance if we want to make inferences and estimate population values ​​from the results of our sample.

Histograms with Plotly Express

We worked with a dataset downloaded from Kaggle [2]. The dataset consists of 10,000 bank customers mentioning their age, salary, marital status, credit card limit, credit card category, education level, and additional features. The bank manager wants to know the age distribution of his customers. The following code allows us to answer his questions.

First, we import plotly.express as px , and the pandas library as pd . We load our dataset as a pandas dataframe ( df ) and select the column Customer_Age as the numerical variable whose frequency distribution we want to know. Draw the figure with px.histogram using plotly, the default template. Finally, we export our chart as a static PNG format.

PE allows you to choose the number of bins. Even though there are no strictly defined rules for the size and number of intervals, you must try out a few different numbers of bins. Always keep in mind that: few intervals do not allow us to elucidate the fine structure of the data distribution; many intervals give importance to the sampling error.

import pandas as pd

import plotly.express as px path = 'your path'

df = pd.read_csv(path + 'CreditCardCustomersCols.csv', index_col = False, header = 0, sep = ';', engine='python') fig1 = px.histogram(df, x="Customer_Age", nbins = 10) fig1.write_image(path + "fighist1.png")

fig1.show()

Fig. 1 shows the age distribution of the bank customers in five-year bins. Clearly, there are very few Centennials and few Millennials. The generation cohorts of the customers are represented by Baby Boomers and Gen X.

Fig. 1: Histogram made with Plotly Express with the default template. Image by Author.

In Fig.2 we changed the theme to ggplot2 , and update the chart with update.layout: set the title; the name of the x-axis and the name of the y-axis; set the figure dimensions with width and height .

fig2 = px.histogram(df, x="Customer_Age", nbins = 10, template = 'ggplot2') fig2.update_layout(title = "Histogram of Customers' Age ", xaxis_title = 'Customer Age', yaxis_title = 'Standard Count', width = 1600, height = 1400) fig2.write_image(path + "fighist2.png")

fig2.show()

Fig. 2: Histogram made with Plotly Express with the ggplot2 template. Image by Author.

By default, PE shows in the vertical axis frequencies (counts) of the data that fall into each bin. You can change this mode using the histnorm argument. This argument can take the following values: percent, probability, density, or probability density.

In Fig.3 we changed the theme to plotly_dark and the mode of representation from the standard count of samples to the percent one using the histnorm argument.

In Fig. 4 we changed the theme to simple_white and the mode to probabilty.

fig3 = px.histogram(df, x="Customer_Age", nbins = 10, template = 'plotly_dark', histnorm = 'percent') fig3.update_layout(title = "Histogram of Customers' Age ",xaxis_title = 'Customer Age', yaxis_title = 'Percent Count', width = 1600, height = 1400) fig3.write_image(path + "fighist3.png")

fig3.show() fig4 = px.histogram(df, x=”Customer_Age”, nbins = 10, template = ‘simple_white’, histnorm = ‘probability’) fig4.update_layout(title = “Histogram of Customers’ Age “,xaxis_title = ‘Customer Age’, yaxis_title = ‘Probability ‘, width = 1600, height = 1400) fig4.write_image(path + “fighist4.png”)

fig4.show()

Fig. 3: Histogram made with Plotly Express with the plotly_dark template. Image by Author.

Fig. 4: Histogram made with Plotly Express with the simple_white template. Image by Author.

In Fig. 5 we removed the x gridlines using the xgridoff template. Probability Density was selected as the mode of representation. In Fig. 6 we returned to the probability mode and changed the theme to simple_white+presentation . Clearly, there is an increase in the size of fonts, markers, and line widths.

fig5 = px.histogram(df, x=”Customer_Age”, nbins = 10, template = xgridoff’, histnorm = ‘probability density’) fig5.update_layout(title = “Histogram of Customers’ Age “, xaxis_title = ‘Customer Age’, yaxis_title = ‘Probability Density’, width = 1600, height = 1400) fig5.write_image(path + “fighist5.png”)

fig5.show() fig6 = px.histogram(df, x=”Customer_Age”, nbins = 10, template = ‘simple_white+presentation’, histnorm = ‘probability’) fig6.update_layout(title = “Histogram of Customers’ Age “, xaxis_title = ‘Customer Age’, yaxis_title = ‘Probability ‘, width = 1600, height = 1400) fig6.write_image(path + “fighist6.png”)

fig6.show()

Fig. 5: Histogram made with Plotly Express with the xgridoff template.Image by Author.

Fig. 6: Histogram made with Plotly Express with the simple+presentation template. Image by Author.

Overlapping histograms are used to compare the frequency distribution of a continuous variable in two or more categories. Even though the PE website indicates that you can draw several histograms for the different values of one column using the argument color , I did not get a proper chart. So, I filtered the dataframe for the two different values of the categorical variable “ Gender ”, use twice the px.histogram function, and “merge” both figures with the add_trace method. As the px.histogram function does not have a text attribute, we used the argument color only for labeling purposes. We used different themes to be able to identify each figure and the barmode = ‘overlay’ argument to get the overlapping. Figure 7 shows that there is no difference in the distribution of customers according to their gender.

df7a = df[df[‘Gender’] == ‘M’]

df7b = df[df[‘Gender’] == ‘F’] fig7a = px.histogram(df7a, x=”Customer_Age”, nbins = 10, template=‘seaborn’, barmode = ‘overlay’, color = “Gender”) fig7b = px.histogram(df7b, x=”Customer_Age”, nbins = 10,

template = ‘ggplot2’, opacity = 0.25, color = ‘Gender’) fig7a.update_layout(title = “Histogram of Customers’ Age & Gender”,xaxis_title = ‘Customer Age’, yaxis_title = ‘Standard Count‘, width = 1600, height = 1400) fig7a.add_trace(fig7b.data[0]) fig7a.write_image(path + “fighist7.png”)

fig7a.show()

Fig. 7: Overlapping histograms made with Plotly Express with the seaborn and plotly_dark templates. Image by Author.

Fig. 8 shows overlapping histograms for the categorical variable Marital_Status according to the Married, Single, or Divorced condition. We used three different templates and the color argument to be able to identify each figure. The barmode and the opacity level were indicated with update_layout and update_traces respectively.

df8a = df[df[‘Marital_Status’] == ‘Married’]

df8b = df[df[‘Marital_Status’] == ‘Single’]

df8c = df[df[‘Marital_Status’] == ‘Divorced’] fig8a = px.histogram(df8a, x=”Customer_Age”, nbins = 10, template = ‘seaborn’, color = ‘Marital_Status’ ) fig8b = px.histogram(df8b, x=”Customer_Age”, nbins = 10, template = ‘ggplot2’, color = ‘Marital_Status’) fig8c = px.histogram(df8c, x=”Customer_Age”, nbins = 10, template = ‘plotly_dark’, color = ‘Marital_Status’) fig8a.update_layout(title = “Histogram of Customers’ Age & Marital Status”,xaxis_title = ‘Customer Age’, yaxis_title = ‘Probability ‘, width = 1600, height = 1400) fig8a.add_trace(fig8b.data[0])

fig8a.add_trace(fig8c.data[0]) fig8a.update_layout(barmode=’overlay’)

fig8a.update_traces(opacity = 0.75) fig8a.write_image(path + “fighist8.png”)

fig8a.show()

Fig. 8: Overlapping histograms made with Plotly Express with the seaborn, ggplot2, and plotly_dark templates. Image by Author.

Some Warnings

You can see (even on the PE website) categorical histograms and also date histograms.

Categorical histograms refer to counts from categories of a discrete variable. I do not consider that they can be defined as histograms, but rather as bar charts (BC). Remember that standard bar charts are used to make numerical comparisons amongst categories whilst histograms are used to show the frequency distribution of a numerical variable. Besides, there are no “gaps” or spaces between the bars of a histogram, but it is mandatory to leave some space between the bars on a BC to clearly indicate that it refers to discrete (mutually exclusive) groups.

Something similar happens with date histograms: bins created as date ranges are equivalent to an average value for a specific year, so a bar chart or a line chart are more appropriate than a histogram to show the trend over time.

PE allows rotating the histogram so counts are in the horizontal axis while intervals or bins of the numerical variable are in the vertical axis. I do not find any technical reason for such an arrangement and it should be avoided because it is contrary to all existing histogram definitions.

Last but not least, using the histnorm argument with density or probability density values does not translate into density plots. Density plots attempt to show the probability density function of the data set through a continuous curve. With that goal in mind, density plots apply a statistical procedure (kernel density estimation) with the idea of smoothing the rectangular bars that characterize the histogram. As a result, a smooth curve is obtained that allows better visualization of the shape of the distribution (Fig. 9).

Fig. 9: Comparison of the histogram (left) and kernel density estimation (right) constructed using the same data. The 6 individual kernels are the red dashed curves; the blue curve is the kernel density estimation. The data points are the rug plot on the horizontal axis. Source: [3].

To sum up:

Plotly Express is a user-friendly data visualization tool that includes 11 pre-defined themes or templates to speed up work and avoid delays.

You can draw a histogram with a single line of code.

As histograms are considered to be some of the most commonly used charts, you must be very clear about when should histograms be used and which are the differences between them and bar charts.

References

[1]: https://plotly.com/python/templates/

[2]: https://www.kaggle.com/sakshigoyal7/credit-card-customers

[3]: https://en.wikipedia.org/wiki/Kernel_density_estimation