How to resize data point in streamlit st.map()? - pandas

Summary
I am building a real-time dashboard that plots latitude and longitude using st.map(df).
Steps to reproduce
I was following this example here.
Code snippet:
import streamlit as st
import pandas as pd
import numpy as np
data = [[-33.71205471, 29.19017682], [-33.81205471, 29.11017682], [-34.71205471, 29.49017682]]
df = pd.DataFrame(data, columns=['Latitude', 'Longitude'])
st.map(df)
Actual behavior:
The plot works as intended but the data points are too large to distinguish between movements in latititude and longitude. Movements in lat and long have a 7 decimal place granularity (e.g. lat=166.1577634).
Expected behavior:
Here is an example in AWS QuickSight of how the points should look.
Any ideas on how to reduce the size of the map circles for each respective data point?
Thanks!

Related

Convert a pandas dataframe to geoTIFF (python)

I have a pandas df with X/Y and lat/lon coordinates.
I want to convert the data frame using lat/lon columns and store the TIFF image in WGS84 CRS.
Thanks
A couple package recommendations for you: xarray and rioxarray.
xarray is pydata's solution to labeled N-dimensional arrays (think pandas but in 3+ dimensions, or think numpy ND-arrays but with pandas indices rather than just positional indices).
rioxarray is an extension package combining xarray with rasterio, giving the ability to read and write raster files including GeoTIFFs. rioxarray has docs on converting xarray DataArrays to rasters. See also the API docs for converting RasterArray and RasterDataset objects to rasters.
In your case, assuming your orthogonal dimensions are (lat, lon) and that model_lat and model_lon are in fact indexed by both lat and lon (e.g. they're in a 3D projection), and that res is the band you'd like to encode, your result would look something like this:
import xarray as xr
import rioxarray
da = df.set_index(['lat', 'lon']).to_xarray()
# promote the data variables model lat/long to 2d coordinates
da = da.set_coords(['model_lat', 'model_long'])
da.res.rio.to_raster(filepath)

Contour Map Failure

I am trying to make contour maps with a Latitude, Longitude, and a value that is not elevation for my Master's project. I really like the contour plot of irregularly spaced data in matplotlib, but just can't make it work for my data! I get how it generally works. I have over 600 coordinates.
SEE:
https://matplotlib.org/stable/gallery/images_contours_and_fields/irregulardatagrid.html
I have a data frame and just need it to plot some points and those nice contour lines. Please save me! I am a noob. I bet this is super easy for one of you matplotlib pros. Here is what I have:
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
df = pd.read_csv('BI_LT_475_South_Carolina.csv')
Lon = df.iloc[:,0]
Lat = df.iloc[:,1]
CSR = df.iloc[:,2] # What I want to plot instead of elevation.
The csv. looks like this:
Longitude, Latitude, and CSR

Graph csv data that is represented horizontally rather than vertical - Python Pandas CSV

Context: I have combined numerous CSV's into one representing use case vs usage over a period of time.
The way the data is represented currently is attached.
What I am trying to do is, for each usecase, graph across row A(1, 1.1, 1.9, 4.0.11435, 4.1.11436 and so on...) - creating a linear plot to show progression over time
What I have so far:
import matplotlib.pyplot as plt
plot_df = pd.read_csv("results.csv")
milestones = plot_df.columns[1:]
row = plot_df.iloc[0]
row.plot(kind='line')
plt.show()
Any help is appreciated.
Thank you

Trouble geo mapping with datashader, holoviews and bokeh

I'm trying to map google phone history locations on to a map using holoviews, datashader and bokeh. Mostly very similar to the examples given in the datashader website. But when I do the map overlay doesn't work as the lat/long gets mangled up.
import datashader as ds
import geoviews as gv
import holoviews as hv
from holoviews.operation.datashader import datashade, dynspread
from datashader import transfer_functions as tf
from colorcet import fire
hv.extension('bokeh')
> df2.head()
lat long
0 -37.7997515 144.9636466
1 -37.7997515 144.9636466
2 -37.7997369 144.9636036
3 -37.7997387 144.9636358
4 -37.7997515 144.9636466
This works to produce an image of the data,
ds_viz = ds.Canvas().points(df2,'lat','long')
tf.set_background(tf.shade(ds_viz, cmap=fire),"black")
However when I try to overlay it with a map it doesn't work,
from bokeh.models import WMTSTileSource
url = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg'
tile_opts = dict(width=1000,height=600,bgcolor='black',show_grid=False)
map_tiles = gv.WMTS(url).opts(style=dict(alpha=0.5), plot=tile_opts)
points = hv.Points(df2, kdims=['long','lat'])
trips = datashade(points, cmap=fire,width=1000, height=600)
map_tiles * trips
What am I doing wrong?
It looks like your points are in lon,lat but your map is in Web Mercator coordinates, so you need to project your points into Web Mercator before you overlay them. GeoViews offers comprehensive support for projections, but for this specific case Datashader provides the special-purpose function datashader.utils.lnglat_to_meters. Something like this should work:
df2.loc[:, 'lon'], df.loc[:, 'lat'] = lnglat_to_meters(df2.lon,df2.lat)
Projecting can be slow, so you may want to save the resulting df2 to a Parquet file so that you only have to do it once.

Cutting up the x-axis to produce multiple graphs with seaborn?

The following code when graphed looks really messy at the moment. The reason is I have too many values for 'fare'. 'Fare' ranges from [0-500] with most of the values within the first 100.
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
titanic = sns.load_dataset("titanic")
y =titanic.groupby([titanic.fare//1,'sex']).survived.mean().reset_index()
sns.set(style="whitegrid")
g = sns.factorplot(x='fare', y= 'survived', col = 'sex', kind ='bar' ,data= y,
size=4, aspect =2.5 , palette="muted")
g.despine(left=True)
g.set_ylabels("Survival Probability")
g.set_xlabels('Fare')
plt.show()
I would like to try slicing up the 'fare' of the plots into subsets but would like to see all the graphs at the same time on one screen. I was wondering it this is possible without having to resort to groupby.
I will have to play around with the values of 'fare' to see what I would want each graph to represent, but for a sample let's use break up the graph into these 'fare' values.
[0-18]
[18-35]
[35-70]
[70-300]
[300-500]
So the total would be 10 graphs on one page, because of the juxtaposition with the opposite sex.
Is it possible with Seaborn? Do I need to do a lot of configuring with matplotlib? Thanks.
Actually I wrote a little blog post about this a while ago. If you are plotting histograms you can use the by keyword:
import matplotlib.pyplot as plt
import seaborn.apionly as sns
sns.set() #rescue matplotlib's styles from the early '90s
data = sns.load_dataset('titanic')
data.hist(by='class', column = 'fare')
plt.show()
Otherwise if you're just plotting value-counts, you have to roll your own grid:
def categorical_hist(self,column,by,layout=None,legend=None,**params):
from math import sqrt, ceil
if layout==None:
s = ceil(sqrt(self[column].unique().size))
layout = (s,s)
return self.groupby(by)[column]\
.value_counts()\
.sort_index()\
.unstack()\
.plot.bar(subplots=True,layout=layout,legend=None,**params)
categorical_hist(data, by='class', column='embark_town')
Edit If you want survival rate by fare range, you could do something like this
data.groupby(pd.cut(data.fare,10)).apply(lambda x.survived.sum(): x./len(x))