Plot.ly

Plot.ly is a JavaScript graphing library that enables interactivity in python and R charts.

Note: Plot.ly is currently in beta support in both Periscope’s Python and R environments. Please send any feedback or requests to the solutions team via live chat or support@periscopedata.com

Note: Plot.ly Dash is not supported

Leveraging Plot.ly

Plot.ly can be added to the python or R environment by importing it like any other supported library:

import plotly.plotly as py
from plotly import graph_objs as go

To pass Plot.y interactive plots to Periscope for visualization, pass the figure into periscope.plotly():

periscope.plotly(fig)

The plot.ly Mode Bar is off by default. It can be enabled by including the following into the output.

For Python 2.7 & 3.6, pass the configurations into periscope.plotly():

periscope.plotly(figure,config={'displayModeBar':True})

For R, pass the configurations directly into the figure:

p <- plot_ly(data = iris, x = ~Sepal.Length, y = ~Petal.Length, type="scatter", mode="markers") %>% config(displayModeBar = TRUE)
periscope.plotly(p)

Python Plot.ly Example: Sankey Chart

This is an example Python script which uses Plot.ly to make a Sankey chart (example shown above).

# SQL output is imported as a dataframe variable called 'df'
import pandas as pd
import numpy as np

DEFAULT_PLOTLY_COLORS = [
   '#1f77b4',  # muted blue
   '#ff7f0e',  # safety orange
   '#2ca02c',  # cooked asparagus green
   '#d62728',  # brick red
   '#9467bd',  # muted purple
   '#e377c2',  # raspberry yogurt pink
   '#7f7f7f',  # middle gray
   '#bcbd22',  # curry yellow-green
   '#17becf'   # blue-teal
]

def color(i):
 return DEFAULT_PLOTLY_COLORS[i % len(DEFAULT_PLOTLY_COLORS)]

def rgb_from_hex(hex):
 h = hex.lstrip('#')
 return ",".join(str((int(h[i:i+2], 16))) for i in (0, 2 ,4))

def is_circular(df_agg, row):
  circular_reference = df_agg.query(f'prior_stage_index == {row["stage_index"]} & stage_index == {row["prior_stage_index"]}')
  
  if circular_reference.size == 0:
   return False
  elif circular_reference['count'].iloc[0] > row['count']:
   return True
  else:
   return False

df.columns = [c.lower() for c in df.columns]

stages = df.groupby(['stage_name']).size().reset_index()[['stage_name']]
stages['stage_index'] = stages.index
stages['color'] = stages.apply(lambda r: color(r['stage_index']), axis=1)

# print(stages)
df['stage_index'] = df.apply(lambda r: stages.loc[stages['stage_name'] == r['stage_name']]['stage_index'].iloc[0], axis=1)
df['prior_stage_index'] = df.groupby('unique_id').stage_index.shift()

df = df[np.isfinite(df['prior_stage_index'])]

df['prior_stage_name'] = df.apply(lambda r: stages.loc[stages['stage_index'] == r['prior_stage_index']]['stage_name'].iloc[0], axis=1)

df['prior_stage_index'] = df['prior_stage_index'].astype(int)

df_agg = df.groupby(['prior_stage_index', 'prior_stage_name', 'stage_index', 'stage_name']).size().reset_index(name='count')

df_agg['is_circular'] = df_agg.apply(lambda row: is_circular(df_agg, row), axis=1)
df_agg = df_agg.query('is_circular == False')

priors = df_agg['prior_stage_index']
ends = stages.query('stage_index not in @priors')
print(ends)

df_agg['color'] = df_agg.apply(lambda r: f'rgba({rgb_from_hex(color(r["prior_stage_index"]))},{.95 if r["stage_index"] in ends["stage_index"] else .25})', axis=1)
print(df_agg)    

data=dict(
 type='sankey',
 node=dict(
   label=stages['stage_name'],
   pad = 20,
   thickness = 5,
   color=stages['color'],
   line=dict(
     width=0
   )
 ),
 link=dict(
   source=df_agg['prior_stage_index'].astype(int)
   ,target=df_agg['stage_index']
   ,value=df_agg['count']
   ,color=df_agg['color']
 )
)

layout =  dict(
   font = dict(
     size = 16
   ),
   hoverlabel = dict(
       bgcolor = 'purple'
   ),
 margin=dict(
               t=20,
               b=50,
               l=10,
               r=10
             )
)

fig = dict(data=[data], layout=layout)
periscope.plotly(fig)



Our support team is ready to help