Alealejandrooo commited on
Commit
6904daa
1 Parent(s): 90658ae

Upload 5 files

Browse files

<h1>Postcodes Map</h1>

<h2>Project Overview</h2>
The Postcodes Map is a Python-based interactive visualization tool that leverages Folium for mapping and Gradio for creating an intuitive web interface. <br>
This tool is designed to help users visualize the distribution and frequency of postcodes across specific UK regions, providing insights into geographical data trends.

<h2>Features</h2>
<li>Interactive Mapping: Utilizes Folium to create dynamic maps that display geographical data based on UK postcodes.
<li>Frequency Visualization: Generates heatmaps to indicate the frequency of postcodes, distinguishing between areas with varying densities.
<li>File Upload Capability: Allows users to upload their postcode data in CSV or Excel formats directly through a web interface.
<li>Customizable Visuals: Supports different heatmap intensities and colors based on data frequency, enhancing the analytical utility of the maps.

<h2>License</h2>
This project is licensed under the MIT License.

.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ data/ukpostcodes.csv filter=lfs diff=lfs merge=lfs -text
data/ukpostcodes.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:39890648ae7165babb23192da09a48704f1ebc9250494fee77e3f78f6d0b0501
3
+ size 65741556
gradio/app.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from folium.plugins import HeatMap
3
+ from ingest import load_data
4
+ from process import get_lat_lon
5
+ from gradio_folium import Folium
6
+ from folium import Map
7
+
8
+
9
+ def update_header(file_info):
10
+ if file_info is not None:
11
+ filename = file_info.split('/')[-1] # Access the filename from the file_info dictionary
12
+ header = f"<h1>Nordic Balance Postcodes Map: {filename}</h1>" # Update the Markdown content
13
+ return header # Continue to pass the file_info to the next function if necessary
14
+
15
+ def generate_map(file_path):
16
+ # Load the postcodes
17
+ postcode_mapping = load_data('../data/ukpostcodes.csv')
18
+ # Load the data (this needs to be adapted to work outside Flask)
19
+ postcodes = load_data(file_path)
20
+
21
+ # Get latitude, longitude, and count data for the specified postcodes
22
+ lat_lon_data = get_lat_lon(postcodes, postcode_mapping)
23
+
24
+ # Prepare data for different frequency bands
25
+ low_freq_data = [
26
+ [data['latitude'], data['longitude']]
27
+ for data in lat_lon_data
28
+ if data['count'] == 1 and data['latitude'] and data['longitude']
29
+ ]
30
+ med_freq_data = [
31
+ [data['latitude'], data['longitude']]
32
+ for data in lat_lon_data
33
+ if 2 <= data['count'] <= 5 and data['latitude'] and data['longitude']
34
+ ]
35
+ high_freq_data = [
36
+ [data['latitude'], data['longitude']]
37
+ for data in lat_lon_data
38
+ if data['count'] > 5 and data['latitude'] and data['longitude']
39
+ ]
40
+
41
+ # Create your map here using Folium
42
+ map = Map(location=[51.505303, -0.13902], zoom_start=10)
43
+
44
+ # Adding different heatmaps for different frequencies
45
+ if low_freq_data:
46
+ HeatMap(low_freq_data, radius=10, blur=10, gradient={0.8: 'blue', 1: 'lime'}).add_to(map)
47
+ if med_freq_data:
48
+ HeatMap(med_freq_data, radius=15, blur=10, gradient={0.8: 'orange', 1: 'lime'}).add_to(map)
49
+ if high_freq_data:
50
+ HeatMap(high_freq_data, radius=20, blur=10, gradient={0.8: 'red', 1: 'lime'}).add_to(map)
51
+
52
+ return map
53
+
54
+ # Define a Gradio interface
55
+ with gr.Blocks() as demo:
56
+
57
+ with gr.Row():
58
+ header = gr.Markdown(("<h1>Nordic Balance Postcodes Map</h1>"))
59
+
60
+ with gr.Row():
61
+ map = Folium(value = Map(location=[51.505303, -0.13902], zoom_start=10), height=750)
62
+
63
+
64
+ with gr.Row():
65
+ file_uploader = gr.UploadButton(
66
+ label=("Upload"),
67
+ file_count="single",
68
+ file_types=[".csv", ".xlsx", '.xls'],
69
+ interactive=True,
70
+ scale=1,
71
+ )
72
+
73
+ file_uploader.upload(fn = generate_map,
74
+ inputs= file_uploader,
75
+ outputs=map)
76
+
77
+ file_uploader.upload(fn=update_header,
78
+ inputs=file_uploader,
79
+ outputs=header)
80
+
81
+
82
+ if __name__ == "__main__":
83
+ demo.launch()
gradio/ingest.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+
3
+ def load_data(filepath):
4
+ # Check the file extension and load the file accordingly
5
+ if filepath.endswith('.csv'):
6
+ df = pd.read_csv(filepath)
7
+ elif filepath.endswith('.xlsx') or filepath.endswith('.xls'):
8
+ df = pd.read_excel(filepath)
9
+ else:
10
+ raise ValueError("Unsupported file format: Please provide a .csv or .xlsx file")
11
+
12
+ # Convert all string values to lowercase and remove spaces
13
+ df = df.map(lambda x: x.lower().replace(" ", "") if isinstance(x, str) else x)
14
+
15
+ return df
gradio/process.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import gradio as gr
3
+
4
+
5
+ def get_lat_lon(postcodes_df, postcode_mapping):
6
+
7
+ try:
8
+
9
+ postcode_mapping.rename(columns={'postcode': 'Postal code'}, inplace=True)
10
+
11
+ # Normalize postcodes to ensure matching and count occurrences
12
+ postcodes_df['Postal code'] = postcodes_df['Postal code'].str.lower().str.replace(' ', '')
13
+ postcode_counts = postcodes_df['Postal code'].value_counts().reset_index()
14
+ postcode_counts.columns = ['Postal code', 'count']
15
+
16
+ # Normalize the postcodes in the mapping DataFrame
17
+ postcode_mapping['Postal code'] = postcode_mapping['Postal code'].str.lower().str.replace(' ', '')
18
+
19
+ # Merge the counts with the mapping data
20
+ result_df = pd.merge(postcode_counts, postcode_mapping, on='Postal code', how='left')
21
+
22
+ # Fill NaN values for latitude and longitude where postcode was not found in the mapping
23
+ result_df['latitude'] = result_df['latitude'].fillna('')
24
+ result_df['longitude'] = result_df['longitude'].fillna('')
25
+
26
+ # Optionally, convert the DataFrame to a dictionary if needed, or work directly with the DataFrame
27
+ results = result_df.to_dict(orient='records')
28
+
29
+ except:
30
+ raise gr.Error('Make sure your file contains the postal codes under a column named "Postal code"')
31
+
32
+ return results
gradio/requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ pandas==2.2.2
2
+ openpyxl==3.1.2
3
+ gradio==4.27.0
4
+ gradio_folium==0.0.6