Pygal: Displaying information for each data point - python

I have been playing around with Pygal, creating some line graphs for a project I am working on. I currently have my y axis set to be the value recorded and the x axis being the date / time the test was conducted. However I would also like to link the serial number to each data point. At the moment when you hover on a data point you get the y value in bold and underneith that you get the date it was recorded.
Does anyone know if it is possible to link information to data points without them being an axis label?
For reference I currently have the serial numbers being added to the list: 'sn_list'.
for row in line_graph_query:
if str(row.date_time) >= start_date and str(row.date_time) <= end_date :
min_values.append(float(row.minimum_value))
max_values.append(float(row.maximum_value))
recorded_values.append(float(row.recorded_value))
sn_list.append(row.product_serial_number)
date_list.append(row.date_time)
number_of_records = number_of_records + 1
print(min_values)
print(max_values)
print(recorded_values)
distance_x_axis = math.floor(number_of_records/6)
line_chart = pygal.Line(no_data_text='No result found', style=custom_style,x_labels_major_every=distance_x_axis, x_label_rotation=20, show_minor_x_labels=False )
line_chart.title = 'Detailed Results of '+test_name+' tests of '+board_pn
line_chart.x_labels = map(str,date_list)
line_chart.add('Minimum', min_values)
line_chart.add('Maximum', max_values)
line_chart.add('Recorded', recorded_values)
graph_render.append(line_chart.render_data_uri())
graphs_to_render[test_name] = graph_render[-1]

You can set the tooltip to any text you like by providing your data as dicts (see the documentation here). Each value should be represented by a dict that has at least a value attribute, this is the same value that you were providing to the chart directly. There are then a number of other attributes you can set, amongst them label.
You should be able to get the tooltips you want by changing the three lines that append data in your if structure:
min_values.append({"value": float(row.minimum_value),
"label": row.product_serial_number})
max_values.append({"value": float(row.maximum_value),
"label": row.product_serial_number})
recorded_values.append({"value": float(row.recorded_value),
"label": row.product_serial_number})
Unless you are using it somewhere else this also means that you have no need of the sn_list.

Related

Python pptx - creating chart with multiple categories?

is it possible to create a chart in python with multiple categories?
For example:
I copy pasted this in powerpoint, loaded it and tried this:
presentation.slides[0].shapes[0].chart.plots[0].categories.flattened_labels
which gave me all the labels in a tuple format -->
(('Oct-2019', 'Advertiser'),('Oct-2019','25th percentile), etc ...)
if I try printing :
presentation.slides[0].shapes[0].chart.plots[0].categories[i]
for i in 0 to 3
I get the values 'Advertiser','25th percentile' etc, but I can't find a way to access the 'Oct-2019' value.
When creating the ChartData, I saw that I can also add_category, but this adds the label to the categories I'm currently accessing (e.g. Advertiser, 25th percentile, etc), but I would like to add 'Nov 2019' which is in another hierarchy level.
This is a bit of a roundabout way of asking if anyone has created a multi-category chart with python pptx, and how they would do it from the chartdata level/what this would look like.
Thank you!
#data
pivot_digital_monthly_imp_laydown = pd.pivot_table(digital_monthly_imp_laydown, values='Original Value', index=['Year','Month'],
columns=['Campaign'], aggfunc=np.sum,fill_value=0,sort=False).reset_index().rename_axis(None, axis=1)
pivot_digital_monthly_imp_laydown.Year=pivot_digital_monthly_imp_laydown.Year.astype(str)
#inserting Impressions laydown in slide
prs=input_ppt
digital_monthly_imp_laydown_chart = prs.slides[3].shapes[6].chart
digital_monthly_imp_laydown_data =CategoryChartData()
#multilevel Categories
cat=list(pivot_digital_monthly_imp_laydown['Year'])
subcat=list(pivot_digital_monthly_imp_laydown['Month'])
b={}
for i,j in zip(cat,subcat):
key=str(i)
b.setdefault(key,[])
b[key].append(j)
main_cat=list(b.keys())
for i in range(len(main_cat)):
ear=digital_monthly_imp_laydown_data.add_category(str(main_cat[i]))
for sub in b[main_cat[i]]:
ear.add_sub_category(str(sub))
#add series data
for col in pivot_digital_monthly_imp_laydown.columns[2:]:
new = list(pivot_digital_monthly_imp_laydown[col])
digital_monthly_imp_laydown_data.add_series(str(col),new)
new=[]
digital_monthly_imp_laydown_chart.replace_data(digital_monthly_imp_laydown_data)
#saving
prs.save("./Output/Sub Brand Output.pptx")

Time series on folium map

I have a dataframe that denotes events that occured in particular locations.
I am aware that folium does not allow dynamic display of the appearance of the events so I was thinking about basically iterate through the dates and save a png of each folium map created.
Unfortunately I am mentally stuck in a 2 part problem:
1) how to loop through a ranges of dates (for example one map for each month)
2) an appropriate way to save the generated images for each loop.
This is a dataframe sample for this example:
since = ['2019-07-05', '2019-07-17', '2014-06-12', '2016-03-11']
lats = [38.72572, 38.71362, 38.79263, 38.71931]
longs = [-9.13412, -9.14407, -9.40824, -9.13143]
since_map = {'since' : pd.Series(since), 'lats' : pd.Series(lats), 'longs' : pd.Series(longs)}
since_df = pd.DataFrame(since_map)
I was able to create the base map:
lat_l = 38.736946
long_l = -9.142685
base_l = folium.Map(location=[lat_l,long_l], zoom_start=12)
neigh = folium.map.FeatureGroup()
And add some of the markers to the folium map:
for lati, longi in zip(since_df.longs, since_df.lats):
neigh.add_child(folium.CircleMarker([longi, lati], radius = 2, color = 'blue', fill = True))
base_l.add_child(neigh)
I am struggling to visualize how to loop through ranges of the dates and save each file. From what I saw here:
https://github.com/python-visualization/folium/issues/35 I actually have to open the saved html and then save it as png for each image.
If you could point me to an example or documentation that could demonstrate how this can be accomplished I would be very appreciative.
If you think I am overcomplicating it or you have a better alternative to what I am thinking I have an open ear to suggestions.
Thank you for your help.

