Borya-Goldarb commited on
Commit
fab1d1c
·
verified ·
1 Parent(s): 4bb27eb

Update pages/market_rent_estimation.py

Browse files
Files changed (1) hide show
  1. pages/market_rent_estimation.py +172 -172
pages/market_rent_estimation.py CHANGED
@@ -11,207 +11,207 @@ import geopandas as gpd
11
 
12
 
13
  def main():
14
-     st.set_page_config(initial_sidebar_state="collapsed", layout="wide")
15
-     tab1, tab2 = st.tabs(["Comps", "Combined estimation"])#, "Market distributions", "Rexy"])
16
-  
17
-     distances_matrix = np.load('atlanta_matrix.npy')
18
-     df_properties = pd.read_csv("atlanta_data_new.csv", encoding='utf-8')
19
-  
20
-     # user's filter for property size is a range in percentage around picked property
21
-     min_size = (100 + st.session_state['min_property_lease_size_perc']) / 100 * st.session_state['building_sf']
22
-     max_size = (100 + st.session_state['max_property_lease_size_perc']) / 100 * st.session_state['building_sf']
23
 
24
  # user's filter for lease size is a range in percentage around picked lease
25
-     lease_min_size = (100 + st.session_state['min_property_size_perc']) / 100 * st.session_state['rented_sf']
26
-     lease_max_size = (100 + st.session_state['max_property_size_perc']) / 100 * st.session_state['rented_sf']
27
 
28
  #apply all filters
29
-     mask = (df_properties['rented_sf'] >= lease_min_size) & (df_properties['rented_sf'] <= lease_max_size) & (df_properties['building_sf'] >= min_size) & (df_properties['building_sf'] <= max_size) & (df_properties['months_since'] <= st.session_state['months_back']) 
30
-     df_properties_filtered = df_properties[mask]
31
-    
32
-     # create distances matrix for remaining rows
33
-     positions = np.nonzero(mask)[0]
34
-     distances_matrix_filtered = distances_matrix[np.ix_(positions, positions)]
35
-  
36
-     # row_index = df_properties_filtered.index.get_loc(st.session_state['user_select_value'])
37
-     df_properties_filtered = df_properties_filtered.reset_index()
38
-     row_index = (df_properties_filtered[df_properties_filtered['google_ola'] == st.session_state['user_select_value']].index)[0]
39
-     distances = distances_matrix_filtered[row_index]
40
-     sorted_indices = np.argsort(distances)
41
-     sorted_distances = distances[sorted_indices]
42
-     sorted_indexes = df_properties_filtered.index[sorted_indices]
43
-     reordered_df_properties_filtered = df_properties_filtered.loc[sorted_indexes]
44
-  
45
-        
46
-     #comps page
47
-     with tab1:
48
-         filtered_data = reordered_df_properties_filtered[["google_ola", "market_costar", "submarket_costar", "execution_date", "rented_sf", "building_sf", "year_built", "office_rate", "min_clear_height", "max_clear_height", "docks", "drive_ins", "rent_combined"]]#pd.concat([filtered_data2])
49
-         comps_scores = sorted_distances
50
-  
51
-         filtered_data.insert(loc=1, column='Similarity score', value=comps_scores)
52
-        
53
-         # Formatting the DataFrame
54
-         filtered_data['Similarity score'] = ((1 - filtered_data['Similarity score']) * 100).apply(lambda x: f"{x:.2f}")
55
-         filtered_data['execution_date'] = pd.to_datetime(filtered_data['execution_date']).dt.strftime('%m-%d-%Y')
56
-         filtered_data['LSF (sf)'] = filtered_data['rented_sf'].round(0).astype(int)
57
-         filtered_data['RSF (sf)'] = filtered_data['building_sf'].round(0).astype(int)
58
-         filtered_data['Year built'] = filtered_data['year_built'].astype(int)
59
-         filtered_data.loc[filtered_data['office_rate'].notna(), 'office_rate'] = (filtered_data.loc[filtered_data['office_rate'].notna(), 'office_rate'] * 100).apply(lambda x: f"{x:.2f} %")
60
-  
61
-         filtered_data.loc[filtered_data['min_clear_height'].notna(), 'min_clear_height'] = (filtered_data.loc[filtered_data['min_clear_height'].notna(), 'min_clear_height']).apply(lambda x: f"{int(x)}")
62
-         # filtered_data['Clear Height (feet)'] = filtered_data['min_clear_height'].round(0).astype(int)
63
   
