<jupyter_start><jupyter_text>Table of Contents plotly[1. Interactive vs static visualisation](Interactive-vs-static-visualisation)  [2. Basics of Plotly](Basics-of-plotly)  [3. Using pandas](Using-pandas)  [4. Using cufflinks](Using-cufflinks)  [5. Interactivity](Interactivity)    [6. Plotting on Maps](Plotting-on-maps)   [7. Exercise solutions](Exercise-solutions)    [8. More Information](More-information)<jupyter_code>import plotly.graph_objs as go
import plotly.offline as pltly
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

pltly.init_notebook_mode(connected=False)
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Interactive vs static visualisation  Some existing packages* [Plotly](https://plot.ly/) - used in this tutorial  * [Bokeh](bokeh.pydata.org)* [mpld3](http://mpld3.github.io/)* [Holoviews](http://holoviews.org/)  Basic comparison<jupyter_code># A simple matplotlib plot is quick to put together
plt.plot([0, 1, 3], [0, 1, 5], color='red')
# As is a simple plotly plot!
pltly.iplot([go.Scatter(x=[0, 1, 3], y=[0, 1, 5], line=dict(color='red'))])
# Actually, you can quickly see the possible benefits by 
# using your matplotlib figure to produce the plotly plot 

fig = plt.figure()
plt.plot([0, 1, 3], [0, 1, 5], color='red')
pltly.iplot_mpl(fig)<jupyter_output><empty_output><jupyter_text>More complex comparisonWe will return to plot this in [section 3](Using-pandas)<jupyter_code>df = pd.read_csv('./data/time_series_60min_singleindex.csv', index_col=0, parse_dates=True, low_memory=False)
de_solar = df.DE_solar_generation.dropna()
de_solar.resample('7D').mean().plot(figsize=(12, 4))
pltly.iplot([go.Scatter(x=de_solar.resample('7D').mean().index,
                        y=de_solar.resample('7D').mean().values)
            ])<jupyter_output><empty_output><jupyter_text>Basics of plotlyFull API is available at: https://plot.ly/python/referenceKeep this open to refer to during the session<jupyter_code>data = [go.Scatter(x=[0, 1, 3], y=[0, 1, 5], line=dict(color='red'))] # define data
pltly.iplot(data) # plot data
data  # `data` is just a list of dictionaries
data[0]['line']['color']='blue' # Update line colour by editing dictionary
pltly.iplot(data) # Plot data
data # See that the dictionary has been updated
data = [go.Scatter(x=[0, 1, 3], y=[0, 1, 5], 
                  line=dict(color='red', dash='dash', width='0.2'), # change line vis
                  marker=dict(symbol='o', size=10, line=dict(width=2, color='black')) # change marker vis
                  )]
pltly.iplot(data)
data = [go.Scatter(x=[0, 1, 3], y=[0, 1, 5],
                   line=dict(color='red', dash='dash', width='0.2'),
                   marker=dict(symbol='o', size=10, line=dict(width=2, color='black')),
                   name='red line'
                  ), # trace 1
        go.Scatter(x=[0, 1, 3], y=[5, 2, 0],
                   line=dict(color='blue', dash='solid', width='0.1'),
                   marker=dict(symbol='asterisk', size=10, line=dict(width=1, color='blue')),
                   name='blue line'
                  ) # trace 2
       ]
pltly.iplot(data)<jupyter_output><empty_output><jupyter_text>Data and LayoutWhere data to be plotted is given within the `data` dictionary, information related to the axes is given in the `Layout` dictionary.<jupyter_code>data = [
    go.Scatter(
        x=[0, 1, 3], y=[0, 1, 5],
        line=dict(color='red', dash='dash', width='0.2'),
        marker=dict(symbol='o', size=10, line=dict(width=2, color='black')),
        name='red line'
    )
]
layout = go.Layout(xaxis=dict(title='the x-axis', range=[0,100]), # give the x axis a title and a range that it must adhere to
                   yaxis=dict(title='the y-axis'), # give the y axis a title
                   height=300, width=800) # force a plot shape (300 x 800)
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)
fig<jupyter_output><empty_output><jupyter_text>Subplots - plotly toolsFor more information, see https://plot.ly/python/subplots/<jupyter_code>from plotly import tools # the tools module lets us do subplotting
trace1 = go.Scatter(x=[0, 1, 3], y=[0, 1, 5], name='top line')
trace2 = go.Scatter(x=[0, 1, 3], y=[4, 3, 2], name='bottom line')

