Is there any way to show gray color to states which are not having any data in Plotly map? - matplotlib

I need to show gray color to the states which do not have any data in Plotly.
Sample csv file is: (This states have data)
States which are not having data are: (I have filled the missing values as -1
The current plots generated are: ( I need to show gray color to the states with missing data.
Thanks!

Your solution is to use custom colorscale in combination with
import plotly.express as px
px.choropleth_mapbox
The following is an example on how to use custom colorscale:
import plotly.plotly as py
import plotly.graph_objs as go
import numpy as np
import copy
import pandas as pd
# Read data from a csv
z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv')
z=z_data.values.copy()
# Compute surface color with nan's
surfacecolor = z.copy()
surfacecolor[-10:, -10:] = np.nan
# Replace nans with -100
surfacecolor[np.isnan(surfacecolor)] = -100
# Build surface trace
data = [
go.Surface(
z=z,
surfacecolor=surfacecolor,
cmin = -5,
cmax = 350,
colorscale=[[0, 'gray'],
[0.01, 'gray'],
[0.01, 'blue'],
[1, 'red']]
)
]
# Build layout
layout = go.Layout(
title='Mt Bruno Elevation',
autosize=False,
width=500,
height=500,
margin=dict(
l=65,
r=50,
b=65,
t=90
)
)
fig = go.FigureWidget(data=data, layout=layout)
fig
A similar question has been solved by the plotly community forum.
Please find the plotly documentation on how to define custom colorscales.
Hope this solves your issue!

Related

Add a slider to plotly that dynamically changes a column of data frame that is displayed

Minimal working example:
import pandas as pd
import plotly.express as px
A = [10,20,30,40,50,60]
B = [40,50,60,10,20,30]
data = pd.DataFrame({"A":A,"B":B})
alpha=0.5
data["Parameter"]= alpha*data["A"] +(1-alpha)*data["B"]
fig = px.scatter(
data, x="A",y="B",color="Parameter"
)
fig.show()
I would like to have a slider for alpha in plotly graph. I looked at the documentation but only found a slider for a fixed column with constant values.
fig = px.scatter(data, x="A", y="B", color="Parameter", animation_frame='Parameter')
fig["layout"].pop("updatemenus")
fig.update_xaxes(range=[0, 100])
fig.show('browser')

Pandas Plotly -- Secondary Graph needs to be to RSI

In plotly, I am able to make this graph(Attached picture at the end), with the code below.
(Data is stock market data for 1year, which is in csv format. Please use any OHLC data which has about 200 to 300 rows)
import pandas as pd
import ta
import plotly.graph_objects as go
df = pd.read_csv("Trial.csv")
df["rsi"] = ta.momentum.rsi(df["Close"], window=14, fillna=False)
dfff = df.tail(180)
layoutt = go.Layout(autosize=False, width=4181, height=1597)
fig_001 = go.Figure(data=[go.Candlestick(x=dfff['Date'], open=dfff['Open'], high=dfff['High'], low=dfff['Low'], close=dfff['Close'])], layout=layoutt)
fig_001.write_image("fig_001.jpeg")
As you see in the attached picture below, Plotly is generating 2 charts by default (with a smaller-duplicated chart below)...
About the secondary graph which is enclosed in 'Green', how can I change that to a RSI graph((Which is currently the same candlestick data as in red))?
plotly is not generating two charts. It is one with a range slider (when interactive can use to zoom into xaxis)
have hidden range slider
have created an additional trace and set it to use a second yaxis
have configure yaxes to use domains so it has same visual effect
import pandas as pd
import ta
import plotly.graph_objects as go
# df = pd.read_csv("Trial.csv")
# use plotly OHLC sample data
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv"
)
df = df.rename(columns={c: c.split(".")[1] for c in df.columns if "." in c})
df["rsi"] = ta.momentum.rsi(df["Close"], window=14, fillna=False)
dfff = df.tail(180)
layoutt = go.Layout(autosize=False, width=4181, height=1597)
# make it fit on my screen!!!
layoutt = go.Layout(autosize=True)
layoutt2 = go.Layout(autosize=False, width=6731, height=2571)
fig_001 = go.Figure(
data=[
go.Candlestick(
x=dfff["Date"],
open=dfff["Open"],
high=dfff["High"],
low=dfff["Low"],
close=dfff["Close"],
name="OHLC",
),
go.Scatter(
x=dfff["Date"], y=dfff["rsi"], mode="markers+lines", name="RSI", yaxis="y2"
),
],
layout=layoutt,
).update_layout(
yaxis_domain=[0.3, 1],
yaxis2={"domain": [0, 0.20]},
xaxis_rangeslider_visible=False,
showlegend=False,
)
fig_001

Plotly chart percentage with smileys

I would like o add a plot figure based on smileys like this one:
dat will come from a dataframe pandas : dataframe.value_counts(normalize=True)
Can some one give me some clues.
use colorscale in normal way for a heatmap
use anotation_text to assign an emoji to a value
import plotly.figure_factory as ff
import plotly.graph_objects as go
import pandas as pd
import numpy as np
df = pd.DataFrame([[j*10+i for i in range(10)] for j in range(10)])
e=["😃","🙂","😐","☚ī¸"]
fig = go.Figure(ff.create_annotated_heatmap(
z=df.values, colorscale="rdylgn", reversescale=False,
annotation_text=np.select([df.values>75, df.values>50, df.values>25, df.values>=0], e),
))
fig.update_annotations(font_size=25)
# allows emoji to use background color
fig.update_annotations(opacity=0.7)
update coloured emoji
fundamentally you need emojicons that can accept colour styling
for this I switched to Font Awesome. This then also requires switching to dash, plotly's cousin so that external CSS can be used (to use FA)
then build a dash HTML table applying styling logic for picking emoticon and colour
from jupyter_dash import JupyterDash
import dash_html_components as html
import pandas as pd
import branca.colormap
# Load Data
df = pd.DataFrame([[j*10+i for i in range(10)] for j in range(10)])
external_stylesheets = [{
'href': 'https://use.fontawesome.com/releases/v5.8.1/css/all.css',
'rel': 'stylesheet', 'crossorigin': 'anonymous',
'integrity': 'sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf',
}]
# possibly could use a a different library for this - simple way to map a value to a colormap
cm = branca.colormap.LinearColormap(["red","yellow","green"], vmin=0, vmax=100, caption=None)
def mysmiley(v):
sm = ["far fa-grin", "far fa-smile", "far fa-meh", "far fa-frown"]
return html.Span(className=sm[3-(v//25)], style={"color":cm(v),"font-size": "2em"})
# Build App
app = JupyterDash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Table([html.Tr([html.Td(mysmiley(c)) for c in r]) for r in df.values])
])
# Run app and display result inline in the notebook
app.run_server(mode='inline')

set_xlim() does not work with text labels

I am trying to zoom in on geopandas map with labels using set_xlim() in with matplotlib. I basically adapted this SO question to add labels to a map.
However, set_xlim() does not seem to work and did not zoom in on the given extent. (By the way, I've also tried to use text() instead of annotate(), to no avail.)
What I did was the following:
I used the same US county data as in the question linked above, extracted the files, and then executed the following in Jupyter notebook:
import geopandas as gpd
import matplotlib.pyplot as plt
%matplotlib inline
shpfile='shp/cb_2015_us_county_20m.shp'
gdf=gpd.read_file(shpfile)
gdf.plot()
, which gives a map of all US counties as expected:
Adding labels as with one of the answers also works:
ax = gdf.plot()
gdf.apply(lambda x: ax.annotate(s=x.NAME, xy=x.geometry.centroid.coords[0], ha='center'),axis=1);
However, when trying to zoom in to a particular geographic extent with set_xlim() and set_ylim() as follows:
ax = gdf.plot()
gdf.apply(lambda x: ax.annotate(s=x.NAME, xy=x.geometry.centroid.coords[0], ha='center'),axis=1);
ax.set_xlim(-84.2, -83.4)
ax.set_ylim(42, 42.55)
, the two functions do not seem to work. Instead of zooming in, they just trimmed everything outside of the given extent.
If the labeling code is dropped out (gdf.apply(lambda x: ax.annotate(s=x.NAME, xy=x.geometry.centroid.coords[0], ha='center'),axis=1);, the set_xlim() works as expected:
My question is:
What is the correct way to zoom in to an area when labels are present in a plot?
You need some coordinate transformation.
import cartopy.crs as ccrs
# relevant code follows
# set numbers in degrees of longitude
ax.set_xlim(-84.2, -83.4, ccrs.PlateCarree())
# set numbers in degrees of latitude
ax.set_ylim(42, 42.55, ccrs.PlateCarree())
plt.show()
with the option ccrs.PlateCarree(), the input values are transformed to proper data coordinates.
When I try it, I can't draw on matplotlib with the axes restricted. So it's possible to extract the data.
import geopandas as gpd
import matplotlib.pyplot as plt
%matplotlib inline
fig,ax = plt.subplots(1,1, figsize=(4,4), dpi=144)
shpfile = './cb_2015_us_county_20m/cb_2015_us_county_20m.shp'
gdf = gpd.read_file(shpfile)
# gdf = gdf.loc[gdf['STATEFP'] == '27']
gdf['coords'] = gdf['geometry'].apply(lambda x: x.representative_point().coords[:])
gdf['coords'] = [coords[0] for coords in gdf['coords']]
gdf = (gdf[(gdf['coords'].str[0] >= -84.2) & (gdf['coords'].str[0] <= -83.4)
& (gdf['coords'].str[1] >= 42) & (gdf['coords'].str[1] <= 42.55)])
gdf.plot(ax=ax)
gdf.apply(lambda x: ax.annotate(text=x.NAME, xy=x.geometry.centroid.coords[0], ha='center'),axis=1)

Using perceptually uniform colormaps in Mayavi volumetric visualization

AFAIK Mayavi does not come with any perceptually uniform colormaps. I tried naively to just pass it one of Matplotlib's colormaps but it failed:
from mayavi import mlab
import multiprocessing
import matplotlib.pyplot as plt
plasma = plt.get_cmap('plasma')
...
mlab.pipeline.volume(..., colormap=plasma)
TraitError: Cannot set the undefined 'colormap' attribute of a 'VolumeFactory' object.
Edit: I found a guide to convert Matplotlib colormaps to Mayavi colormaps. However, it unfortunately doesn't work since I am trying to use a volume using a perceptually uniform colormap.
from matplotlib.cm import get_cmap
import numpy as np
from mayavi import mlab
values = np.linspace(0., 1., 256)
lut_dict = {}
lut_dict['plasma'] = get_cmap('plasma')(values.copy())
x, y, z = np.ogrid[-10:10:20j, -10:10:20j, -10:10:20j]
s = np.sin(x*y*z)/(x*y*z)
mlab.pipeline.volume(mlab.pipeline.scalar_field(s), vmin=0, vmax=0.8, colormap=lut_dict['plasma']) # still getting the same error
mlab.axes()
mlab.show()
...
Instead of setting it as the colormap argument, if you set it as the ColorTransferFunction of the volume, it works as expected.
import numpy as np
from mayavi import mlab
from tvtk.util import ctf
from matplotlib.pyplot import cm
values = np.linspace(0., 1., 256)
x, y, z = np.ogrid[-10:10:20j, -10:10:20j, -10:10:20j]
s = np.sin(x*y*z)/(x*y*z)
volume = mlab.pipeline.volume(mlab.pipeline.scalar_field(s), vmin=0, vmax=0.8)
# save the existing colormap
c = ctf.save_ctfs(volume._volume_property)
# change it with the colors of the new colormap
# in this case 'plasma'
c['rgb']=cm.get_cmap('plasma')(values.copy())
# load the color transfer function to the volume
ctf.load_ctfs(c, volume._volume_property)
# signal for update
volume.update_ctf = True
mlab.show()
While the previous answer by like444 helped me partially with a similar problem, it leads to incorrect translation between colormaps. This is because the format in which matplotlib and tvtk store color information is slightly different: Matplotlib uses RGBA, while ColorTransferFunction uses VRGB, where V is the value in the shown data that this part of the colormap is assigned to. So by doing a 1-to-1 copy, green becomes red, blue becomes green and alpha becomes blue. The following code snippet fixes that:
def cmap_to_ctf(cmap_name):
values = list(np.linspace(0, 1, 256))
cmap = cm.get_cmap(cmap_name)(values)
transfer_function = ctf.ColorTransferFunction()
for i, v in enumerate(values):
transfer_function.add_rgb_point(v, cmap[i, 0], cmap[i, 1], cmap[i, 2])
return transfer_function