1

I am using the following Python code to produce a sunburst plot:-

import plotly
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv('CellUsageStats.csv',dtype={'Population':int},keep_default_na=False)
print(df.head(50))
fig = px.sunburst(df, path=['LibPrefix', 'MasterPrefixAbrHead', 'MasterPrefixAbrTail', 'Drive'], values='Population', color='Population', color_continuous_scale=px.colors.sequential.Inferno)
fig.update_traces(hovertemplate='Pattern: %{currentPath}%{label}<br>Matches: %{value}<br>Percent of <b>%{parent}</b>: %{percentParent:0.2%f}<br>Percent of <b>%{entry}</b>: %{percentEntry:0.2%f}<br>Percent of <b>%{root}</b>: %{percentRoot:0.2%f}')
fig.show()
plotly.offline.plot(fig, filename='sunburst.html')

I have a second csv file that I use to produce another sunburst, using the same code above. How do I combine them to create side-by-side plots in the same html output? I found...

https://plotly.com/python/sunburst-charts/

However, I really need px.sunburst attributes, and the examples in the above link use go.Sunburst, not px.sunburst. Is there a straightforward way to produce side-by-side plots from two different sets of data?

Thanks!

vestland
  • 55,229
  • 37
  • 187
  • 305
Chris
  • 179
  • 1
  • 11
  • Are you looking for [subplots](https://plotly.com/python/subplots/)? – S3DEV Oct 15 '20 at 20:11
  • If you REALLY need to use Plotly Express plots, then I think you out of luck (see this [link](https://plotly.com/python/mixed-subplots/)). However, have you read the full documentation for go.Sunburst [here](https://plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.Sunburst.html) and are sure it doesn't have inputs for the attributes you need? – Jacob K Oct 15 '20 at 21:00
  • @Chris How did my suggestion work out for you? – vestland Oct 19 '20 at 19:37
  • Hi, @vestland, yes, I was able to get your example to work; however, I don't think it will work with the px.sunburst attributes that I am using. I am especially interested in some of the more complex hovertemplate properties (in original post). I was unable to pass those properties to go.Sunburst without error. So I am kind of at a dead end here, unfortunately. – Chris Oct 19 '20 at 20:21
  • @Chris If you're able to share a sample of your data, then just maybe we can work it out. – vestland Oct 19 '20 at 20:36
  • @Chris `path`, for example, wasn't a problem to implement for another example. Just had to include the `ids` arguments like `ids=sb1[0]['ids']` and `ids=sb2[0]['ids']`. I don't see any reason why the other elements should not be able to implement as well... – vestland Oct 19 '20 at 21:34
  • @vestland, sure, just have df1 = pd.read_csv consume a file with the header line `LibPrefix,MasterPrefixAbrHead,MasterPrefixAbrTail,Drive,Population` and then just have the subsequent lines include 4 strings and then an integer, e.g. `lib1,A,B,D1,10`. – Chris Oct 20 '20 at 02:52
  • @vestland and then the second df2 - pd.read_scv would point to the same file format, but with different strings, e.g `lib2,Z,V,D12,133`. – Chris Oct 20 '20 at 02:54
  • It is the hovertemplate that is causing the problems--its attributes are not understood by go.Sunburst. unless I am missing something. – Chris Oct 20 '20 at 02:55
  • @Chris I don't think hovertemplate should be a problem either. But that "sample" isn't much to work with. What you've got in your comment is rather a *description* of your data. Proper samples are usually regarded as a crucial element to a good question on SO. But I understand that the payoff might not outweigh the time and effort it takes to provide a proper data sample, so nevermind. – vestland Oct 20 '20 at 05:44
  • @vestland thanks for helping--it is much appreciated. The two lines of data I supplied are actually what's in the csv files, only there are another 1000 lines or so per file. If there is a way to point to the contents, I would happily make them available. But I am not sure how to do that in SO, and I don't have any public data that can be accessed via an html link. – Chris Oct 20 '20 at 13:27
  • @ChrisThere's rarely any need to share your *complete* dataset. Take a look [here](https://stackoverflow.com/questions/63163251/pandas-how-to-easily-share-a-sample-dataframe-using-df-to-dict/63163254#63163254) on how to share a *sample* – vestland Oct 20 '20 at 13:40

2 Answers2

7

Here's a modified version of @vestland's answer that makes use of subplots:

import plotly.express as px
from plotly.subplots import make_subplots

# data for px.sunburst1
data1 = dict(character=["Eve", "Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
             parent=["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve"],
             value=[10, 14, 12, 10, 2, 6, 6, 4, 4])

# data for px.sunburst2
data2 = dict(character=["Eve", "Cain", "Seth", "Enos"],
             parent=["", "Eve", "Eve", "Seth"],
             value=[10, 14, 12, 10])

# extract data and structure FROM px.sunburst1
sb1 = px.sunburst(data1,
                  names='character',
                  parents='parent',
                  values='value',
                  )

# extract data and structure FROM px.sunburst2
sb2 = px.sunburst(data2,
                  names='character',
                  parents='parent',
                  values='value',
                  )

fig = make_subplots(rows=1, cols=2, specs=[
    [{"type": "sunburst"}, {"type": "sunburst"}]
])

fig.add_trace(sb1.data[0], row=1, col=1)
fig.add_trace(sb2.data[0], row=1, col=2)
fig.show()
marcusaurelius
  • 121
  • 2
  • 4
  • That works very well ! Thanks. @chris I suggest you to mark this one as the validated answer – Skratt Mar 28 '23 at 14:43
2

Answer

The following suggestion will show you how you can:

1. build two separate px.Sunburst figures, and

2. extract all necessary info regarding data and structure from them using ._data, and

3. use that to build two go.Sunburst traces, and

4. set them up side by side using the domain attribute.

In other words, you form your figures using px.Sunburst, and steal what you need from there to easily set up two sunburst diagrams side by side.

Plot

enter image description here

Complete code

import plotly
import plotly.offline as py
import plotly.graph_objs as go
import plotly.express as px

# data for px.sunburst1
data1 = dict(character=["Eve", "Cain", "Seth", "Enos", "Noam", "Abel", "Awan", "Enoch", "Azura"],
             parent=["", "Eve", "Eve", "Seth", "Seth", "Eve", "Eve", "Awan", "Eve" ],
             value=[10, 14, 12, 10, 2, 6, 6, 4, 4])

# data for px.sunburst2
data2 = dict(character=["Eve", "Cain", "Seth", "Enos"],
             parent=["", "Eve", "Eve", "Seth" ],
             value=[10, 14, 12, 10])

# extract data and structure FROM px.sunburst1
sb1 =px.sunburst(data1,
                 names='character',
                 parents='parent',
                 values='value',
                )._data

# extract data and structure FROM px.sunburst2
sb2 =px.sunburst(data2,
                 names='character',
                 parents='parent',
                 values='value',
                )._data

# traces with separate domains to form a subplot
trace1 = go.Sunburst(labels=sb1[0]['labels'],
                        parents=sb1[0]['parents'],
                        values=sb1[0]['values'],
                        domain={'x': [0.0, 0.5], 'y': [0.0, 1]})

trace2 = go.Sunburst(labels=sb2[0]['labels'],
                        parents=sb2[0]['parents'],
                        values=sb2[0]['values'],
                        domain={'x': [0.5, 1.0], 'y': [0., 1.00]})

# layout and figure production
layout = go.Layout(height = 600,
                   width = 600,
                   autosize = False,
                   title = 'Side by side px.Sunburst diagrams')
fig = go.Figure(data = [trace1, trace2], layout = layout)
fig.show()
vestland
  • 55,229
  • 37
  • 187
  • 305