# create the subplots
fig = tools.make_subplots(rows=2, cols=1, subplot_titles=('Top figure', 'Bottom figure'))

# assign traces to the specific plots
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 2, 1)

layout = dict(title='Multiple Subplots', 
              xaxis=dict(range=[0,4], 
                         title='x-axis')
             )
fig['layout'].update(layout)

pltly.iplot(fig)<jupyter_output><empty_output><jupyter_text>Sharing Axes<jupyter_code>trace1 = go.Scatter(x=[0, 1, 3], y=[0, 1, 5], name='top line')
trace2 = go.Scatter(x=[0, 1, 3], y=[4, 3, 2], name='bottom line')

fig = tools.make_subplots(rows=2, cols=1, 
                          subplot_titles=('Top figure', 'Bottom figure'), 
                          shared_xaxes=True, # here we force a shared axis
                          vertical_spacing=0.3)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 2, 1) # second row is below first row

layout = dict(title='Multiple Subplots', 
              xaxis=dict(range=[0, 4], 
                         title='shared x-axis')
             )
fig['layout'].update(layout)

pltly.iplot(fig)
fig<jupyter_output><empty_output><jupyter_text>Subplots - Layout method<jupyter_code># I prefer to explicitly set the subplots, rather than using `plotly.tools`. 
# This gives a bit more flexibility, in general

trace1 = go.Scatter(x=[0, 1, 3], y=[0, 1, 5], name='top line', xaxis='x2', yaxis='y2')
trace2 = go.Scatter(x=[0, 1, 3], y=[4, 3, 2], name='bottom line', xaxis='x1', yaxis='y1')

layout = dict(title='Multiple Subplots',
              xaxis1=dict(range=[0,4], 
                          title='x-axis 1'), 
              xaxis2=dict(anchor='y2', # anchor = the axis to which this axis aligns zero
                          range=[0,4], 
                          title='x-axis 2'), 
              yaxis1=dict(domain=[0,0.4], # domain = the part of the plot that the axis will fill (0 to 1 range)
                          range=[0,5], 
                          title='y-axis 1'), 
              yaxis2=dict(domain=[0.6,1], # giving a 20% vertical spacing between the two y axes (0.4 vs 0.6)
                          range=[0,6], 
                          title='y-axis 2')
                      
             )

fig = go.Figure(data=[trace1, trace2], layout=layout)

pltly.iplot(fig)<jupyter_output><empty_output><jupyter_text>Sharing Axes<jupyter_code>trace1 = go.Scatter(x=[0, 1, 3], y=[0, 1, 5], name='top line', xaxis='x1', yaxis='y2') # xaxis = 'x1' in both
trace2 = go.Scatter(x=[0, 1, 3], y=[4, 3, 2], name='bottom line', xaxis='x1', yaxis='y1') # but yaxis is different

layout = dict(title='Multiple Subplots',
              xaxis1=dict(anchor='y1',
                          range=[0,4], 
                          title='x-axis 1'),
              yaxis1=dict(domain=[0,0.4],
                          range=[0,5], 
                          title='y-axis 1'), 
              yaxis2=dict(domain=[0.6,1],
                          range=[0,6], 
                          title='y-axis 2')
                      
             )

fig = go.Figure(data=[trace1, trace2], layout=layout)

pltly.iplot(fig)
trace1 = go.Scatter(x=[0, 1, 3], y=[0, 1, 5], name='Line 1', xaxis='x1', yaxis='y2')
trace2 = go.Scatter(x=[0, 1, 3], y=[4, 3, 2], name='Line 2', xaxis='x1', yaxis='y1')
trace3 = go.Scatter(x=[0, 2, 3], y=[0, 2, 5], name='Line 3', xaxis='x2', yaxis='y2')
trace4 = go.Scatter(x=[0, 0.5, 3.5], y=[5, 3, 1], name='Line 4', xaxis='x2', yaxis='y1')