Setting Gmaps bounds in Pandas

I want to display a whole country, but it zooms in to a street level somewhere in the middle of the country.
I am looking for a way to set the bounds to display the full country/region requested. I know there are bound coordinates but is there a property or a call I can make in pandas/python that will set it for the figure?
Everything I have found on Google so far was related C# and not python/pandas.
#get the coordinates for google maps API
gmaps.configure(api_key=cfg.key)
#build request
params = {'key': cfg.key}
params['address'] = f"{targetLocation}"
response = requests.get(cfg.baseApiUrl, params=params)
#convert response to json
response = response.json()
northeastLatBounds = response["results"][0]["geometry"]["bounds"]["northeast"]["lat"]
northeastLngBounds = response["results"][0]["geometry"]["bounds"]["northeast"]["lng"]
southwestLatBounds = response["results"][0]["geometry"]["bounds"]["southwest"]["lat"]
southwestLngBounds = response["results"][0]["geometry"]["bounds"]["southwest"]["lng"]
coordinates = pd.DataFrame({'lat': response["results"][0]["geometry"]["location"]["lat"],
'lng': response["results"][0]["geometry"]["location"]["lng"]}, index=[0])
coordinates.loc[1] = [northeastLatBounds] + [northeastLngBounds]
coordinates.loc[2] = [southwestLatBounds] + [southwestLngBounds]
coordinates
Please note the coordinates Dataframe was for my marker layer. I thought that entering the bounds there would help, but now I have 3 markers and doesn't look clean. Any help would be great!
Well I couldn't find any property settings like we have in C# so I created a "hard coding" of the zoom level based on whether it was a country or region being searched for. Not exactly what I wanted to do but it gets the job done.

Save Holoviews as interactive html

