creating a Piechart in Plotly/Dash out of a Dataframe/Pivot Table - python

This is my code, as a quick explanation I am filtering my dataframe to select the correct KPI, in this case Operator Share, the correct country, which is prestored in the variable country and the year 2017.
Then I want to create a piechart that uses the KPIvalues of the different specifications. So Specifications should be the labels and KPI values the values.
df_plot_operator_share = df[df['Country'] == Country]
df_plot_operator_share = df.loc[(df['KPIname'].isin(['OperatorShare'])) & (df['YearNb']==2017)]
pv_operator_share = pd.pivot_table(
df_plot_operator_share,
index=['Specification'],
values=['KPIvalue'],
aggfunc=sum,
fill_value=0)
trace1 = go.Pie(
lables= pv_operator_share.index, values= pv_operator_share["KPIvalue"],
name='OperatorShare')
return {
'data': [trace1],
'layout':
go.Layout(
title='Country: {} Operator Share'.format(Country),
)
}
The Pivot has the Specifications has the headers and the KPIvalues as its values.
I want to have a pie chart that uses the Specifications as labels and the KPIvalues as values.
But for some reason it is not working.

You tried to call plotly?
For example:
import plotly
import plotly.plotly as py
import plotly.graph_objs as go
trace1 = go.Pie(
labels = pv_operator_share.index,
values= pv_operator_share["KPIvalue"],
name='OperatorShare'
)
data = [trace1]
layout = go.Layout(
title='Country: {} Operator Share'.format(Country),
)
fig = go.Figure(data=data, layout=layout)
plotly.offline.plot(fig, filename='Plot.html')

import plotly.express as px
fig = px.pie(df, values='numeric_value', names='column_name', title='Your title')
fig.show()

Related

Python Plotly display other information on Hover