layout = dict(title='Even more Subplots',
              xaxis1=dict(domain=[0,0.49], # left
                          anchor='y1',
                          range=[0,4], 
                          title='x-axis 1'),
              xaxis2=dict(domain=[0.51,1], # right
                          anchor='y1',
                          range=[0,4], 
                          title='x-axis 1'),
              yaxis1=dict(domain=[0,0.4], # bottom
                          range=[0,6], 
                          title='y-axis 1'), 
              yaxis2=dict(domain=[0.6,1], # top
                          range=[0,6], 
                          title='y-axis 2')
                      
             )

fig = go.Figure(data=[trace1, trace2, trace3, trace4], layout=layout)

pltly.iplot(fig)<jupyter_output><empty_output><jupyter_text>Exercise: basicsTry to plot the below image using the available data.Solution is available [here](Exercise-solutions)<jupyter_code>ldc = [1, 0.8, 0.75, 0.7, 0.65, 0.64, 0.63, 0.62, 0.61, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1]
coal = [0.43] * len(ldc)
x_values = np.linspace(0, 8760, num=len(ldc))<jupyter_output><empty_output><jupyter_text>Using Pandas<jupyter_code>data = [go.Scatter(x=de_solar.resample('7D').mean().index,
                   y=de_solar.resample('7D').mean().values)]
layout = dict(height=400, width = 800)
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)
trace_week = go.Scatter(x=de_solar.resample('7D').mean().index,
                        y=de_solar.resample('7D').mean().values,
                        name='weekly')
trace_month = go.Scatter(x=de_solar.resample('1M').mean().index,
                         y=de_solar.resample('1M').mean().values,
                         mode='markers', 
                         marker=dict(symbol='line-ew-open', color='orange', size=5), # symbol names given in API reference
                         name='monthly')
layout = dict(height=400, width = 800)
fig = go.Figure(data=[trace_week, trace_month], layout=layout)
pltly.iplot(fig)
trace_week = go.Scatter(x=de_solar.resample('7D').mean().index,
                        y=de_solar.resample('7D').mean().values,
                        name='weekly')
trace_month = go.Bar(x=de_solar.resample('1M').mean().index,
                     y=de_solar.resample('1M').mean().values,
                     marker=dict(color='orange'), # symbol names given in API reference
                     text=[str(i).split('-')[0] + '-' + str(i).split('-')[1] for i in de_solar.resample('1M').mean().index],
                     name='monthly')
layout = dict(height=400, width = 800)
fig = go.Figure(data=[trace_week, trace_month], layout=layout)
pltly.iplot(fig)
df_wind = df.loc[:, [
    'CZ_wind_onshore_generation',
    'DK_wind_offshore_generation',
    'DK_wind_onshore_generation',
    'SE_wind_generation'
]]

df_wind = df_wind.rename(columns={
    k: k.replace('_wind_', ' ').replace('generation', '') for k in df_wind.columns
})

data = [] # initialise the data list

# Iterate over the columns, adding each scatter to our data list
for column in df_wind.columns:
    data.append(go.Scatter(x=df_wind.resample('1M').mean()[column].loc['2012':'2015-06'].index,
                       y=df_wind.resample('1M').mean()[column].loc['2012':'2015-06'].values,
                       name=column))
layout = dict(height=400, width = 800)
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)<jupyter_output><empty_output><jupyter_text>Using cufflinks<jupyter_code>import cufflinks as cf
cf.set_config_file(offline=True, world_readable=True, theme='white')
# notice that we don't need to iterate over the columns with cufflinks
df_wind.resample('1M').mean().loc['2012':'2015-06'].iplot(kind='scatter') 
layout = cf.Layout(xaxis=dict(showgrid=False),yaxis=dict(showgrid=False))
df_wind.resample('12M').mean().loc['2012':].iplot(kind='barh', 
                                                  barmode='stack', 
                                                  layout_update=layout)<jupyter_output><empty_output><jupyter_text>ColourmapsFor more information, see https://plot.ly/pandas/colorlover/<jupyter_code>import colorlover as cl
colormap = cl.scales[str(len(df_wind.columns))]['seq']['Blues']
df_wind.resample('1M').mean().loc['2012':'2015-06'].iplot(kind='scatter', colors=colormap)<jupyter_output><empty_output><jupyter_text>Interactivity<jupyter_code># - Use `legendgroup` to group datasets, they will turn on/off together when legend entries are clicked - #
data = []

