How does osmnx.plot_graph determine which edges get which colors? - geopandas

I've followed this tutorial:
https://towardsdatascience.com/creating-beautiful-maps-with-python-6e1aae54c55c
and the one this above was derived from.
They pass a list of edge colors to the plot_graph function
like so:
fig, ax = ox.plot_graph(gdf, node_size=0, bbox = (north, south, east, west),figsize=(height, width),
dpi = 96,bgcolor = bgcolor,
save = False, edge_color=roadColors,
edge_linewidth=roadWidths, edge_alpha=1)
I don't think they're assigned the way that the tutorial indicates.
On the github I found get_edge_colors_by_attr which seems to take attributes into account.
How are the colors assigned?
Specifically I am asking because I'd like to plot "highways" in different colors based on their openstreetmap tag.

How does osmnx.plot_graph determine which edges get which colors?
You can see how it does it here. Essentially, it either applies a single color to all edges or, if you passed it a list of colors, it assigns the first color in the list to the first edge in the graph, the second to the second, the third to the third, and so on.
Specifically I am asking because I'd like to plot "highways" in different colors based on their openstreetmap tag.
You can create a list of colors based on the edges' highway attribute values:
import osmnx as ox
G = ox.graph_from_place('Piedmont, California, USA', network_type='drive')
# assign colors to edges based on "highway" value
hwy_color = {'residential': 'gray',
'secondary': 'r',
'tertiary': 'y',
'tertiary_link': 'b',
'unclassified': 'm'}
edges = ox.graph_to_gdfs(G, nodes=False)['highway']
ec = edges.replace(hwy_color)
# plot graph using these colors
fig, ax = ox.plot_graph(G, edge_color=ec)
Also, you mentioned get_edge_colors_by_attr but note that per the docs the attribute must be numeric.

Related

Plot does not highlight all the unique values of a column represented by hue

My dataframe has a column 'rideable_type' which has 3 unique values:
1.classic_bike
2.docked_bike
3.electric_bike
While plotting a barplot using the following code:
g = sns.FacetGrid(electric_casual_type_week, col='member_casual', hue='rideable_type', height=7, aspect=0.65)
g.map(sns.barplot, 'day_of_week', 'number_of_rides').add_legend()
I only get a plot showing 2 unique 'rideable_type' values.
Here is the plot:
As you can see only 'electric_bike' and 'classic_bike' are seen and not 'docked_bike'.
The main problem is that all the bars are drawn on top of each other. Seaborn's barplots don't easily support stacked bars. Also, this way of creating the barplot doesn't support the default "dodging" (barplot is called separately for each hue value, while it would be needed to call it in one go for dodging to work).
Therefore, the recommended way is to use catplot, a special version of FacetGrid for categorical plots.
g = sns.catplot(kind='bar', data=electric_casual_type_week, x='day_of_week', y='number_of_rides',
col='member_casual', hue='rideable_type', height=7, aspect=0.65)
Here is an example using Seaborn's 'tips' dataset:
import seaborn as sns
tips = sns.load_dataset('tips')
g = sns.FacetGrid(data=tips, col='time', hue='sex', height=7, aspect=0.65)
g.map_dataframe(sns.barplot, x='day', y='total_bill')
g.add_legend()
When comparing with sns.catplot, the coinciding bars are clear:
g = sns.catplot(kind='bar', data=tips, x='day', y='total_bill', col='time', hue='sex', height=7, aspect=0.65)

How to customize seaborn.scatterplot legends?

I plotted a scatterplot with seaborn library and I want to change the legend text but dont know how to do that.
example:
The following is iris dataset with species columns encoded in 0/1/2 as per species.
plt.figure(figsize=(8,8))
pl = sns.scatterplot(x='petal_length', y ='petal_width', hue='Species', data=data, s=40,
palette='Set1', legend='full')
I want to change the legends text from [0, 1, 2] to ['setosa', 'versicolor', 'virginica'].
can anybody help.
First, Seaborn (and Matplotlib) usually picks up the labels to put into the legend for hue from the unique values of the array you provide as hue. So as a first step, check that the column Species in your dataframe actually contains the values "setosa", "versicolor", "virginica". If not, one solution is to temporarily map them to other values, for the purpose of plotting:
legend_map = {0: 'setosa',
1: 'versicolor',
2: 'virginica'}
plt.figure(figsize=(8,8))
ax = sns.scatterplot(x=data['petal_length'], y =data['petal_width'], hue=data['species'].map(legend_map),
s=40, palette='Set1', legend='full')
plt.show()
Alternatively, if you want to directly manipulate the plot information and not the underlying data, you can do by accessing the legend names directly:
plt.figure(figsize=(8,8))
ax = sns.scatterplot(x='petal_length', y ='petal_width', hue='species', data=data, s=40,
palette='Set1', legend='full')
l = ax.legend()
l.get_texts()[0].set_text('Species') # You can also change the legend title
l.get_texts()[1].set_text('Setosa')
l.get_texts()[2].set_text('Versicolor')
l.get_texts()[3].set_text('Virginica')
plt.show()
This methodology allows you to also change the legend title, if need be.

