Maps using Python Plotly!
One of the best things to do while you are analyzing the Data, is visualizing it for a better understanding, as plotting any kind of graphs and in this case, maps.
Therefore, if you are trying to analyze data from properties, zones, countries or anything that can be interpreted on a map you should try to graph them. So the client or you, can visualize patterns, distributions or any relevant information that can be interpreted on a map, being this a very useful information for the analysis of the data.

For me, one of my favorite things to do while analyzing the data that I’m working with is to create visualizations. They are proof of taking all of that information into a more visual and understanding way.
This visualization would give me more insights that would lead me to more paths of analysis of the information that I am working with, especially if I can visualize this into any type of Maps that can show me any patterns and extra information that can´t be shown in a numerical way different from a visualization/map.

Analyzing the data
First of all, I have to analyze the data that I am working with.
Importing libraries
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.impute import KNNImputer
from sklearn.preprocessing import StandardScaler
Before I start analyzing I have to import the first and most important libraries to analyze the data (Pandas, Numpy, Matplotlib and Seaborn), and also I import extra libraries for the manipulation of the data in case of null/NaN values (Knn Imputer and Standard Scaler).
Basic Analysis of the data and Null
After importing the libraries, I load and read the data that I am going to work with.

Then, I search for null values in the data:

As we can see we have a lot of null values in the data, especially in Latitude and Longitude, important values for the implementation of maps, and the visualization of the distribution of the properties in Buenos Aires.
So, here is the importance of the Knn Imputer and the Standard Scaler (libraries previously imported).
Since I would like to eliminate those null values I would input those values with their nearest neighbors with similar characteristics and in this case close properties for the "Latitude" and "Longitude" data.
Also, I used the Standard Scaler to standardize the features by subtracting the mean and then scaling to unit variance. Unit variance means dividing all the values by the standard deviation. I do this so I standardize all the data for the imputer to work faster, lower magnitude values converge faster, and later inverse transforms to have the data in its original form.
This could be made like this:
scaler = StandardScaler()
data[["lat","lon","surface_covered","surface_total", "bathrooms"]] = scaler.fit_transform(data[["lat","lon","surface_covered","surface_total", "bathrooms"]])
variable = data[["lat","lon","surface_covered","surface_total", "bathrooms"]]
imputer = KNNImputer(n_neighbors=2,weights='uniform', metric='nan_euclidean')
variable = imputer.fit_transform(variable)
data.loc[:, ["lat","lon","surface_covered","surface_total", "bathrooms"]] = variable
data[["lat","lon","surface_covered","surface_total", "bathrooms"]] = scaler.inverse_transform(data[["lat","lon","surface_covered","surface_total", "bathrooms"]])
data['bathrooms'] = data['bathrooms'].round()
It shows like this in the notebook:

Using PLOTLY
First of all, I needed to create an Account on Mapbox to take advantage of the amount of good layer that the APK gives.
- Creating an Account:

- After you create an account, you need to create a Token, this will grant you an access to use the layers you want to visualize on the map.

- Copying the access Token:

You will need to copy and save that token, because you will use it later on the code
After I had the Mapbox Access Token I started to code how I wanted to show my data on a map using Plotly and here is the first code:
import Plotly.express as px
px.set_mapbox_access_token("Your-Access-Token")
fig = px.scatter_mapbox(data, lat="lat", lon="lon", color="l2",hover_name="property_type", size="price", hover_data=["price", "l3"],color_continuous_scale=px.colors.cyclical.IceFire, zoom=10, height=1000, center={"lat":-34.60652, "lon":-58.43557})
fig.show()
And this is how it looks:

The code has various parts:
fig = px.scatter_mapbox(data, lat="lat", lon="lon", color="l2",hover_name="property_type", size="price", hover_data=["price", "l3"],color_continuous_scale=px.colors.cyclical.IceFire, zoom=10, height=1000, center={"lat":-34.60652, "lon":-58.43557})
First I had to specify my dataframe where the info is, in this case is called "data". Then, specify the name of the columns where the Latitude and Longitude is in this case "lat" and "lon". The "color" part of the function is how the properties will be divided, like the hue. The "hover_name" will be the title I wanted to see when we step the mouse over a property. The "size" is how I wanted to visualize the properties, in this case if the bubble (property) is very big, it is because the price is big. The "hover_data" is the information I wanted to see when I step over a property. And finally, the "center" is where I wanted to center my ap as soon as it loads.
I did different types of maps with plotly, but what will happen if I didn’t have the "lat" and "lon" of each property? How could I graph them on a map?
Graphing on a map without having Latitude and Longitude at first in our data
Since I already had the latitude and longitude of each property I decided to graph each Borough on a map, for those I didn’t had their Latitude and Longitude.
Using Geopy library
The Geopy library help us to search latitude and longitude for what we are looking for, in this case the Borough. We can see it here:
First I needed to put in the most explicit way the Borough that I needed to be searched with Geopy.
precio_barrio['l3'] = 'Argentina, Buenos Aires, ' + precio_barrio['l3'].astype(str)

I was searching for "l3" that is the Borough, and the price is the mean price of the properties on each Borough.
After putting in the Borough in the most explicit way, we make the search:
from geopy.geocoders import Nominatim
geolocator = Nominatim()
precio_barrio["location"] = precio_barrio["l3"].apply(geolocator.geocode)
precio_barrio["latitude"] = precio_barrio["l3"].apply(geolocator.geocode).apply(lambda x: (x.latitude))
precio_barrio["longitude"] = precio_barrio["l3"].apply(geolocator.geocode).apply(lambda x: (x.longitude))
This was the result:

Now that I had the "Latitude" and "Longitude" by Borough, I can map it the way we did it earlier with different types of maps layers.
- Map # 1
fig = px.scatter_geo(precio_barrio, lat="latitude", lon="longitude", color="l2",
hover_name="l3", size="price",
projection="natural earth", center={"lat":-34.60652, "lon":-58.43557})
fig.show()

- Map #2
px.set_mapbox_access_token("Yor-Access-Token")
fig = px.scatter_mapbox(precio_barrio, lat="latitude", lon="longitude", color="price",hover_name="l3", size="price",
color_continuous_scale=px.colors.cyclical.IceFire, zoom=10, height=1000, center={"lat":-34.60652, "lon":-58.43557})
fig.show()

- Map #3
px.set_mapbox_access_token("Yor-Access-Token")
fig = px.scatter_mapbox(precio_barrio, lat="latitude", lon="longitude", color="l2",hover_name="l3", size="price",
color_continuous_scale=px.colors.cyclical.IceFire, zoom=10, height=1000, center={"lat":-34.60652, "lon":-58.43557})
fig.show()

Finally, even though we search each Borough with the Geopy library, the Latitude and Longitude weren’t so exactly like we wish them to be. This is because we need to put the address or something more specific for Geopy Nominatum found the exact latitude and longitude by Borough.
You can find the original notebook for this project in here.
Here in my Github.
Anything to improve and add, I am all ears!!
