Plotly: Plotting one trace with two x-axes that are not linearly related

The problem

I am trying to plot data that can be presented as either Absorbance vs Wavelength (nm) or Absorbance vs Wavenumber (cm⁻¹). Note the conversion is cm⁻¹ = 10⁷/nm.

I wish to plot a single trace with one y-axis (‘Absorbance’) and two x-axes ( ‘Wavelength (nm)’ and ‘Wavenumber (cm⁻¹)’ )

Presently, my plan is to graph the both traces but keep one invisible. However, I do not understand how to implement a secondary x-axis. Additionally, is there a way to scale the Wavenumber axis properly such that both the visible and invisible plots overlay each other?

Sample Data and Starting Code

import pandas as pd
import plotly.graph_objects as go

data = pd.DataFrame[{'Wavelength' = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000}
                     'Absorbance' = {1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.04, 1.03, 1.02, 1.01}

def nm_convert(nm):
    wavenumber = 10000000/nm
    return wavenumber

data['Wavenumber'] = nm_convert(data['Wavelength'])

trace1 = go.Scatter(x=dataset['Wavelength'], y=dataset['Absorbance'], mode='lines', line=dict(width=1.5), name='nm_trace')
trace2 = go.Scatter(x=dataset['Wavenumber'], y=dataset['Absorbance'], name='cm-1 trace', visible=False)

Example Image

I’ve made an example of the result I might be looking for. However, I am open to alternative suggestions.

enter image description here


There are several questions here, and I believe @vestland has answered the primary question. But to expand on his answer and to address your second question you can use a combination of tickvals and ticktext to achieve the “rescaling” of the second axis, another example here.

Below is an example adapted from vestland’s work, with the following comments

  • there’s two series here, the second is not shown with opacity=0
  • for xaxis2 the tickvals are Wavelength but the ticktext is set to the Wavenumber (also rounded with round)
  • using customdata and hovertemplate on the first series to provide a unified hover
import pandas as pd
import plotly.graph_objects as go

data = pd.DataFrame({'Wavelength' : [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000],
                     'Absorbance' : [1.00,1.01,1.02,1.03,1.04,1.05,1.04,1.03,1.02,1.01]})
data['Wavenumber'] = 10000000/data['Wavelength']

fig = go.Figure()
                            "Wavelength: %{x}<br>" +
                            "Wavenumber: %{customdata:.0f}<br>" +
                            "Absorbance: %{y}" +

fig.update_layout(xaxis= {'title':'Wavelength','showgrid':False,})
fig.update_layout(yaxis= {'title':'Absorbance','showgrid':False,})
fig.update_layout(xaxis2= {'title':'Wavenumber', 'showgrid':False,
                           'anchor': 'y', 
                           'overlaying': 'x', 
                           'side': 'top',

enter image description here