Here is the code that I have tried:
# import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
df = pd.read_csv("resultant_data.txt", index_col = 0, sep = ",")
display=df[["Velocity", "WinLoss"]]
pos = lambda col : col[col > 0].sum()
neg = lambda col : col[col < 0].sum()
Related_Display_Info = df.groupby("RacerCount").agg(Counts=("Velocity","count"),
WinLoss=("WinLoss","sum"),
Positives=("WinLoss", pos),
Negatives=("WinLoss", neg),
)
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])
# Add traces
fig.add_trace(
go.Scatter(x=display.index, y=display["Velocity"], name="Velocity", mode="markers"),
secondary_y=False
)
fig.add_trace(
go.Scatter(x=Related_Display_Info.index,
y=Related_Display_Info["WinLoss"],
name="Win/Loss",
mode="markers",
marker=dict(
color=(
(Related_Display_Info["WinLoss"] < 0)
).astype('int'),
colorscale=[[0, 'green'], [1, 'red']]
)
),
secondary_y=True,
)
# Add figure title
fig.update_layout(
title_text="Race Analysis"
)
# Set x-axis title
fig.update_xaxes(title_text="<b>Racer Counts</b>")
# Set y-axes titles
fig.update_yaxes(title_text="<b>Velocity</b>", secondary_y=False)
fig.update_yaxes(title_text="<b>Win/Loss/b>", secondary_y=True)
fig.update_layout(hovermode="x unified")
fig.show()
The output is:
But I was willing to display the following information when I hover on the point:
RaceCount = From Display dataframe value Number of the race corresponding to the dot I hover on.
Velocity = From Display Dataframe value Velocity at that point
Counts = From Related_Display_Info Column
WinLoss = From Related_Display_Info Column
Positives = From Related_Display_Info Column
Negatives = From Related_Display_Info Column
Please can anyone tell me what to do to get this information on my chart?
I have checked this but was not helpful since I got many errors: Python/Plotly: How to customize hover-template on with what information to show?
Data:
RacerCount,Velocity,WinLoss
111,0.36,1
141,0.31,1
156,0.3,1
141,0.23,1
147,0.23,1
156,0.22,1
165,0.2,1
174,0.18,1
177,0.18,1
183,0.18,1
114,0.32,1
117,0.3,1
120,0.29,1
123,0.29,1
126,0.28,1
129,0.27,1
120,0.32,1
144,0.3,1
147,0.3,1
159,0.27,1
165,0.26,1
168,0.25,1
156,0.29,1
165,0.26,1
168,0.26,1
165,0.28,1
213,0.17,1
243,0.15,1
249,0.14,1
228,0.54,1
177,0.67,1
180,0.66,1
183,0.65,1
192,0.66,1
195,0.62,1
198,0.6,1
180,0.66,1
222,0.56,1
114,0.41,1
81,0.82,1
102,0.56,1
111,0.55,1
90,1.02,1
93,1.0,1
90,1.18,1
90,1.18,1
93,1.1,1
96,1.07,1
99,1.04,1
102,0.99,1
105,0.94,1
108,0.92,1
111,0.9,1
162,0.66,1
159,0.63,1
162,0.65,-1
162,0.66,-1
168,0.64,-1
159,0.68,-1
162,0.67,-1
174,0.62,-1
168,0.65,-1
171,0.64,-1
198,0.55,-1
300,0.47,-1
201,0.56,-1
174,0.63,-1
180,0.61,-1
171,0.64,-1
174,0.62,-1
303,0.47,-1
312,0.48,-1
258,0.51,-1
261,0.51,-1
264,0.5,-1
279,0.47,-1
288,0.48,-1
294,0.47,-1
258,0.52,-1
261,0.51,-1
267,0.5,-1
222,0.53,-1
171,0.64,-1
177,0.63,-1
177,0.63,-1
Essentially, this code ungroups the data frame before plotting to create the hovertemplate you're looking for.
As stated in the comments, the data has to have the same number of rows to be shown in the hovertemplate. At the end of my answer, I added the code all in one chunk.
Since you have hovermode as x unified, you probably only want one of these traces to have hover content.
I slightly modified the creation of Related_Display_Info. Instead of WinLoss, which is already in the parent data frame, I modified it to WinLoss_sum, so there wouldn't be a naming conflict when I ungrouped.
Related_Display_Info = df.groupby("RacerCount").agg(
Counts=("Velocity","count"), WinLoss_sum=("WinLoss","sum"),
Positives=("WinLoss", pos), Negatives=("WinLoss", neg))
Now it's time to ungroup the data you grouped. I created dui (stands for display info ungrouped).
dui = pd.merge(df, Related_Display_Info, how = "outer", on="RacerCount",
suffixes=(False, False))
I created the hovertemplate for both traces. I passed the entire ungrouped data frame to customdata. It looks like the only column that isn't in the template is the original WinLoss.
# create hover template for all traces
ht="<br>".join(["<br>RacerCount: %{customdata[0]}",
"Velocity: %{customdata[1]:.2f}",
"Counts: %{customdata[3]}",
"Winloss: %{customdata[4]}",
"Positives: %{customdata[5]}",
"Negatives: %{customdata[6]}<br>"])
The creation of fig is unchanged. However, the traces are both based on dui. Additionally, the index isn't RacerCount, so I used the literal field instead.
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])
# Add traces
fig.add_trace(go.Scatter(x=dui["RacerCount"], y=dui["Velocity"],
name="Velocity", mode="markers",
customdata=dui, hovertemplate=ht),
secondary_y=False)
fig.add_trace(
go.Scatter(x = dui["RacerCount"], y=dui["WinLoss_sum"], customdata=dui,
name="Win/Loss", mode="markers",
marker=dict(color=((dui["WinLoss_sum"] < 0)).astype('int'),
colorscale=[[0, 'green'], [1, 'red']]),
hovertemplate=ht),
secondary_y=True)
All the code altogether (for easier copy + paste)
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
df = pd.read_clipboard(sep = ',')
display=df[["Velocity", "WinLoss"]]
pos = lambda col : col[col > 0].sum()
neg = lambda col : col[col < 0].sum()
Related_Display_Info = df.groupby("RacerCount").agg(
Counts=("Velocity","count"), WinLoss_sum=("WinLoss","sum"),
Positives=("WinLoss", pos), Negatives=("WinLoss", neg))
# ungroup the data for the hovertemplate
dui = pd.merge(df, Related_Display_Info, how = "outer", on="RacerCount",
suffixes=(False, False))
# create hover template for all traces
ht="<br>".join(["<br>RacerCount: %{customdata[0]}",
"Velocity: %{customdata[1]:.2f}",
"Counts: %{customdata[3]}",
"Winloss: %{customdata[4]}",
"Positives: %{customdata[5]}",
"Negatives: %{customdata[6]}<br>"])
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])
# Add traces
fig.add_trace(go.Scatter(x=dui["RacerCount"], y=dui["Velocity"],
name="Velocity", mode="markers",
customdata=dui, hovertemplate=ht),
secondary_y=False)
fig.add_trace(
go.Scatter(x = dui["RacerCount"], y=dui["WinLoss_sum"], customdata=dui,
name="Win/Loss", mode="markers",
marker=dict(color=((dui["WinLoss_sum"] < 0)).astype('int'),
colorscale=[[0, 'green'], [1, 'red']]),
hovertemplate=ht),
secondary_y=True)
# Add figure title
fig.update_layout(
title_text="Race Analysis"
)
# Set x-axis title
fig.update_xaxes(title_text="<b>Racer Counts</b>")
# Set y-axes titles
fig.update_yaxes(title_text="<b>Velocity</b>", secondary_y=False)
fig.update_yaxes(title_text="<b>Win/Loss/b>", secondary_y=True)
fig.update_layout(hovermode="x unified")
fig.show()