for column in df_wind.columns:
    if 'DK' in column:
        group = 'DK'
    else:
        group = column
    data.append(go.Scatter(x=df_wind.resample('1M').mean()[column].loc['2012':'2015-06'].index,
                           y=df_wind.resample('1M').mean()[column].loc['2012':'2015-06'].values,
                           name=column,
                           legendgroup=group))
layout = dict(height=400, width = 800)
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)
# - Use `hoverinfo` to change the information given on hovering over the data - #
data = []
df_wind_monthly = df_wind.resample('1M').mean().loc['2012':'2015-06']
for column in df_wind.columns:
    data.append(go.Scatter(x=df_wind_monthly[column].index,
                           y=df_wind_monthly[column].values,
                           text=np.round(df_wind_monthly[column].values,0),
                           name=column,
                           hoverinfo='x+text'))
layout = dict(height=400, width = 800)
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)
# - Use `rangeslider` to have a full timeseries outline below the main figure, 
# which is useful if you zoom in on your data by slicing the time domain

data = []

for column in df_wind.columns:
    data.append(
        go.Scatter(
            x=df_wind.resample('1D').mean()[column].loc['2012':'2015-06'].index,
            y=df_wind.resample('1D').mean()[column].loc['2012':'2015-06'].values,
            name=column,
        )
    )
layout = {
    'height': 400, 'width': 800, 
    'xaxis': {'range': ['2014-01', '2014-02'], 'rangeslider': {}}
}
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)<jupyter_output><empty_output><jupyter_text>Exercise 2 Your task: visualise the monthly and annual means from the df_wind data from above, using subplots and connected layout.* You want to resample the data, e.g. with df_wind.resample('12M').mean()* As with go.Scatter(), you can plot bar charts with go.Bar()* Bars can be stacked by editing the layout function to include `barmode='stack'` * Try cufflinks and pure plotly to test their strengths and weaknessesSolution is available [here](Exercise-solutions)    Your output might look something like:  Adding sliders<jupyter_code># use buttons to create a dropdown of data
# data_len is used to populate visibility of traces, for dropdown

# sliders, dropdowns, buttons, etc. all work by preparing every single
# dataset as we would if we plotted them seperately. Then, we add a
# layer to switch on/off the visibility of these different datasets.

# In this example we will be switching on/off 4 scatter plots at a time,
# which correspond to the 4 data columns. We will be switching between 
# time frequencies, to see the effect of time resolution.
def get_x_y(freq, column):
    x = df_wind.resample(freq).mean().index,
    y = df_wind.resample(freq).mean()[column].values
    
    return x, y


data = []
# only data from the first frequency will be visible by default, we switch this to False after
visible = True
steps = []
num_columns = len(df_wind.columns)
freqs = ['1H', '1D', '7D', '1M', '1Y']

visible_data = [False] * len(freqs) * num_columns

i = 0
for freq in freqs:
    for column in df_wind.columns:
        x, y = get_x_y(freq, column)
        # It might be better to view annual mean as a Bar, not scatter
        plotter = go.Bar if freq == '1Y' else go.Scatter
        data.append(plotter(x=x[0], y=y, name=column, visible=visible))
        
    # Only the plots associated with the first frequency have visible=True
    visible=False
    
    step = {
        'method': 'restyle', 'label': freq, 'args': ['visible', visible_data.copy()]
    }
    # Set the plots associated with this step as visible=True
    step['args'][1][i * num_columns:(i + 1) * num_columns] = [True] * num_columns
    steps.append(step)
    i += 1

# Put the slider above the main plot (y = 1.5)
sliders = [{
    'x': 0, 'y': 1.5,
    'steps': steps
}]

layout = {'sliders': sliders, 'xaxis': {'rangeslider': {}}}