64
-         filtered_data.loc[filtered_data['docks'].notna(), 'docks'] = (filtered_data.loc[filtered_data['docks'].notna(), 'docks']).apply(lambda x: f"{int(x)}")
65
-         filtered_data.loc[filtered_data['drive_ins'].notna(), 'drive_ins'] = (filtered_data.loc[filtered_data['drive_ins'].notna(), 'drive_ins']).apply(lambda x: f"{int(x)}")
66
-  
67
-         # filtered_data['Docks (/10ksf)'] = filtered_data['docks'].astype(int)
68
-         # filtered_data['Doors (/10ksf)'] = filtered_data['drive_ins'].astype(int)
69
-         filtered_data['Rent (NNN)'] = filtered_data['rent_combined'].apply(lambda x: f"${x:.2f}")
70
         
71
-         # Dropping old columns and renaming headers
72
-         filtered_data = filtered_data.drop(columns=['rented_sf', 'building_sf', 'year_built', 'max_clear_height', 'rent_combined'])
73
-         filtered_data = filtered_data.rename(columns={
74
-             'google_ola': 'Address',
75
-             'office_rate': 'Office %',
76
-             'min_clear_height': 'Clear Height (feet)',
77
-             'docks': 'Docks (/10ksf)',
78
-             'drive_ins': 'Doors (/10ksf)',
79
-             'market_costar': 'Market',
80
-             'submarket_costar': 'Submarket'
81
-         })
82
-         filtered_data = filtered_data.sort_values(by="Similarity score", ascending=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
         
84
         
85
-         # Display the filtered data
86
-         col_1_1, col_1_2 = st.columns([2, 1])
87
-         with col_1_1:
88
-             filtered_data['Similarity score'] = pd.to_numeric(filtered_data['Similarity score'], errors='coerce')
89
-             filtered_data['LSF (sf)'] = pd.to_numeric(filtered_data['LSF (sf)'], errors='coerce')
90
-             st.write('Comps list:')
91
-             filtered_data_sorted = filtered_data.sort_values(by="Similarity score", ascending=False)
 
 
 
 
 
 
 
 
 
 
92
             
93
-             # sort_column = st.selectbox('Select column to sort by:', filtered_data.columns[:])
94
-             # # display_df = st.table(filtered_data)
95
-             # if sort_column:
96
-             #     filtered_data_sorted = filtered_data.sort_values(by=sort_column, ascending=False)         
97
-             st.dataframe(filtered_data_sorted)
98
-  
99
-         with col_1_2:
100
-         # Create a map object
101
-             m = folium.Map(width=500, height=440, location=(reordered_df_properties_filtered['lat'].mean(), reordered_df_properties_filtered['long'].mean()), zoom_start=9)
102
-            
103
-             # Add markers to the map
104
-             all_markers = folium.FeatureGroup(name='All Markers')
105
-             active_markers = folium.FeatureGroup(name='Active Markers', show=False)
106
-             inactive_markers = folium.FeatureGroup(name='Inactive Markers', show=False)
107
                 
108
-             for index, row in reordered_df_properties_filtered.iterrows():
109
-                 status_color = 'green' if index==0 else 'red'
110
-                 html_content = f"""
111
-                 <div style="
112
-                     display: inline-block;
113
-                     background-color: white;
114
-                     border: 2px solid black;
115
-                     border-radius: 50%;
116
-                     width: 20px;
117
-                     height: 20px;
118
-                     text-align: center;
119
-                     line-height: 20px;
120
-                     font-size: 8pt;
121
-                     color: {status_color};
122
-                 ">{index}</div>
123
-                 """
124
                     
125
-                 # Create a DivIcon with custom HTML content
126
-                 icon = folium.DivIcon(html=html_content)
127
-                 marker = folium.Marker([row['lat'], row['long']], popup=row['google_ola'], icon=icon).add_to(m)
128
   
129
   
130
-             #add poligons on map
131
-             gdf = gpd.read_file('costar_sm_polygons.geojson')
132
-             gdf_Atlanta = gdf[gdf.full_submarket.str.contains("Atlanta")]
133
-             folium.GeoJson(data=gdf_Atlanta.geometry.to_json(), name='geojson').add_to(m)
134
              for _, row in gdf_Atlanta.iterrows():
135
-                 # Convert the row's geometry to GeoJSON
136
-                 geojson = folium.GeoJson(data=row['geometry'].__geo_interface__,
137
-                                          style_function=lambda feature: {
138
-                                                'fillColor': '#00000000',  # Make the fill color transparent
139
-                                                'color': '#00000000',             # Set the border color
140
-                                                'weight': 2                  # Set the border width
141
-                                              },                                        
142
-                                         )
143
-                 # Add a popup with the name
144
-                 popup = folium.Popup(row['full_submarket'], parse_html=True)
145
                 
146
-                 # Add the GeoJson and Popup to the map
147
-                 geojson.add_child(popup).add_to(m)
148
                     
149
-             # Add layer control to toggle marker visibility
150
-             folium.LayerControl().add_to(m)
151
             
152
-             # Render the map
153
-             folium_static(m)
154
   
155
-         back_to_serach_tab2 = st.button("Search page ")
156
-         if back_to_serach_tab2:
157
-             st.switch_page("app.py")
158
             
159
-     with tab2:
160
-         st.title('Combined estimation')
161
-         if 'user_select_value' not in st.session_state:
162
-             st.session_state['user_select_value'] = ""
163
-         if 'year_buit' not in st.session_state:
164
-             st.session_state['year_buit'] = ""
165
-         if 'submarket_val' not in st.session_state:
166
-             st.session_state['submarket_val'] = ""
167
-         if 'market_val' not in st.session_state:
168
-             st.session_state['market_val'] = ""
169
-  
170
-         box_contents = [
171
-             {"header": "Address", "content": st.session_state['user_select_value']},
172
-             {"header": "LSF", "content": str(st.session_state['rented_sf'])},
173
-             {"header": "Sub-Market", "content": st.session_state['submarket_val']},
174
-             {"header": "Market", "content": st.session_state['market_val']}
175
-         ]
176
-  
177
-         # Divide the layout into four columns
178
-         col1, col2, col3, col4 = st.columns(4)
179
         
180
-         for i, col in enumerate([col1, col2, col3, col4]):
181
-             col.markdown(f"""
182
-                 <div style="padding: 20px; margin: 10px; text-align: center;">
183
-                     <h3 style="font-size: small;">{box_contents[i]['header']}</h3>
184
-                     <p style="font-size: small;">{box_contents[i]['content']}</p>
185
-                 </div>
186
-             """, unsafe_allow_html=True)
187
             
188
-         # Add padding between the boxes and the slider
189
-         st.markdown('<style>div[data-testid="stBlock"]{margin-top: 20px;}</style>', unsafe_allow_html=True)
190
         
191
-         def safe_eval(val):
192
-             try:
193
-                 return ast.literal_eval(val)
194
-             except (ValueError, SyntaxError):
195
-                 return val
196
                  
197
-         average_rent = reordered_df_properties_filtered['rent_combined'].mean()
198
         
199
-         x1 ="Comps " + str(average_rent)
200
-         x3="Rent " + str(st.session_state['prediction'])
201
         
202
-         # x2 = (st.session_state['prediction']+average_rent)/2
203
         
204
-         pick = st.select_slider(
205
-         "Combined estimation ",
206
-         options=[x1, x3],
207
-         value=x1)
208
         
209
-         back_to_serach_tab1 = st.button("Search page")
210
-         if back_to_serach_tab1:
211
-             st.switch_page("app.py")
212
   
213
             
214
   
215
  if __name__ == "__main__":
216
-     main()
217
 
 
11
 
12
 
13
  def main():
14
+ st.set_page_config(initial_sidebar_state="collapsed", layout="wide")
15
+ tab1, tab2 = st.tabs(["Comps", "Combined estimation"])#, "Market distributions", "Rexy"])
16
+
17
+ distances_matrix = np.load('atlanta_matrix.npy')
18
+ df_properties = pd.read_csv("atlanta_data_new.csv", encoding='utf-8')
19
+
20
+ # user's filter for property size is a range in percentage around picked property
21
+ min_size = (100 + st.session_state['min_property_lease_size_perc']) / 100 * st.session_state['building_sf']
22
+ max_size = (100 + st.session_state['max_property_lease_size_perc']) / 100 * st.session_state['building_sf']
23
 
24
  # user's filter for lease size is a range in percentage around picked lease
25
+ lease_min_size = (100 + st.session_state['min_property_size_perc']) / 100 * st.session_state['rented_sf']
26
+ lease_max_size = (100 + st.session_state['max_property_size_perc']) / 100 * st.session_state['rented_sf']
27
 
28
  #apply all filters
29
+ mask = (df_properties['rented_sf'] >= lease_min_size) & (df_properties['rented_sf'] <= lease_max_size) & (df_properties['building_sf'] >= min_size) & (df_properties['building_sf'] <= max_size) & (df_properties['months_since'] <= st.session_state['months_back']) 
30
+ df_properties_filtered = df_properties[mask]
31
+
32
+ # create distances matrix for remaining rows
33
+ positions = np.nonzero(mask)[0]
34
+ distances_matrix_filtered = distances_matrix[np.ix_(positions, positions)]
35
+
36
+ # row_index = df_properties_filtered.index.get_loc(st.session_state['user_select_value'])
37
+ df_properties_filtered = df_properties_filtered.reset_index()
38
+ row_index = (df_properties_filtered[df_properties_filtered['google_ola'] == st.session_state['user_select_value']].index)[0]
39
+ distances = distances_matrix_filtered[row_index]
40
+ sorted_indices = np.argsort(distances)
41
+ sorted_distances = distances[sorted_indices]
42
+ sorted_indexes = df_properties_filtered.index[sorted_indices]
43
+ reordered_df_properties_filtered = df_properties_filtered.loc[sorted_indexes]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
   
 
 
 
 
 
 
45
         
46
+ #comps page
47
+ with tab1:
48
+ filtered_data = reordered_df_properties_filtered[["google_ola", "market_costar", "submarket_costar", "execution_date", "rented_sf", "building_sf", "year_built", "office_rate", "min_clear_height", "max_clear_height", "docks", "drive_ins", "rent_combined"]]#pd.concat([filtered_data2])
49
+ comps_scores = sorted_distances
50
+
51
+ filtered_data.insert(loc=1, column='Similarity score', value=comps_scores)
52
+
53
+ # Formatting the DataFrame
54
+ filtered_data['Similarity score'] = ((1 - filtered_data['Similarity score']) * 100).apply(lambda x: f"{x:.2f}")
55
+ filtered_data['execution_date'] = pd.to_datetime(filtered_data['execution_date']).dt.strftime('%m-%d-%Y')
56
+ filtered_data['LSF (sf)'] = filtered_data['rented_sf'].round(0).astype(int)
57
+ filtered_data['RSF (sf)'] = filtered_data['building_sf'].round(0).astype(int)
58
+ filtered_data['Year built'] = filtered_data['year_built'].astype(int)
59
+ filtered_data.loc[filtered_data['office_rate'].notna(), 'office_rate'] = (filtered_data.loc[filtered_data['office_rate'].notna(), 'office_rate'] * 100).apply(lambda x: f"{x:.2f} %")
60
+
61
+ filtered_data.loc[filtered_data['min_clear_height'].notna(), 'min_clear_height'] = (filtered_data.loc[filtered_data['min_clear_height'].notna(), 'min_clear_height']).apply(lambda x: f"{int(x)}")
62
+ # filtered_data['Clear Height (feet)'] = filtered_data['min_clear_height'].round(0).astype(int)
63
+
64
+ filtered_data.loc[filtered_data['docks'].notna(), 'docks'] = (filtered_data.loc[filtered_data['docks'].notna(), 'docks']).apply(lambda x: f"{int(x)}")
65
+ filtered_data.loc[filtered_data['drive_ins'].notna(), 'drive_ins'] = (filtered_data.loc[filtered_data['drive_ins'].notna(), 'drive_ins']).apply(lambda x: f"{int(x)}")
66
+
67
+ # filtered_data['Docks (/10ksf)'] = filtered_data['docks'].astype(int)
68
+ # filtered_data['Doors (/10ksf)'] = filtered_data['drive_ins'].astype(int)
69
+ filtered_data['Rent (NNN)'] = filtered_data['rent_combined'].apply(lambda x: f"${x:.2f}")
70
+
71
+ # Dropping old columns and renaming headers
72
+ filtered_data = filtered_data.drop(columns=['rented_sf', 'building_sf', 'year_built', 'max_clear_height', 'rent_combined'])
73
+ filtered_data = filtered_data.rename(columns={
74
+ 'google_ola': 'Address',
75
+ 'office_rate': 'Office %',
76
+ 'min_clear_height': 'Clear Height (feet)',
77
+ 'docks': 'Docks (/10ksf)',
78
+ 'drive_ins': 'Doors (/10ksf)',
79
+ 'market_costar': 'Market',
80
+ 'submarket_costar': 'Submarket'
81
+ })
82
+ filtered_data = filtered_data.sort_values(by="Similarity score", ascending=False)
83
         
84
         
85
+ # Display the filtered data
86
+ col_1_1, col_1_2 = st.columns([2, 1])
87
+ with col_1_1:
88
+ filtered_data['Similarity score'] = pd.to_numeric(filtered_data['Similarity score'], errors='coerce')
89
+ filtered_data['LSF (sf)'] = pd.to_numeric(filtered_data['LSF (sf)'], errors='coerce')
90
+ st.write('Comps list:')
91
+ filtered_data_sorted = filtered_data.sort_values(by="Similarity score", ascending=False)
92
+
93
+ # sort_column = st.selectbox('Select column to sort by:', filtered_data.columns[:])
94
+ # # display_df = st.table(filtered_data)
95
+ # if sort_column:
96
+ #     filtered_data_sorted = filtered_data.sort_values(by=sort_column, ascending=False)         
97
+ st.dataframe(filtered_data_sorted)
98
+  
99
+ with col_1_2:
100
+ # Create a map object
101
+ m = folium.Map(width=500, height=440, location=(reordered_df_properties_filtered['lat'].mean(), reordered_df_properties_filtered['long'].mean()), zoom_start=9)
102
             
103
+ # Add markers to the map
104
+ all_markers = folium.FeatureGroup(name='All Markers')
105
+ active_markers = folium.FeatureGroup(name='Active Markers', show=False)
106
+ inactive_markers = folium.FeatureGroup(name='Inactive Markers', show=False)
 
 
 
 
 
 
 
 
 
 
107
                 
108
+ for index, row in reordered_df_properties_filtered.iterrows():
109
+ status_color = 'green' if index==0 else 'red'
110
+ html_content = f"""
111
+ <div style="
112
+ display: inline-block;
113
+ background-color: white;
114
+ border: 2px solid black;
115
+ border-radius: 50%;
116
+ width: 20px;
117
+ height: 20px;
118
+ text-align: center;
119
+ line-height: 20px;
120
+ font-size: 8pt;
121
+ color: {status_color};
122
+ ">{index}</div>
123
+ """
124
                     
125
+ # Create a DivIcon with custom HTML content
126
+ icon = folium.DivIcon(html=html_content)
127
+ marker = folium.Marker([row['lat'], row['long']], popup=row['google_ola'], icon=icon).add_to(m)
128
   
129
   
130
+ #add poligons on map
131
+ gdf = gpd.read_file('costar_sm_polygons.geojson')
132
+ gdf_Atlanta = gdf[gdf.full_submarket.str.contains("Atlanta")]
133
+ folium.GeoJson(data=gdf_Atlanta.geometry.to_json(), name='geojson').add_to(m)
134
              for _, row in gdf_Atlanta.iterrows():
135
+ # Convert the row's geometry to GeoJSON
136
+ geojson = folium.GeoJson(data=row['geometry'].__geo_interface__,
137
+ style_function=lambda feature: {
138
+ 'fillColor': '#00000000',  # Make the fill color transparent
139
+ 'color': '#00000000',             # Set the border color
140
+ 'weight': 2                  # Set the border width
141
+ },                                        
142
+ )
143
+ # Add a popup with the name
144
+ popup = folium.Popup(row['full_submarket'], parse_html=True)
145
                 
146
+ # Add the GeoJson and Popup to the map
147
+ geojson.add_child(popup).add_to(m)
148
                     
149
+ # Add layer control to toggle marker visibility
150
+ folium.LayerControl().add_to(m)
151
             
152
+ # Render the map
153
+ folium_static(m)
154
   
155
+ back_to_serach_tab2 = st.button("Search page ")
156
+ if back_to_serach_tab2:
157
+ st.switch_page("app.py")
158
             
159
+ with tab2:
160
+ st.title('Combined estimation')
161
+ if 'user_select_value' not in st.session_state:
162
+ st.session_state['user_select_value'] = ""
163
+ if 'year_buit' not in st.session_state:
164
+ st.session_state['year_buit'] = ""
165
+ if 'submarket_val' not in st.session_state:
166
+ st.session_state['submarket_val'] = ""
167
+ if 'market_val' not in st.session_state:
168
+ st.session_state['market_val'] = ""
169
+  
170
+ box_contents = [
171
+ {"header": "Address", "content": st.session_state['user_select_value']},
172
+ {"header": "LSF", "content": str(st.session_state['rented_sf'])},
173
+ {"header": "Sub-Market", "content": st.session_state['submarket_val']},
174
+ {"header": "Market", "content": st.session_state['market_val']}
175
+ ]
176
+  
177
+ # Divide the layout into four columns
178
+ col1, col2, col3, col4 = st.columns(4)
179
         
180
+ for i, col in enumerate([col1, col2, col3, col4]):
181
+ col.markdown(f"""
182
+ <div style="padding: 20px; margin: 10px; text-align: center;">
183
+ <h3 style="font-size: small;">{box_contents[i]['header']}</h3>
184
+ <p style="font-size: small;">{box_contents[i]['content']}</p>
185
+ </div>
186
+ """, unsafe_allow_html=True)
187
             
188
+ # Add padding between the boxes and the slider
189
+ st.markdown('<style>div[data-testid="stBlock"]{margin-top: 20px;}</style>', unsafe_allow_html=True)
190
         
191
+ # def safe_eval(val):
192
+ #     try:
193
+ #         return ast.literal_eval(val)
194
+ #     except (ValueError, SyntaxError):
195
+ #         return val
196
                  
197
+ average_rent = reordered_df_properties_filtered['rent_combined'].mean()
198
         
199
+ x1 ="Comps " + str(average_rent)
200
+ x3="Rent " + str(st.session_state['prediction'])
201
         
202
+ # x2 = (st.session_state['prediction']+average_rent)/2
203
         
204
+ pick = st.select_slider(
205
+ "Combined estimation ",
206
+ options=[x1, x3],
207
+ value=x1)
208
         
209
+ back_to_serach_tab1 = st.button("Search page")
210
+ if back_to_serach_tab1:
211
+ st.switch_page("app.py")
212
   
213
             
214
   
215
  if __name__ == "__main__":
216
+ main()
217