How to add labels to plotly Box chart like Scatter chart?

I couldn't find the way to add text labels to plotly/dash box plot like you could add it to a scatterplot. In the example below, for ScatterPlot x=qty, y=price and you can then add Salesperson to the graph when the cursor is on Marker. For adding this I use the 'text' argument.
In the second example for BoxPlot when x=date, y=price I want to add salesperson in the same way. It would be very useful in case of outliers to see immediately who was the salesperson for that purchase. I looked in the documentation, but there is no clue. I assume it's not possible but still decided to try my luck here.
scatterplot:
import plotly.offline as pyo
import plotly.graph_objs as go
purchase={'date':['11/03/2021','12/03/2021','14/03/2021','11/03/2021'],
'price':[300, 400,200, 200],
'currency':['eur', 'usd','usd','usd'],
'qty':[200, 300, 400, 500],
'salesman':['AC', 'BC', "CC", 'DC']}
pur=pd.DataFrame(purchase)
pur
data = [go.Scatter(
x = pur['qty'],
y = pur['price'],
mode = 'markers',
text=pur['salesman'],
marker = dict(
size = 12,
color = 'rgb(51,204,153)',
symbol = 'pentagon',
line = dict(
width = 2,
)
)
)]
layout = go.Layout(
title = 'Random Data Scatterplot',
xaxis = dict(title = 'Some random x-values'),
yaxis = dict(title = 'Some random y-values'),
hovermode ='closest'
)
fig = go.Figure(data=data, layout=layout)
fig.show()
boxplot:
import plotly.offline as pyo
import plotly.graph_objs as go
x = pur['date']
y = pur['price']
data = [
go.Box(
y=y,
x=x,
text=pur['salesman']
)
]
layout = go.Layout(
title = 'box_plot'
)
fig = go.Figure(data=data, layout=layout)
fig.show()
The data you currently have is not suitable for boxplot. If you try to plot a boxplot with your data, the list [300, 400,200, 200] is used only once for the first date. For the other dates, there is no data.
I will show a simpler example with my own data.
dataset.csv
salesman,sales
alan,1.8
bary,2.3
copa,4.2
dac,1.19
eila,2.3
foo,2.5
gary,0.1
holland,10
code
import plotly.graph_objs as go
import pandas as pd
import plotly.io as pio
pio.renderers.default = 'browser'
df = pd.read_csv("deletelater")
fig = go.Figure()
fig.add_trace(go.Box(
y=df["sales"],
name='12/12/22',
customdata=df["salesman"],
hovertemplate='<b>sales: %{y}</b><br>salesperson: %{customdata}'
))
fig.show()
Diagram
As you can see, the name of the outlier salesperson is displayed on the hover label.

How to get standard notation (rather than scientific) when hovering over pie chart in Plotly