Changing colors on dimple.js scatter plot

How can I change the color of the circles on a scatter plot based on one of the fields that I'm not using on neither of the axes?
Example, this code:
var myChart3 = new dimple.chart(svg3, data);
myChart3.addMeasureAxis("x", "salary");
myChart3.addMeasureAxis("y", "bonus");
var mySeries = myChart3.addSeries(["Index","a"], dimple.plot.scatter);
myChart3.draw();
produces this graph:
but I also would like to color the bubbles based on a third field called "department"
thanks
The first parameter of addSeries determines colours. In the case of an array the last element is used, so you just need to do:
var mySeries = myChart3.addSeries(["Index","a","department"], dimple.plot.scatter);

Finding area of the image

I used connected component labeling algorithm (bwconncomp) to label the different parts of a binary image (MATLAB). Now i need to calculate the area of different labels and remove the labels with smaller area. Can i use the default area finding command or is there any specific commands for that in matlab...Help..
From the documentation:
CC = bwconncomp(BW) returns the connected components CC found in BW.
The binary image BW can have any dimension. CC is a structure with
four fields...
The final field in CC is PixelIdxList, which is:
[a] 1-by-NumObjects cell array where the kth element in the cell array is
a vector containing the linear indices of the pixels in the kth object.
You can find the area of each label by looking at the length of the corresponding entry in the cell array. Something like:
areas_in_pixels = cellfun(#length, CC.PixelIdxList);
The PixelIdxList is a cell array, each member of which contains the linear indexes of the pixels present in that connected component. The line of code above finds the length of each cell in the cell array - i.e. the number of pixels in each connected component.
I've used cellfun to keep the code short and efficient. A different way of writing the same thing would be something like:
areas_in_pixels = nan(1, length(CC.PixelIdxList);
for i = 1:length(CC.PixelIdxList)
areas_in_pixels(i) = length(CC.PixelIdxList{i});
end
For each connected component, you can then find the size of that component in pixels by accessing an element in areas_in_pixels:
areas_in_pixels(34) %# area of connected component number 34
If you don't want to write lots of code like above just use built-in functions of MATLAB to detect the area. Label your components and from the properties of the component you can find out the area of that component. Suppose Bw is the binary image:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
for k = 1:length(B)
area(k)=stats.Area;
end
You can make this better still by avoiding the for loop with the following:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
area = [stats.Area];
Best,
-Will

How to zoom to fit in WP7 Bing Maps control using LocationCollection?

How can I zoom the Microsoft.Phone.Controls.Maps.Map control to the correct zoom level on Windows Phone 7?
I have a LocationCollection of GeoCoordinates and I calculated the Center myself, but now how do I calculate the correct zoom level to fit the LocationCollection?
P.S. Is there an out of the box method to calculate the center of GeoCoordinates so I don't have to calculate it myself?
EDIT:
I've found another fine solution: http://4mkmobile.com/2010/09/quick-tip-position-a-map-based-on-a-collection-of-pushpins/
map.SetView(LocationRect.CreateLocationRect(points));
You can use the following code to calculate the LocationRect that bounds a set of points, and then pass the LocationRect to the SetView() method on the map control:
var bounds = new LocationRect(
points.Max((p) => p.Latitude),
points.Min((p) => p.Longitude),
points.Min((p) => p.Latitude),
points.Max((p) => p.Longitude));
map.SetView(bounds);
The map control handles animating from the current position to the new location.
NOTE: You'll need a using statement for System.Linq to get the Min and Max methods.
Derek has already given the answer so you should accept his, I offer an alternative code for cases where there many points. This approach only iterates the points collection once instead 4 times however it isn't as asthetically pleasing.
double north, west, south, west;
north = south = points[0].Latitude;
west = east = points[0].Longitude;
foreach (var p in points.Skip(1))
{
if (north < p.Latitude) north = p.Latitude;
if (west > p.Longitude) west = p.Longitude;
if (south > p.Latitude) south = p.Latitude;
if (east < p.Longitude) east = p.Longitude
}
map.SetView(new LocationRect(north, west, south, east));
As suggested by the other answers I use SetView with a LocationRect.
However I found that it always produces to low zoom level, since only integer values was used. If for instance the perfect zoom level would be 5.5, you would get 5.0. To get a proper fit I calculate a new zoom level from TargetZoomLeveland TargetBoundingRectangle:
viewRect = LocationRect.CreateLocationRect(coordinates);
map.SetView(viewRect);
double scale = map.TargetBoundingRectangle.Height/viewRect.Height;
map.ZoomLevel = map.TargetZoomLevel + Math.Log(scale, 2);
This example sets the zoom level to fit viewRect's height on the screen.

Resources