I have a Holoviews code with the intent of saving the output as .html. The below works fine i.e. html is genereated and tags are renders but filters don't work. What am I doing wrong?
def load_data(country, lan_name, **kwargs):
df = subset
if country != 'ALL':
df = df[(df.country == country)]
if lan_name != 'ALL':
df = df[(df.lan_name == lan_name)]
table = format_chars(df['term'], df['hex'])
#hv.Table(df, ['country', 'lan_name'], [], label='Data Table')
layout = (table).opts(
opts.Layout(merge_tools=False),
opts.Div(width=700, height=400),
)
return layout
methods = ['ALL'] + sorted(list(subset['country'].unique()))
models = ['ALL'] + sorted(list(subset['lan_name'].unique()))
dmap = hv.DynamicMap(load_data, kdims=['country', 'lan_name']).redim.values(country=methods, lan_name=models)
hv.save(dmap, 'output.html', backend='bokeh')
By "filters" it sounds like you mean the widgets that select along the country and lan_name dimensions. Each time you select a new value of a widget, a DynamicMap calls the Python function that you provide it (load_data here) to calculate the display (which is what makes it "Dynamic"). There is no Python process available when you have a static HTML file, so the display will never get updated in that case.
To make some limited functionality available in a static HTML file, you can convert the DynamicMap to a HoloMap that contains all the displayed items for some specific combinations of widget values (http://holoviews.org/user_guide/Live_Data.html#Converting-from-DynamicMap-to-HoloMap). The resulting parameter space can quickly get quite large, so you will often need to select a feasible subset of values for this to be a practical option.

Get results in an Earth Engine python script

I'm trying to get NDVI mean in every polygon in a feature collection with earth engine python API.
I think that I succeeded getting the result (a feature collection in a feature collection), but then I don't know how to get data from it.
The data I want is IDs from features and ndvi mean in each feature.
import datetime
import ee
ee.Initialize()
#Feature collection
fc = ee.FeatureCollection("ft:1s57dkY_Sg_E_COTe3sy1tIR_U-5Gw-BQNwHh4Xel");
fc_filtered = fc.filter(ee.Filter.equals('NUM_DECS', 1))
#Image collection
Sentinel_collection1 = (ee.ImageCollection('COPERNICUS/S2')).filterBounds(fc_filtered)
Sentinel_collection2 = Sentinel_collection1.filterDate(datetime.datetime(2017, 1, 1),datetime.datetime(2017, 8, 1))
# NDVI function to use with ee map
def NDVIcalc (image):
red = image.select('B4')
nir = image.select('B8')
ndvi = nir.subtract(red).divide(nir.add(red)).rename('NDVI')
#NDVI mean calculation with reduceRegions
MeansFeatures = ndvi.reduceRegions(reducer= ee.Reducer.mean(),collection= fc_filtered,scale= 10)
return (MeansFeatures)
#Result that I don't know to get the information: Features ID and NDVI mean
result = Sentinel_collection2.map(NDVIcalc)
If the result is small, you pull them into python using result.getInfo(). That will give you a python dictionary containing a list of FeatureCollection (which are more dictionaries). However, if the results are large or the polygons cover large regions, you'll have to Export the collection instead.
That said, there are probably some other things you'll want to do first:
1) You might want to flatten() the collection, so it's not nested collections. It'll be easier to handle that way.
2) You might want to add a date to each result so you know what time the result came from. You can do that with a map on the result, inside your NDVIcalc function
return MeansFeatures.map(lambda f : f.set('date', image.date().format())
3) If what you really want is a time-series of NDVI over time for each polygon (most common), then restructuring your code to map over polygons first will be easier:
Sentinel_collection = (ee.ImageCollection('COPERNICUS/S2')
.filterBounds(fc_filtered)
.filterDate(ee.Date('2017-01-01'),ee.Date('2017-08-01')))
def GetSeries(feature):
def NDVIcalc(img):
red = img.select('B4')
nir = img.select('B8')
ndvi = nir.subtract(red).divide(nir.add(red)).rename(['NDVI'])
return (feature
.set(ndvi.reduceRegion(ee.Reducer.mean(), feature.geometry(), 10))
.set('date', img.date().format("YYYYMMdd")))
series = Sentinel_collection.map(NDVIcalc)
// Get the time-series of values as two lists.
list = series.reduceColumns(ee.Reducer.toList(2), ['date', 'NDVI']).get('list')
return feature.set(ee.Dictionary(ee.List(list).flatten()))
result = fc_filtered.map(GetSeries)
print(result.getInfo())
4) And finally, if you're going to try to Export the result, you're likely to run into an issue where the columns of the exported table are selected from whatever columns the first feature has, so it's good to provide a "header" feature that has all columns (times), that you can merge() with the result as the first feature:
# Get all possible dates.
dates = ee.List(Sentinel_collection.map(function(img) {
return ee.Feature(null, {'date': img.date().format("YYYYMMdd") })
}).aggregate_array('date'))
# Make a default value for every date.
header = ee.Feature(null, ee.Dictionary(dates, ee.List.repeat(-1, dates.size())))
output = header.merge(result)
ee.batch.Export.table.toDrive(...)

Categories

Resources