I have a pie chart that displays worldwide movie sales by rating. When I hover over the chart the woldwide sales are being displayed in scientific notation. How do I fix this so that worldwide sales are represented in standard notation instead? I would appreciate it if anyone has a solution to this in express or graph objects (or both).
Thank you.
# formatting and importing data
import pandas as pd
movie_dataframe = pd.read_csv("https://raw.githubusercontent.com/NicholasTuttle/public_datasets/main/movie_data.csv") # importing dataset to dataframe
movie_dataframe['worldwide_gross'] = movie_dataframe['worldwide_gross'].str.replace(',', '', regex=True) # removing commas from column
movie_dataframe['worldwide_gross'] = movie_dataframe['worldwide_gross'].str.replace('$', '' , regex=True ) # removing dollar signs from column
movie_dataframe['worldwide_gross'] = movie_dataframe['worldwide_gross'].astype(float)
# narrowing dataframe to specific columns
movies_df = movie_dataframe.loc[:, ['title', 'worldwide_gross', 'rating', 'rt_score', 'rt_freshness']]
# plotly express
import plotly.express as px
fig = px.pie(movies_df,
values= movies_df['worldwide_gross'],
names= movies_df['rating'],
)
fig.show()
# plotly graph objects
import plotly.graph_objects as go
fig = go.Figure(go.Pie(
values = movies_df['worldwide_gross'],
labels = movies_df['rating']
))
fig.show()
Have a look here: https://plotly.com/python/hover-text-and-formatting/#disabling-or-customizing-hover-of-columns-in-plotly-express
Basically you give a dictionary of row name and format string to hover_data. The formatting string follows the d3-format's syntax.
import plotly.express as px
fig = px.pie(
movies_df, values= movies_df['worldwide_gross'], names= movies_df['rating'],
hover_data={
"worldwide_gross": ':.d',
# "worldwide_gross": ':.2f', # float
}
)
fig.show()
For the graph object API you need to write an hover_template:
https://plotly.com/python/reference/pie/#pie-hovertemplate
import plotly.graph_objects as go
fig = go.Figure(go.Pie(
values = movies_df['worldwide_gross'],
labels = movies_df['rating'],
hovertemplate='Rating: %{label}<br />World wide gross: %{value:d}<extra></extra>'
))
fig.show()

Plotly: How to add elements to hover_data using plotly.express piechart?

I am playing with examples from plotly.express piechart help page and trying to add an extra element iso_num to the hover_data property (iso_num is an int64 column in the gapminder dataframe)
import plotly.express as px
df = px.data.gapminder().query("year == 2007").query("continent == 'Americas'")
fig = px.pie(df, values='pop', names='country',
title='Population of American continent',
hover_data=['lifeExp','iso_num'], labels={'lifeExp':'life expectancy','iso_num':'iso num'
})
fig.update_traces(textposition='inside', textinfo='percent+label')
fig.show()
Hovering over the slice of the pie chart then gives this:
where iso num value is %{customdata[1]} instead of the numeric value from the column.
What am I missing?
Thanks!
I found a way to do it with Plotly Express Pie chart as well. You can use update_traces to define hover_template. It seems there is an issue with splitting on multiple values for hover_data/custom_data and all values are present at 0 index only i.e. both values are at customdata[0].
import plotly.express as px
df = px.data.gapminder().query("year == 2007").query("continent == 'Americas'")
fig = px.pie(df, values='pop', names='country',
title='Population of American continent',
custom_data=['lifeExp','iso_num'], labels={'lifeExp':'life expectancy','iso_num':'iso num'
})
fig.update_traces(textposition='inside', textinfo='percent+label',\
hovertemplate = "Country:%{label}: <br>Population: %{value} </br>(life expentancy, iso num) : %{customdata}"
)
fig.show()
On hover:
This seems to be a relic from back when it was stated that
Oh pie hover is a big mess
Which since seems to be have been resolved. But perhaps not for px.pie()?
I've tried numerous approaches, but I'm only able to get the customdata + hovertemplate approach to work for go.Pie and not for px.Pie. Here's a demonstration on how assigning values to customdata will make any variable otherwise not assigned to go.Pie() available for a custom hovertamplate:
Plot:
Code:
import plotly.graph_objects as go
import plotly.express as px
df = px.data.gapminder().query("year == 2007").query("continent == 'Americas'")
fig = go.Figure(go.Pie(
name = "",
values = df['pop'],
labels = df['country'],
customdata=df['iso_num'],
hovertemplate = "Country:%{label}: <br>Population: %{value} </br> iso num:%{customdata}"
))
fig.show()

Set up multiple subplots with moving averages using cufflinks and plotly offline