pltly.iplot({'data': data, 'layout': layout})<jupyter_output><empty_output><jupyter_text>Plotting on maps<jupyter_code>df_map = pd.read_csv('./data/conventional_power_plants_EU.csv')
df_map = df_map.dropna(subset=['lat', 'lon'])
data = []
opacity = (df_map.capacity/df_map.capacity.max())/3 + 0.66
text = df_map.energy_source + ' ' + df_map.capacity.astype(str) + 'MW' + ' ' + df_map.country
colors = cl.scales['4']['qual']['Pastel1']
energy_sources = set(df_map.energy_source_level_1)
for source in energy_sources:
    color = colors[list(energy_sources).index(source)]
    data.append(
        dict(
            type='scattergeo',
            lon=df_map.loc[df_map.energy_source_level_1==source].lon,
            lat=df_map.loc[df_map.energy_source_level_1==source].lat,
            text= text.loc[df_map.energy_source_level_1==source],
            hoverinfo='text',
            name=source,
            mode='marker',
            marker=dict(
                opacity=opacity.loc[df_map.energy_source_level_1==source], 
                color=color,
                size=5, 
                line=dict(width=1, color='black')
            )
        )
    )
layout=dict(geo=dict(resolution=50,
                     scope='europe',
                     projection=dict(type='mercator'),
                     showocean=True,
                     oceancolor='rgb(151,182,225)',
                     showcoastlines=True,
                     coastlinecolor='red'))
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)
# minor edits required to plot over a Mapbox base map. 
mapbox_access_token = '' # If you have a mapbox token (free from mapbox.com) then place it here.
if mapbox_access_token:
    for i in range(len(energy_sources)):
        data[i]['type'] = 'scattermapbox'
        # delete the marker 'line' attribute, as scattermapbox doesn't support it 
        data[i]['marker'].pop('line', {})
    layout = dict(
        mapbox=dict(
            accesstoken=mapbox_access_token, 
            style='satellite-streets',
            center=dict(
                lat=df_map.lat.mean(),
                lon=df_map.lon.mean()
            )
        )
    )
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)<jupyter_output><empty_output><jupyter_text>Exercise solutions  Exercise 1<jupyter_code>data = [
    go.Scatter(x=x_values, y=ldc, name='Load duration curve', line=dict(color='blue'), mode='lines'),
    go.Scatter(x=x_values, y=coal, name='Coal generation', line=dict(color='orange'), mode='lines')
]
layout = go.Layout(
    yaxis=dict(title='Capacity Requirement', range=(0, 1)),
    xaxis=dict(title='Hours per year', showgrid=False, range=(0, 8760))
)
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)<jupyter_output><empty_output><jupyter_text>Exercise 2<jupyter_code>data = []
colors = cl.scales[str(len(df_wind.columns))]['div']['Spectral']
# or perhaps colors = sns.color_palette('bright', len(df_wind.columns)).as_hex()
color_index = 0
for column in df_wind.columns:
    data.append(go.Scatter(x=df_wind.resample('1M').mean()[column].loc['2012':'2016'].index,
                           y=df_wind.resample('1M').mean()[column].loc['2012':'2016'].values,
                           name=column,
                           xaxis='x1',
                           yaxis='y1',
                           line=dict(color=colors[color_index]),
                           legendgroup=column))
    data.append(go.Bar(x=df_wind.resample('12M').sum()[column].loc['2012':'2016'].index,
                       y=df_wind.resample('12M').sum()[column].loc['2012':'2016'].values,
                       name=column,
                       xaxis='x2',
                       yaxis='y2',
                       marker=dict(color=colors[color_index]),
                       showlegend=False,
                       legendgroup=column,
                       text=['%.2E' % i for i in df_wind.resample('12M').sum()[column].loc['2012':'2016'].values],
                       hoverinfo='text'))
    color_index += 1
layout = dict(barmode='stack', height=400, width=800,
              xaxis1=dict(domain=[0,0.49], title='Monthly variation'),
              xaxis2=dict(domain=[0.51,1], title='Annual variation'),
              yaxis1=dict(range=[0,3500]),
              yaxis2=dict(anchor='x2', range=[0, 35e6], side='right'),
              legend=dict(orientation='h', xanchor='center',yanchor='bottom', x=0.5, y=1))
fig = go.Figure(data=data, layout=layout)
pltly.iplot(fig)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15285061342314168, 'fraction_numerical': 0.032860235746932885, 'mean_word_length': 2.8216583930869645, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 73, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '336790', 'license': 'MIT', 'n_tokens_mistral': 7359, 'n_tokens_neox': 6797, 'n_words': 1494, 'path': 'Tutorial.ipynb', 'repo_name': 'brynpickering/plotly-tutorial', 'size': '20785'}