I have a function that creates a Holoviewa heatmap. If I save the heatmap using hv.save(heatmap, 'heatmap.html') it works great! I just cannot figure out how to show the plot without having to save it. The same script generates two density plots with Plotly and using .show() and pops the plot up in my browser.
I am NOT using jupyter notebook and have been starting the bokeh server from a DOS prompt. I am working inside PyCharm Community with Python 3.10. Though if I could do it all from inside the script that would be easier.
def gen_heat_map(df: pandas.DataFrame, freq: float) -> holoviews.HeatMap:
"""
Uses a single frequency upon which to build the heatmap.
:param df: pandas.Dataframe containing data read from a JSON file
:param freq: The frequency to build the heatmap out of
:return: Holoviews Heat Map
"""
# Select a single frequency upon which to build the heatmap
single_frq = df[df.centerFrequency == freq].reset_index(drop=True)
# create a second dataframe from each transmission
sec_df = pd.DataFrame()
for index, row in single_frq.iterrows():
sec_df = sec_df.append(make_by_second(row), ignore_index=True)
min_df = sec_df.set_index('time').resample('1min').mean().reset_index().replace(np.nan, -160)
with pd.option_context('display.max_columns', None):
print(min_df)
min_df["Minute"] = min_df["time"].dt.strftime("%M")
min_df["Hour"] = min_df['time'].dt.strftime("%H")
heatmap = hv.HeatMap(min_df, ['Minute', 'Hour'], ['power', 'time'])
heatmap.opts(radial=True,
width=750,
height=750,
tools=['hover'],
colorbar=True,
cmap='bokeh',
start_angle=-np.pi * 7 / 24,
title='Frequency Power Level Radial Heat Map'
)
return heatmap
heatmap = gen_heat_map(df, 929612500.0)
The function gen_heat_map takes a large Pandas Dataframe of data read from a JSON file plus a single frequency and generates the heat map. It is trying to display this resultant heat map that is the issue. I can do so through Holoviz's Panel toolkit but I would like to find a simpler solution.
Suggestions?
Thanks,
Doug
Related
df = pd_df_total_primary_Y.set_index('EthnicGroups_EthnicGroup1Desc')
df1 = pd_df_total_general_Y.set_index('EthnicGroups_EthnicGroup1Desc')
df[["P_Y_Count20", "P_Y_Count16", "P_Y_Count12", "P_Y_Count08","P_Y_Count04", "P_Y_Count00"]].plot.bar()
plt.title('total_primary_Y');
df1[["G_Y_Count20", "G_Y_Count16", "G_Y_Count12", "G_Y_Count08", "G_Y_Count04", "G_Y_Count00"]].plot.bar()
plt.title('total_general_Y');
I am trying to plot these graph on the same row and then add two more graphs below them. I am struggling to get it to work. how can i do it?
I am trying to plot the amount of times a satellite goes over a certain location using Python and a heatmap. I easily generate the satellite data, but I am having issues with displaying it in a nice manner. I am trying to follow this example, as I can use the style function to lower the opacity. I am having some issues replicating this though as it seems that the GeoJson version they were using no longer accepts the same inputs. This is the dataframe I am using:
print(df.head())
latitude longitude countSp geometry
0 -57.9 151.1 1.0 POLYGON ((151.05 -57.95, 151.15 -57.95, 151.15...
1 -57.9 151.2 2.0 POLYGON ((151.15 -57.95, 151.25 -57.95, 151.25...
2 -57.8 151.2 1.0 POLYGON ((151.15 -57.84999999999999, 151.25 -5...
3 -57.8 151.3 3.0 POLYGON ((151.25 -57.84999999999999, 151.35 -5...
4 -57.8 151.4 2.0 POLYGON ((151.35 -57.84999999999999, 151.45 -5...
I then call folium through:
hmap = folium.Map(location=[42.5, -80], zoom_start=7, )
colormap_dept = branca.colormap.StepColormap(
colors=['#00ae53', '#86dc76', '#daf8aa',
'#ffe6a4', '#ff9a61', '#ee0028'],
vmin=0,
vmax=max_amt,
index=[0, 2, 4, 6, 8, 10, 12])
style_func = lambda x: {
'fillColor': colormap_dept(x['countSp']),
'color': '',
'weight': 0.0001,
'fillOpacity': 0.1
}
folium.GeoJson(
df,
style_function=style_func,
).add_to(hmap)
This is the error I get when I run my code:
ValueError: Cannot render objects with any missing geometries: latitude longitude countSp geometry
I know that I can use the HeatMap plugin from folium in order to get most of this done, but I have found a couple of issues with doing that. First is that I cannot easily generate a legend (though I have been able to work around this). Second is that it is way too opaque, and I am not finding any ways of reducing that. I have tried playing around with the radius, and blur parameters for HeatMap without much change. I think that the fillOpacity of the style_func above is a much better way of making my data translucent.
By the way, I generate the polygon in my df by the following command. So in my dataframe all I need folium to know about is the geometry and countSp (which is the number of times a satellite goes over a certain area - ~10kmx10km square).
df['geometry'] = df.apply(lambda row: Polygon([(row.longitude-0.05, row.latitude-0.05),
(row.longitude+0.05, row.latitude-0.05),
(row.longitude+0.05, row.latitude+0.05),
(row.longitude-0.05, row.latitude+0.05)]), axis=1)
Is there a good way of going about this issue?
Once again, they were looking for a way to express the purpose in a heat map, so I used Plotly's data on airline arrivals and departures to visualize it.
The number of flights to and from the U.S. mainland only was used for the data.
Excluded IATA codes['LIH','HNL','STT','STX','SJU','OGG','KOA']
Draw a straight line on the map from the latitude and longitude of the departure airport to the latitude and longitude of the arrival airport.
Draw a heat map with data on the number of arrivals and departures by airport.
Since we cannot use a discrete colormap, we will create a linear colormap and add it.
Embed the heatmap as a layer named Traffic
import pandas as pd
df_airports = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv')
df_airports.sort_values('cnt', ascending=False)
df_air = df_airports[['lat','long','cnt']]
df_flight_paths = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_february_aa_flight_paths.csv')
df_flight_paths = df_flight_paths[~df_flight_paths['airport1'].isin(['HNL','STT','SJU','OGG','KOA'])]
df_flight_paths = df_flight_paths[~df_flight_paths['airport2'].isin(['LIH','HNL','STT','STX','SJU'])]
df_flight_paths = df_flight_paths[['start_lat', 'start_lon', 'end_lat', 'end_lon', 'cnt']]
import folium
from folium.plugins import HeatMap
import branca.colormap as cm
from collections import defaultdict
steps=10
colormap = cm.linear.YlGnBu_09.scale(0, 1).to_step(steps)
gradient_map=defaultdict(dict)
for i in range(steps):
gradient_map[1/steps*i] = colormap.rgb_hex_str(1/steps*i)
m = folium.Map(location=[32.500, -97.500], zoom_start=4, tiles="cartodbpositron")
data = []
for idx,row in df_flight_paths.iterrows():
folium.PolyLine([[row.start_lat, row.start_lon], [row.end_lat, row.end_lon]], weight=2, color="red", opacity=0.4
).add_to(m)
HeatMap(
df_air.values,
gradient=gradient_map,
name='Traffic',
mini_opacity=0.1,
radius=15,
blur=5
).add_to(m)
folium.LayerControl().add_to(m)
colormap.add_to(m)
m
I want to select from a dataframe based on a name. Then I want to plot the data on a single graph using a for loop.
df = pd.read_csv ('Kd.csv')
watertype = ['Evian','Volvic','Buxton']
for type in watertype:
sdf = df[(df['Water']==type)]
Na = sdf.iloc[:,13]
Kd = sdf.iloc[:,2]
plt.plot(Na,Kd,'o')
plt.show()`
Multiple graphs produced instead of overlaying them on a single graph.
I am working on a Bokeh visualisation of datasets across a number of categories. The initial part of the visual is a donut chart of the categories showing the total number of items in each category. I am trying to get the chart to update based on a min-max range using RangeSlider - but the chart does not update.
The input source for the glyphs is the output from a create_cat_df - which is returned as a Pandas DF, then converted into a CDS using ColumnDataSource.from_df().
The chart appears okay when this code is run (with slider alongside) - but moving the slider changes nothing.
There is a similar post here.
The answer here was useful in putting me onto from_df - but even after following this I can't get the code to work.
def create_doc(doc):
### INPUT widget
cat_min_max = RangeSlider(start=0, end=1000, value=[0, 1000], step=1, title="Category min-max items (m)")
inputs = column(cat_min_max, width=300, height=850) # in preparation for multiple widgets
### Tooltip & tools
TOOLTIPS_2 = [("Item", "$item") # a sample
]
hover_2 = HoverTool(tooltips=TOOLTIPS_2, names = ['cat'])
tools = [hover_2, TapTool(), WheelZoomTool(), PanTool(), ResetTool()]
### Create Figure
p = figure(plot_width=width, plot_height=height, title="",
x_axis_type=None, y_axis_type=None,
x_range=(-420, 420), y_range=(-420, 420),
min_border=0, outline_line_color=None,
background_fill_color="#f0e1d2",
tools = tools, toolbar_location="left")
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
# taptool
url = "https://google.com/" #dummy URL
taptool = p.select(type=TapTool)
taptool.callback = OpenURL(url=url)
# create cat_source CDS using create_cat_df function (returns pandas df) and 'from_df' method
cat_source = ColumnDataSource.from_df(create_cat_df(cat_min_max.value[0], cat_min_max.value[1]))
## plot category wedges
p.annular_wedge('centre_x', 'centre_y', 'inner', 'outer', 'start', 'end', color='color',
alpha='alpha', direction='clock', source=cat_source, name='cat')
r = row([inputs, p])
def callback(attr, old, new):
cat_source.data = ColumnDataSource.from_df(create_cat_df(cat_min_max.value[0], cat_min_max.value[1]))
cat_min_max.on_change('value', callback)
doc.add_root(r)
show(create_doc)
I would like to get the code working and the chart updating. There are a number more glyphs & different data layers to layer in, but I want to get the basics working first.
According to Bokeh documentation the ColumnDataSource.from_df() method returns a dictionary while you need to pass a ColumnDatSource to the source argument in p.annular_wedge(source = cat_source)
So instead of:
cat_source = ColumnDataSource.from_df(create_cat_df(cat_min_max.value[0], cat_min_max.value[1]))
You should do:
cat_source = ColumnDataSource(data = ColumnDataSource.from_df(create_cat_df(cat_min_max.value[0], cat_min_max.value[1])))
I am trying to remove the overlay text on my boxplot I created using pandas. The code to generate it is as follows (minus a few other modifications):
ax = df.boxplot(column='min2',by=df['geomfull'],ax=axes,grid=False,vert=False, sym='',return_type='dict')
I just want to remove the "boxplot grouped by 0..." etc. and I can't work out what object it is in the plot. I thought it was an overflowing title but I can't find where the text is coming from! Thanks in advance.
EDIT: I found a work around which is to construct a new pandas frame with just the relevant list of things I want to box (removing all other variables).
data = {}
maps = ['BA4','BA5','BB4','CA4','CA5','EA4','EA5','EB4','EC4','EX4','EX5']
for mapi in maps:
mask = (df['geomfull'] == mapi)
arr = np.array(df['min2'][mask])
data[mapi] = arr
dfsub = pd.DataFrame(data)
Then I can use the df.plot routines as per examples....
bp = dfsub.plot(kind='box',ax=ax, vert=False,return_type='dict',sym='',grid=False)
This produces the same plot without the overlay.