Im trying to select 4 different product prices from my dataframe and plot their moving average as a subplot (2,2) using plotly cufflinks. I would appreciate if anyone can guide on this.
I tried plotting the price as below.
I came across cufflinks technical analysis which allow me to plot moving average in a cleaner way, however, im not too sure how to apply it yet.
from plotly.offline import download_plotlyjs,init_notebook_mode,plot,iplot
from plotly import tools
import plotly.graph_objs as go
trace1= go.Scatter(name=',milk', x=df.Date, y=df['milk'])
trace2= go.Scatter(name='soap', x=df.Date, y=df['soap'])
trace3= go.Scatter(name='rice', x=df.Date, y=df['rice'])
trace4= go.Scatter(name='water', x=df.Date, y=df['water'])
fig = tools.make_subplots(rows=2, cols=2, subplot_titles=('milk', 'soap',
'rice', 'water'))
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
fig.append_trace(trace3, 2, 1)
fig.append_trace(trace4, 2, 2)
fig['layout'].update(height=1000, width=1800, title='supermarket')
plot(fig, filename='supermarket.html')
I would appreciate if someone could teach me how to use plotly cufflinks to plot four moving averages from the selected columns from a dataframe using plotly offline.
Insert the code section below in a Jupyter Notebook to produce the following plot using cufflinks and plotly offline:
Plot:
Code:
# imports
import plotly
from plotly import tools
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import pandas as pd
import numpy as np
from IPython.core.display import display, HTML
import copy
import plotly.graph_objs as go
####### PART 1 - SETUP AND SAMPLE DATA #######
# setup
display(HTML("<style>.container { width:55% !important; } .widget-select > select {background-color: gainsboro;}</style>"))
init_notebook_mode(connected=True)
np.random.seed(123)
cf.set_config_file(theme='pearl')
# Random data using cufflinks
df = cf.datagen.lines().iloc[:,0:4]
df.columns = ['StockA', 'StockB', 'StockC', 'StockD']
####### PART 2 - FUNCTION FOR MOVING AVERAGES #######
# Function for moving averages
def movingAvg(df, win, keepSource):
"""Add moving averages for all columns in a dataframe.
Arguments:
df -- pandas dataframe
win -- length of movingAvg estimation window
keepSource -- True or False for keep or drop source data in output dataframe
"""
df_temp = df.copy()
# Manage existing column names
colNames = list(df_temp.columns.values).copy()
removeNames = colNames.copy()
i = 0
for col in colNames:
# Make new names for movingAvgs
movingAvgName = colNames[i] + '_MA' #+ str(win)
# Add movingAvgs
df_temp[movingAvgName] = df[col].rolling(window=win).mean()
i = i + 1
# Remove estimates with insufficient window length
df_temp = df_temp.iloc[win:]
# Remove or keep source data
if keepSource == False:
df_temp = df_temp.drop(removeNames,1)
return df_temp
# Add moving averages to df
windowLength = 10
df = movingAvg(df=df, win=windowLength, keepSource = True)
####### PART 3 -PLOTLY RULES #######
# Structure lines / traces for the plots
# trace 1
trace1 = go.Scatter(
x=df.index,
y=df['StockA'],
name='StockA'
)
trace1_ma = go.Scatter(
x=df.index,
y=df['StockA_MA'],
name='StockA_MA'
)
# trace 2
trace2 = go.Scatter(
x=df.index,
y=df['StockB'],
name='StockB'
)
trace2_ma = go.Scatter(
x=df.index,
y=df['StockB_MA'],
name='StockB_MA'
)
# trace 3
trace3 = go.Scatter(
x=df.index,
y=df['StockC'],
name='StockC'
)
trace3_ma = go.Scatter(
x=df.index,
y=df['StockC_MA'],
name='StockC_MA'
)
# trace 4
trace4 = go.Scatter(
x=df.index,
y=df['StockD'],
name='StockD'
)
trace4_ma = go.Scatter(
x=df.index,
y=df['StockD_MA'],
name='StockD_MA'
)
# Structure traces as datasets
data1 = [trace1, trace1_ma]
data2 = [trace2, trace2_ma]
data3 = [trace3, trace3_ma]
data4 = [trace4, trace4_ma]
# Build figures
fig1 = go.Figure(data=data1)
fig2 = go.Figure(data=data2)
fig3 = go.Figure(data=data3)
fig4 = go.Figure(data=data4)
# Subplots setup and layout
figs = cf.subplots([fig1, fig2, fig3, fig4],shape=(2,2))
figs['layout'].update(height=800, width=1200,
title='Stocks with moving averages = '+ str(windowLength))
iplot(figs)

Categories