# **Group 9 Final Project - Where Should I Open My Restaurant?**

##### Amy Park, Cesar Espinoza, Danny Gallegos, and Margarita Coronel

### **Background**
### In real estate, the three things that matter the most are location, location, and location. So in a bustling city like Austin, TX, how would a new restaurant choose its location? We have several business criteria a location should meet - saturation of the cuisine in a neighborhood among others - and offer a perspective on the competitive landscape for a new restaurant. For our use case, we will be opening a pizzeria in Austin, TX.
#### Note:
*   This analysis focuses on the competitive landscape only.  Factors such as real estate prices of locations or demographic data are not in scope

### **Executive Summary**
### This analysis was conducted using Yelp Academic Data in five steps (import data, clean data, explore data, measure competitive landscape of a given area, and result/conclusion).
### We import and clean the data to focus on restaurants in  Austin, Texas, then present our initial findings of the data in various visualizations such as histograms and geographical maps. We then focus on three sample areas to analyze the competitive landscape in theses areas, and based on our business critieria for measuring competitiveness offer our perspective on which is the most optimal of the sample group. In closing, we address further steps that will help make this analysis more robust.

### **1. Importing the Data**

#### **1.1 Import Data** - we used the publicly available Yelp academic data to import data via Google Drive, clean the dataset, and conduct this analysis

```python
import pandas as pd
import io
```

```python
from google.colab import drive
drive.mount('/content/drive')
```

    Mounted at /content/drive

```python
# Since the date is in json format we import the json library
import json
!
f = open('/content/drive/MyDrive/data/yelp_academic_dataset_business.json',)
f
```

    <_io.TextIOWrapper name='/content/drive/MyDrive/data/yelp_academic_dataset_business.json' mode='r' encoding='UTF-8'>

```python
# Uploading JSON data into data list
data1 = []
for line in open('/content/drive/MyDrive/data/yelp_academic_dataset_business.json', 'r'):
    data1.append(json.loads(line))
data1[0]
```

    {'address': '921 Pearl St',
     'attributes': {'Alcohol': "'beer_and_wine'",
      'Ambience': "{'touristy': False, 'hipster': False, 'romantic': False, 'divey': False, 'intimate': False, 'trendy': False, 'upscale': False, 'classy': False, 'casual': True}",
      'BikeParking': 'True',
      'BusinessAcceptsBitcoin': 'False',
      'BusinessAcceptsCreditCards': 'True',
      'BusinessParking': "{'garage': False, 'street': True, 'validated': False, 'lot': False, 'valet': False}",
      'Caters': 'True',
      'DogsAllowed': 'False',
      'GoodForMeal': "{'dessert': False, 'latenight': False, 'lunch': False, 'dinner': False, 'brunch': False, 'breakfast': False}",
      'HappyHour': 'True',
      'HasTV': 'True',
      'NoiseLevel': "u'average'",
      'OutdoorSeating': 'True',
      'RestaurantsAttire': "'casual'",
      'RestaurantsDelivery': 'None',
      'RestaurantsGoodForGroups': 'True',
      'RestaurantsPriceRange2': '2',
      'RestaurantsReservations': 'False',
      'RestaurantsTableService': 'True',
      'RestaurantsTakeOut': 'True',
      'WheelchairAccessible': 'True',
      'WiFi': "u'free'"},
     'business_id': '6iYb2HFDywm3zjuRg0shjw',
     'categories': 'Gastropubs, Food, Beer Gardens, Restaurants, Bars, American (Traditional), Beer Bar, Nightlife, Breweries',
     'city': 'Boulder',
     'hours': {'Friday': '11:0-23:0',
      'Monday': '11:0-23:0',
      'Saturday': '11:0-23:0',
      'Sunday': '11:0-23:0',
      'Thursday': '11:0-23:0',
      'Tuesday': '11:0-23:0',
      'Wednesday': '11:0-23:0'},
     'is_open': 1,
     'latitude': 40.0175444,
     'longitude': -105.2833481,
     'name': 'Oskar Blues Taproom',
     'postal_code': '80302',
     'review_count': 86,
     'stars': 4.0,
     'state': 'CO'}

#### **1.2 Exploring the Data and Creating a Dataframe**
#### We then explore the data to see what kind of attributes the dataset has and the format of the data. We then proceed to create a dataframe to store the data.

```python
# Exploring the data set's main keys
dict1 = data1[1]
dict1.keys()
```

    dict_keys(['business_id', 'name', 'address', 'city', 'state', 'postal_code', 'latitude', 'longitude', 'stars', 'review_count', 'is_open', 'attributes', 'categories', 'hours'])

```python
# Now that we know the dictionary keys we proceed to create a data frame with Pandas
df = pd.DataFrame(data1, columns=['business_id', 'name', 'address', 'city', 'state', 'postal_code', 'latitude', 'longitude', 'stars', 'review_count', 'is_open', 'attributes', 'categories', 'hours'])
df.head(1)
```

      business_id
      name
      address
      city
      state
      postal_code
      latitude
      longitude
      stars
      review_count
      is_open
      attributes
      categories
      hours

      0
      6iYb2HFDywm3zjuRg0shjw
      Oskar Blues Taproom
      921 Pearl St
      Boulder
      CO
      80302
      40.017544
      -105.283348
      4.0
      86
      1
      {'RestaurantsTableService': 'True', 'WiFi': 'u...
      Gastropubs, Food, Beer Gardens, Restaurants, B...
      {'Monday': '11:0-23:0', 'Tuesday': '11:0-23:0'...

      <button class="colab-df-convert" onclick="convertToInteractive('df-4fe10a91-c3ab-4c76-889b-f508bef60391')"
              title="Convert this dataframe to an interactive table."
              style="display:none;">

  <svg xmlns="http://www.w3.org/2000/svg" height="24px"viewBox="0 0 24 24"
       width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"/>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"/><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"/>
  </svg>
      </button>

```python
df.attributes[0]
```

    {'Alcohol': "'beer_and_wine'",
     'Ambience': "{'touristy': False, 'hipster': False, 'romantic': False, 'divey': False, 'intimate': False, 'trendy': False, 'upscale': False, 'classy': False, 'casual': True}",
     'BikeParking': 'True',
     'BusinessAcceptsBitcoin': 'False',
     'BusinessAcceptsCreditCards': 'True',
     'BusinessParking': "{'garage': False, 'street': True, 'validated': False, 'lot': False, 'valet': False}",
     'Caters': 'True',
     'DogsAllowed': 'False',
     'GoodForMeal': "{'dessert': False, 'latenight': False, 'lunch': False, 'dinner': False, 'brunch': False, 'breakfast': False}",
     'HappyHour': 'True',
     'HasTV': 'True',
     'NoiseLevel': "u'average'",
     'OutdoorSeating': 'True',
     'RestaurantsAttire': "'casual'",
     'RestaurantsDelivery': 'None',
     'RestaurantsGoodForGroups': 'True',
     'RestaurantsPriceRange2': '2',
     'RestaurantsReservations': 'False',
     'RestaurantsTableService': 'True',
     'RestaurantsTakeOut': 'True',
     'WheelchairAccessible': 'True',
     'WiFi': "u'free'"}

```python
cat2 = df.categories[0]
cat2
```

    'Gastropubs, Food, Beer Gardens, Restaurants, Bars, American (Traditional), Beer Bar, Nightlife, Breweries'

### **2. Cleaning the Data**

#### **2.1 Filtering only for Austin, TX restaurants**

```python
#Filtering to open TX businesses and Austin within
tx_business =  df[df['state']=='TX']
tx_business_open = tx_business[tx_business['is_open']==1]
austin_business = tx_business_open[tx_business_open['city']=='Austin']
austin_business.head(5)
```

      business_id
      name
      address
      city
      state
      postal_code
      latitude
      longitude
      stars
      review_count
      is_open
      attributes
      categories
      hours

      8
      N3_Gs3DnX4k9SgpwJxdEfw
      Lane Wells Jewelry Repair
      7801 N Lamar Blvd, Ste A140
      Austin
      TX
      78752
      30.346169
      -97.711458
      5.0
      30
      1
      {'RestaurantsPriceRange2': '1', 'ByAppointment...
      Shopping, Jewelry Repair, Appraisal Services, ...
      {'Monday': '12:15-17:0', 'Tuesday': '12:15-17:...

      24
      nTIhpR7MhsALPwg_Hh14EA
      DoubleTree by Hilton Hotel Austin
      6505 N Interstate 35
      Austin
      TX
      78752
      30.326377
      -97.704543
      3.0
      139
      1
      {'WiFi': 'u'free'', 'RestaurantsPriceRange2': ...
      Hotels, Hotels & Travel, Event Planning & Serv...
      {'Monday': '0:0-0:0', 'Tuesday': '0:0-0:0', 'W...

      27
      8XyEpVdAO0o6iVkVxkWosQ
      PS Property Management Company
      2506 S Lamar Blvd, Ste 2
      Austin
      TX
      78704
      30.246465
      -97.778738
      4.5
      9
      1
      {'BusinessAcceptsCreditCards': 'True'}
      Home Services, Real Estate, Property Management
      {'Monday': '9:0-17:0', 'Tuesday': '9:0-17:0', ...

      37
      NVfOn7TdnHbaGH97CVB_Qg
      McKinley Chiropractic
      5625 Eiger Rd, Ste 160
      Austin
      TX
      78735
      30.244902
      -97.857409
      5.0
      5
      1
      {'BusinessAcceptsCreditCards': 'True', 'Accept...
      Chiropractors, Health & Medical
      {'Monday': '9:0-17:45', 'Tuesday': '12:0-17:45...

      39
      s8eTWEtW5WcnL2kUxrOVmw
      Austin Regional Clinic: ARC Quarry Lake
      4515 Seton Center Pkwy, Ste 220
      Austin
      TX
      78759
      30.401657
      -97.742943
      3.5
      48
      1
      {'ByAppointmentOnly': 'True', 'AcceptsInsuranc...
      Diagnostic Services, Doctors, Internal Medicin...
      {'Monday': '8:0-17:0', 'Tuesday': '8:0-17:0', ...

      <button class="colab-df-convert" onclick="convertToInteractive('df-629c95e3-27c5-430f-bb47-03ad82c2217d')"
              title="Convert this dataframe to an interactive table."
              style="display:none;">

  <svg xmlns="http://www.w3.org/2000/svg" height="24px"viewBox="0 0 24 24"
       width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"/>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"/><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"/>
  </svg>
      </button>

```python
# Filtering to Austin-only Restaurants
austin_restaurants = austin_business[austin_business['categories'].str.contains("Restaurants", na=False)]
austin_restaurants.head(5)
```

      business_id
      name
      address
      city
      state
      postal_code
      latitude
      longitude
      stars
      review_count
      is_open
      attributes
      categories
      hours

      41
      NRPemqVb4qpWFF0Avq_6OQ
      Eurasia Sushi Bar & Seafood
      7101 W Hwy 71, Ste C-13
      Austin
      TX
      78735
      30.234533
      -97.877262
      4.5
      395
      1
      {'Ambience': '{'touristy': False, 'hipster': F...
      Bars, Nightlife, Cocktail Bars, Seafood, Resta...
      {'Monday': '0:0-0:0', 'Tuesday': '11:0-22:0', ...

      61
      bRsDZ44CD3uhGnRY3NeQhQ
      Wendy's
      6247 Mcneil Drive
      Austin
      TX
      78729
      30.441875
      -97.746581
      2.0
      46
      1
      {'RestaurantsPriceRange2': '1', 'OutdoorSeatin...
      Fast Food, Restaurants, Burgers
      {'Monday': '6:30-1:0', 'Tuesday': '6:30-1:0', ...

      199
      Pk4ZwXwUU50BDn5gqw_rKg
      Johnny Carino's
      9500 S IH-35 Service Rd
      Austin
      TX
      78748
      30.162081
      -97.789132
      3.0
      136
      1
      {'RestaurantsGoodForGroups': 'True', 'Business...
      Italian, Salad, Pizza, Nightlife, Restaurants,...
      {'Monday': '11:0-21:30', 'Tuesday': '11:0-21:3...

      253
      Ieelu69Y23nbjKG3OGfwnw
      McDonald's
      5017 Hwy 290 W
      Austin
      TX
      78735
      30.232133
      -97.823183
      1.5
      9
      1
      {'RestaurantsTakeOut': 'True', 'RestaurantsRes...
      Restaurants, Coffee & Tea, Food, Burgers, Fast...
      {'Monday': '7:0-22:30', 'Tuesday': '7:0-22:30'...

      258
      IFB2K3BEZ2L_Mv5AbUD26Q
      Chispas
      214 W 4th St
      Austin
      TX
      78701
      30.266996
      -97.745362
      3.5
      119
      1
      {'RestaurantsTakeOut': 'True', 'OutdoorSeating...
      Tex-Mex, Mexican, Tacos, Restaurants
      {'Monday': '11:0-22:0', 'Tuesday': '11:0-22:0'...

      <button class="colab-df-convert" onclick="convertToInteractive('df-336f5ed7-bbd6-41c7-836f-3b047e564b08')"
              title="Convert this dataframe to an interactive table."
              style="display:none;">

  <svg xmlns="http://www.w3.org/2000/svg" height="24px"viewBox="0 0 24 24"
       width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"/>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"/><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"/>
  </svg>
      </button>

```python
# Restricting data to Pizza joints
pizza_joint = austin_restaurants[austin_restaurants['categories'].str.contains("Pizza|Pizzeria|pizza|pizzeria", na=False)]
pizza_joint.head(5)
```

      business_id
      name
      address
      city
      state
      postal_code
      latitude
      longitude
      stars
      review_count
      is_open
      attributes
      categories
      hours

      199
      Pk4ZwXwUU50BDn5gqw_rKg
      Johnny Carino's
      9500 S IH-35 Service Rd
      Austin
      TX
      78748
      30.162081
      -97.789132
      3.0
      136
      1
      {'RestaurantsGoodForGroups': 'True', 'Business...
      Italian, Salad, Pizza, Nightlife, Restaurants,...
      {'Monday': '11:0-21:30', 'Tuesday': '11:0-21:3...

      267
      fBvQQUk1-V9IUA8PbuYFWg
      Newk's Eatery
      408 Congress Ave
      Austin
      TX
      78701
      30.266639
      -97.743659
      3.5
      43
      1
      {'HasTV': 'True', 'BusinessParking': '{'garage...
      Pizza, Restaurants, American (Traditional), Am...
      {'Monday': '0:0-0:0', 'Tuesday': '10:30-18:0',...

      1354
      DSEsFWzM3UCq54E2X0P9Zg
      Mangieri's Pizza Cafe
      5900 W Slaughter Ln
      Austin
      TX
      78749
      30.201336
      -97.878995
      4.0
      237
      1
      {'RestaurantsTakeOut': 'True', 'Alcohol': 'u'f...
      Restaurants, Pizza, Italian
      {'Monday': '11:0-21:0', 'Tuesday': '11:0-21:0'...

      1857
      p99DZXmdF7smudK9FnlC9A
      Spartan Pizza
      1007 E 6th St
      Austin
      TX
      78702
      30.264940
      -97.732093
      4.0
      264
      1
      {'BusinessAcceptsCreditCards': 'True', 'Restau...
      Food Trucks, Pizza, Salad, Sandwiches, Food, E...
      {'Monday': '0:0-0:0', 'Tuesday': '11:0-22:0', ...

      2886
      zIrE7JvF0xVprDjbnL4PDQ
      J Clips
      900 E Braker Ln
      Austin
      TX
      78753
      30.376738
      -97.673122
      3.0
      15
      1
      {'BusinessAcceptsCreditCards': 'False', 'ByApp...
      Beauty & Spas, Barbers, Pizza, Restaurants
      {'Monday': '9:0-20:0', 'Tuesday': '9:0-20:0', ...

      <button class="colab-df-convert" onclick="convertToInteractive('df-26a3fc66-cc43-46fe-8d28-ddad05643c7f')"
              title="Convert this dataframe to an interactive table."
              style="display:none;">

  <svg xmlns="http://www.w3.org/2000/svg" height="24px"viewBox="0 0 24 24"
       width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"/>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"/><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"/>
  </svg>
      </button>

#### **2.2 Visualizing all of the pizza joints in the data source**

```python
# Getting a scatter plot of the pizza joints in all of Austin
pizza_joint.plot(
    kind='scatter',
    x='longitude',
    y='latitude',
    figsize = (10,10)
)
```

### **3. First Look at Clean Data - Analysis**
### We analyze the clean data by visualizing the Austin, TX restaurant data

#### **3.1 Where are the pizzerias in Austin?**

```python
! pip3 install -U geopandas fiona shapely pyproj geopy pysal descartes
```

    Collecting geopandas
      Downloading geopandas-0.10.2-py2.py3-none-any.whl (1.0 MB)
         |████████████████████████████████| 1.0 MB 12.8 MB/s
    Collecting fiona
      Downloading Fiona-1.8.21-cp37-cp37m-manylinux2014_x86_64.whl (16.7 MB)
         |████████████████████████████████| 16.7 MB 41.8 MB/s
    Requirement already satisfied: shapely in /usr/local/lib/python3.7/dist-packages (1.8.1.post1)
    Collecting pyproj
      Downloading pyproj-3.2.1-cp37-cp37m-manylinux2010_x86_64.whl (6.3 MB)
         |████████████████████████████████| 6.3 MB 77.9 MB/s
    Requirement already satisfied: geopy in /usr/local/lib/python3.7/dist-packages (1.17.0)
    Collecting geopy
      Downloading geopy-2.2.0-py3-none-any.whl (118 kB)
         |████████████████████████████████| 118 kB 71.6 MB/s
    Collecting pysal
      Downloading pysal-2.6.0-py3-none-any.whl (17 kB)
    Requirement already satisfied: descartes in /usr/local/lib/python3.7/dist-packages (1.1.0)
    Requirement already satisfied: pandas>=0.25.0 in /usr/local/lib/python3.7/dist-packages (from geopandas) (1.3.5)
    Requirement already satisfied: six>=1.7 in /usr/local/lib/python3.7/dist-packages (from fiona) (1.15.0)
    Requirement already satisfied: click>=4.0 in /usr/local/lib/python3.7/dist-packages (from fiona) (7.1.2)
    Collecting cligj>=0.5
      Downloading cligj-0.7.2-py3-none-any.whl (7.1 kB)
    Requirement already satisfied: attrs>=17 in /usr/local/lib/python3.7/dist-packages (from fiona) (21.4.0)
    Requirement already satisfied: certifi in /usr/local/lib/python3.7/dist-packages (from fiona) (2021.10.8)
    Collecting munch
      Downloading munch-2.5.0-py2.py3-none-any.whl (10 kB)
    Collecting click-plugins>=1.0
      Downloading click_plugins-1.1.1-py2.py3-none-any.whl (7.5 kB)
    Requirement already satisfied: setuptools in /usr/local/lib/python3.7/dist-packages (from fiona) (57.4.0)
    Requirement already satisfied: python-dateutil>=2.7.3 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.25.0->geopandas) (2.8.2)
    Requirement already satisfied: numpy>=1.17.3 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.25.0->geopandas) (1.21.6)
    Requirement already satisfied: pytz>=2017.3 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.25.0->geopandas) (2022.1)
    Requirement already satisfied: geographiclib<2,>=1.49 in /usr/local/lib/python3.7/dist-packages (from geopy) (1.52)
    Collecting segregation>=2.1.0
      Downloading segregation-2.2.3-py3-none-any.whl (147 kB)
         |████████████████████████████████| 147 kB 70.9 MB/s
    Collecting mgwr>=2.1.2
      Downloading mgwr-2.1.2.tar.gz (41 kB)
         |████████████████████████████████| 41 kB 529 kB/s
    Collecting spint>=1.0.7
      Downloading spint-1.0.7.tar.gz (28 kB)
    Collecting mapclassify>=2.4.3
      Downloading mapclassify-2.4.3-py3-none-any.whl (38 kB)
    Collecting spopt>=0.2.1
      Downloading spopt-0.3.0-py3-none-any.whl (83 kB)
         |████████████████████████████████| 83 kB 2.1 MB/s
    Collecting momepy>=0.5.2
      Downloading momepy-0.5.3-py3-none-any.whl (243 kB)
         |████████████████████████████████| 243 kB 76.0 MB/s
    Collecting spvcm>=0.3.0
      Downloading spvcm-0.3.0.tar.gz (5.7 MB)
         |████████████████████████████████| 5.7 MB 40.7 MB/s
    Collecting giddy>=2.3.3
      Downloading giddy-2.3.3-py3-none-any.whl (60 kB)
         |████████████████████████████████| 60 kB 7.8 MB/s
    Collecting tobler>=0.8.2
      Downloading tobler-0.9.0-py3-none-any.whl (22 kB)
    Collecting esda>=2.4.1
      Downloading esda-2.4.1.tar.gz (95 kB)
         |████████████████████████████████| 95 kB 4.4 MB/s
    Collecting inequality>=1.0.0
      Downloading inequality-1.0.0.tar.gz (11 kB)
    Collecting spglm>=1.0.8
      Downloading spglm-1.0.8.tar.gz (37 kB)
    Collecting spaghetti>=1.6.5
      Downloading spaghetti-1.6.5-py3-none-any.whl (46 kB)
         |████████████████████████████████| 46 kB 3.7 MB/s
    Collecting spreg>=1.2.4
      Downloading spreg-1.2.4-py3-none-any.whl (209 kB)
         |████████████████████████████████| 209 kB 73.1 MB/s
    Collecting splot>=1.1.4
      Downloading splot-1.1.5.post1-py3-none-any.whl (39 kB)
    Collecting libpysal>=4.6.0
      Downloading libpysal-4.6.2-py3-none-any.whl (2.4 MB)
         |████████████████████████████████| 2.4 MB 62.2 MB/s
    Collecting access>=1.1.3
      Downloading access-1.1.3-py3-none-any.whl (21 kB)
    Collecting pointpats>=2.2.0
      Downloading pointpats-2.2.0.tar.gz (55 kB)
         |████████████████████████████████| 55 kB 4.0 MB/s
    Requirement already satisfied: scipy>=0.11 in /usr/local/lib/python3.7/dist-packages (from esda>=2.4.1->pysal) (1.4.1)
    Requirement already satisfied: scikit-learn in /usr/local/lib/python3.7/dist-packages (from esda>=2.4.1->pysal) (1.0.2)
    Collecting quantecon>=0.4.7
      Downloading quantecon-0.5.3-py3-none-any.whl (179 kB)
         |████████████████████████████████| 179 kB 63.6 MB/s
    Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from libpysal>=4.6.0->pysal) (2.23.0)
    Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.7/dist-packages (from libpysal>=4.6.0->pysal) (4.6.3)
    Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from libpysal>=4.6.0->pysal) (21.3)
    Requirement already satisfied: appdirs in /usr/local/lib/python3.7/dist-packages (from libpysal>=4.6.0->pysal) (1.4.4)
    Requirement already satisfied: jinja2 in /usr/local/lib/python3.7/dist-packages (from libpysal>=4.6.0->pysal) (2.11.3)
    Requirement already satisfied: networkx in /usr/local/lib/python3.7/dist-packages (from mapclassify>=2.4.3->pysal) (2.6.3)
    Requirement already satisfied: tqdm>=4.27.0 in /usr/local/lib/python3.7/dist-packages (from momepy>=0.5.2->pysal) (4.64.0)
    Collecting pygeos
      Downloading pygeos-0.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.1 MB)
         |████████████████████████████████| 2.1 MB 60.2 MB/s
    Requirement already satisfied: matplotlib in /usr/local/lib/python3.7/dist-packages (from pointpats>=2.2.0->pysal) (3.2.2)
    Collecting opencv-contrib-python>=4.2.0
      Downloading opencv_contrib_python-4.5.5.64-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (66.7 MB)
         |████████████████████████████████| 66.7 MB 1.2 MB/s
    Requirement already satisfied: sympy in /usr/local/lib/python3.7/dist-packages (from quantecon>=0.4.7->giddy>=2.3.3->pysal) (1.7.1)
    Requirement already satisfied: numba in /usr/local/lib/python3.7/dist-packages (from quantecon>=0.4.7->giddy>=2.3.3->pysal) (0.51.2)
    Requirement already satisfied: seaborn in /usr/local/lib/python3.7/dist-packages (from segregation>=2.1.0->pysal) (0.11.2)
    Requirement already satisfied: pip in /usr/local/lib/python3.7/dist-packages (from segregation>=2.1.0->pysal) (21.1.3)
    Collecting quilt3
      Downloading quilt3-5.0.0-py3-none-any.whl (78 kB)
         |████████████████████████████████| 78 kB 7.4 MB/s
    Collecting deprecation
      Downloading deprecation-2.1.0-py2.py3-none-any.whl (11 kB)
    Collecting rvlib>=0.0.5
      Downloading rvlib-0.0.6.tar.gz (183 kB)
         |████████████████████████████████| 183 kB 76.9 MB/s
    Requirement already satisfied: joblib in /usr/local/lib/python3.7/dist-packages (from segregation>=2.1.0->pysal) (1.1.0)
    Requirement already satisfied: cffi>=1.0.0 in /usr/local/lib/python3.7/dist-packages (from rvlib>=0.0.5->segregation>=2.1.0->pysal) (1.15.0)
    Requirement already satisfied: PyYAML in /usr/local/lib/python3.7/dist-packages (from rvlib>=0.0.5->segregation>=2.1.0->pysal) (3.13)
    Requirement already satisfied: pycparser in /usr/local/lib/python3.7/dist-packages (from cffi>=1.0.0->rvlib>=0.0.5->segregation>=2.1.0->pysal) (2.21)
    Requirement already satisfied: llvmlite<0.35,>=0.34.0.dev0 in /usr/local/lib/python3.7/dist-packages (from numba->quantecon>=0.4.7->giddy>=2.3.3->pysal) (0.34.0)
    Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.7/dist-packages (from scikit-learn->esda>=2.4.1->pysal) (3.1.0)
    Collecting rtree
      Downloading Rtree-1.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.0 MB)
         |████████████████████████████████| 1.0 MB 61.7 MB/s
    Collecting pulp
      Downloading PuLP-2.6.0-py3-none-any.whl (14.2 MB)
         |████████████████████████████████| 14.2 MB 54.9 MB/s
    Requirement already satisfied: statsmodels in /usr/local/lib/python3.7/dist-packages (from tobler>=0.8.2->pysal) (0.10.2)
    Collecting rasterstats
      Downloading rasterstats-0.16.0-py3-none-any.whl (16 kB)
    Collecting rasterio
      Downloading rasterio-1.2.10-cp37-cp37m-manylinux1_x86_64.whl (19.3 MB)
         |████████████████████████████████| 19.3 MB 597 kB/s
    Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.7/dist-packages (from jinja2->libpysal>=4.6.0->pysal) (2.0.1)
    Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib->pointpats>=2.2.0->pysal) (3.0.8)
    Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.7/dist-packages (from matplotlib->pointpats>=2.2.0->pysal) (0.11.0)
    Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib->pointpats>=2.2.0->pysal) (1.4.2)
    Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from kiwisolver>=1.0.1->matplotlib->pointpats>=2.2.0->pysal) (4.1.1)
    Collecting jsonlines==1.2.0
      Downloading jsonlines-1.2.0-py2.py3-none-any.whl (7.6 kB)
    Collecting boto3>=1.10.0
      Downloading boto3-1.21.45-py3-none-any.whl (132 kB)
         |████████████████████████████████| 132 kB 84.6 MB/s
    Collecting aws-requests-auth>=0.4.2
      Downloading aws_requests_auth-0.4.3-py2.py3-none-any.whl (6.8 kB)
    Requirement already satisfied: tenacity>=5.1.1 in /usr/local/lib/python3.7/dist-packages (from quilt3->segregation>=2.1.0->pysal) (8.0.1)
    Collecting PyYAML
      Downloading PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (596 kB)
         |████████████████████████████████| 596 kB 83.2 MB/s
    Collecting requests-futures==1.0.0
      Downloading requests_futures-1.0.0-py2.py3-none-any.whl (7.4 kB)
    Requirement already satisfied: jsonschema<5,>=3 in /usr/local/lib/python3.7/dist-packages (from quilt3->segregation>=2.1.0->pysal) (4.3.3)
    Collecting botocore<1.25.0,>=1.24.45
      Downloading botocore-1.24.45-py3-none-any.whl (8.7 MB)
         |████████████████████████████████| 8.7 MB 55.5 MB/s
    Collecting s3transfer<0.6.0,>=0.5.0
      Downloading s3transfer-0.5.2-py3-none-any.whl (79 kB)
         |████████████████████████████████| 79 kB 8.1 MB/s
    Collecting jmespath<2.0.0,>=0.7.1
      Downloading jmespath-1.0.0-py3-none-any.whl (23 kB)
    Collecting urllib3<1.27,>=1.25.4
      Downloading urllib3-1.26.9-py2.py3-none-any.whl (138 kB)
         |████████████████████████████████| 138 kB 86.7 MB/s
    Requirement already satisfied: pyrsistent!=0.17.0,!=0.17.1,!=0.17.2,>=0.14.0 in /usr/local/lib/python3.7/dist-packages (from jsonschema<5,>=3->quilt3->segregation>=2.1.0->pysal) (0.18.1)
    Requirement already satisfied: importlib-metadata in /usr/local/lib/python3.7/dist-packages (from jsonschema<5,>=3->quilt3->segregation>=2.1.0->pysal) (4.11.3)
    Requirement already satisfied: importlib-resources>=1.4.0 in /usr/local/lib/python3.7/dist-packages (from jsonschema<5,>=3->quilt3->segregation>=2.1.0->pysal) (5.7.0)
    Requirement already satisfied: zipp>=3.1.0 in /usr/local/lib/python3.7/dist-packages (from importlib-resources>=1.4.0->jsonschema<5,>=3->quilt3->segregation>=2.1.0->pysal) (3.8.0)
    Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->libpysal>=4.6.0->pysal) (2.10)
      Downloading urllib3-1.25.11-py2.py3-none-any.whl (127 kB)
         |████████████████████████████████| 127 kB 78.1 MB/s
    Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->libpysal>=4.6.0->pysal) (3.0.4)
    Collecting snuggs>=1.4.1
      Downloading snuggs-1.4.7-py3-none-any.whl (5.4 kB)
    Collecting affine
      Downloading affine-2.3.1-py2.py3-none-any.whl (16 kB)
    Collecting simplejson
      Downloading simplejson-3.17.6-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (130 kB)
         |████████████████████████████████| 130 kB 64.9 MB/s
    Requirement already satisfied: patsy>=0.4.0 in /usr/local/lib/python3.7/dist-packages (from statsmodels->tobler>=0.8.2->pysal) (0.5.2)
    Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy->quantecon>=0.4.7->giddy>=2.3.3->pysal) (1.2.1)
    Building wheels for collected packages: esda, inequality, mgwr, pointpats, rvlib, spglm, spint, spvcm
      Building wheel for esda (setup.py) ... done
      Created wheel for esda: filename=esda-2.4.1-py3-none-any.whl size=117429 sha256=7dddd4ef65fc26d8e475f267da4e958026a2659d9e8f03ceebca19f955b61d1d
      Stored in directory: /root/.cache/pip/wheels/ed/67/c5/4558a178be4c410f341c31f71b5aba9c761a40c9d17dbdfddd
      Building wheel for inequality (setup.py) ... done
      Created wheel for inequality: filename=inequality-1.0.0-py3-none-any.whl size=11800 sha256=05b7bbcd472dc5621886de8b78c861811bba4ea0cb865095d44133416c725544
      Stored in directory: /root/.cache/pip/wheels/a8/81/7a/af8b9e8ea0b034ac1bdd9d68f3a8ceac179eb5418cdb83c851
      Building wheel for mgwr (setup.py) ... done
      Created wheel for mgwr: filename=mgwr-2.1.2-py3-none-any.whl size=46386 sha256=7578085f27042f21d743405661d6d22c2caf580e3f6426b0d604043bddf7f400
      Stored in directory: /root/.cache/pip/wheels/e8/55/57/c1bf993ab0ab4b9885ac1fdf7f9f960397355cf889b77a3e4b
      Building wheel for pointpats (setup.py) ... done
      Created wheel for pointpats: filename=pointpats-2.2.0-py3-none-any.whl size=60835 sha256=30ea038b6cc1df65e6b0e565fc1226ce47b7b657fd1ebf8709c71d17c46cdbf3
      Stored in directory: /root/.cache/pip/wheels/41/5f/91/08cc68af630fafdc6bed36128abf8e716e062256a8495fdb2d
      Building wheel for rvlib (setup.py) ... done
      Created wheel for rvlib: filename=rvlib-0.0.6-cp37-cp37m-linux_x86_64.whl size=352493 sha256=4bac3dc964e120a493e91d43ff768a7204ceb9b4644e2a44c7d4b8d4b5c356c6
      Stored in directory: /root/.cache/pip/wheels/8e/fe/cb/66b78310be88014dfbe1a21391c873a9fe49dca403f7d9f454
      Building wheel for spglm (setup.py) ... done
      Created wheel for spglm: filename=spglm-1.0.8-py3-none-any.whl size=38806 sha256=268236637bf849a5669acc6814bc8a733f6b8b3d84a1b899a14d87ab102fff9e
      Stored in directory: /root/.cache/pip/wheels/29/79/e9/453e3b0d858bed16e097c6e6bbd75e2b966bfcfb21b12790d0
      Building wheel for spint (setup.py) ... done
      Created wheel for spint: filename=spint-1.0.7-py3-none-any.whl size=31383 sha256=c7ce46d6eaeca41572310ab4cdacb6ea39ca8a8ff6cdcb1396132687a86925b7
      Stored in directory: /root/.cache/pip/wheels/dd/ac/5d/25d69231f3bffa2cb47ce29bb7eac9df9246aa9ba286a03a2d
      Building wheel for spvcm (setup.py) ... done
      Created wheel for spvcm: filename=spvcm-0.3.0-py3-none-any.whl size=5777202 sha256=1fd0c5770939deed0fcfe3a97c94f3c3c9583b63e16435191a7b702c18299a0b
      Stored in directory: /root/.cache/pip/wheels/a4/85/1a/d890ef4d2eaca2788e45925fa531bb58a2138734065abdfe08
    Successfully built esda inequality mgwr pointpats rvlib spglm spint spvcm
    Installing collected packages: urllib3, jmespath, botocore, snuggs, s3transfer, munch, libpysal, cligj, click-plugins, affine, spreg, simplejson, rtree, requests-futures, rasterio, quantecon, PyYAML, pyproj, mapclassify, jsonlines, fiona, esda, boto3, aws-requests-auth, spglm, spaghetti, rvlib, rasterstats, quilt3, pygeos, pulp, opencv-contrib-python, giddy, geopandas, deprecation, tobler, spvcm, spopt, splot, spint, segregation, pointpats, momepy, mgwr, inequality, access, pysal, geopy
      Attempting uninstall: urllib3
        Found existing installation: urllib3 1.24.3
        Uninstalling urllib3-1.24.3:
          Successfully uninstalled urllib3-1.24.3
      Attempting uninstall: PyYAML
        Found existing installation: PyYAML 3.13
        Uninstalling PyYAML-3.13:
          Successfully uninstalled PyYAML-3.13
      Attempting uninstall: opencv-contrib-python
        Found existing installation: opencv-contrib-python 4.1.2.30
        Uninstalling opencv-contrib-python-4.1.2.30:
          Successfully uninstalled opencv-contrib-python-4.1.2.30
      Attempting uninstall: geopy
        Found existing installation: geopy 1.17.0
        Uninstalling geopy-1.17.0:
          Successfully uninstalled geopy-1.17.0
    ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
    datascience 0.10.6 requires folium==0.2.1, but you have folium 0.8.3 which is incompatible.
    Successfully installed PyYAML-6.0 access-1.1.3 affine-2.3.1 aws-requests-auth-0.4.3 boto3-1.21.45 botocore-1.24.45 click-plugins-1.1.1 cligj-0.7.2 deprecation-2.1.0 esda-2.4.1 fiona-1.8.21 geopandas-0.10.2 geopy-2.2.0 giddy-2.3.3 inequality-1.0.0 jmespath-1.0.0 jsonlines-1.2.0 libpysal-4.6.2 mapclassify-2.4.3 mgwr-2.1.2 momepy-0.5.3 munch-2.5.0 opencv-contrib-python-4.5.5.64 pointpats-2.2.0 pulp-2.6.0 pygeos-0.12.0 pyproj-3.2.1 pysal-2.6.0 quantecon-0.5.3 quilt3-5.0.0 rasterio-1.2.10 rasterstats-0.16.0 requests-futures-1.0.0 rtree-1.0.0 rvlib-0.0.6 s3transfer-0.5.2 segregation-2.2.3 simplejson-3.17.6 snuggs-1.4.7 spaghetti-1.6.5 spglm-1.0.8 spint-1.0.7 splot-1.1.5.post1 spopt-0.3.0 spreg-1.2.4 spvcm-0.3.0 tobler-0.9.0 urllib3-1.25.11

```python
!sudo apt-get install -y libgeos-dev python3-rtree
import geopandas as gpd
```

    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    libgeos-dev is already the newest version (3.6.2-1build2).
    libgeos-dev set to manually installed.
    The following additional packages will be installed:
      libspatialindex-c4v5 libspatialindex-dev libspatialindex4v5
      python3-pkg-resources
    Suggested packages:
      python3-setuptools
    The following NEW packages will be installed:
      libspatialindex-c4v5 libspatialindex-dev libspatialindex4v5
      python3-pkg-resources python3-rtree
    0 upgraded, 5 newly installed, 0 to remove and 40 not upgraded.
    Need to get 671 kB of archives.
    After this operation, 3,948 kB of additional disk space will be used.
    Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libspatialindex4v5 amd64 1.8.5-5 [219 kB]
    Get:2 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libspatialindex-c4v5 amd64 1.8.5-5 [51.7 kB]
    Get:3 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-pkg-resources all 39.0.1-2 [98.8 kB]
    Get:4 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libspatialindex-dev amd64 1.8.5-5 [285 kB]
    Get:5 http://archive.ubuntu.com/ubuntu bionic/universe amd64 python3-rtree all 0.8.3+ds-1 [16.9 kB]
    Fetched 671 kB in 1s (904 kB/s)
    debconf: unable to initialize frontend: Dialog
    debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76, <> line 5.)
    debconf: falling back to frontend: Readline
    debconf: unable to initialize frontend: Readline
    debconf: (This frontend requires a controlling tty.)
    debconf: falling back to frontend: Teletype
    dpkg-preconfigure: unable to re-open stdin:
    Selecting previously unselected package libspatialindex4v5:amd64.
    (Reading database ... 155501 files and directories currently installed.)
    Preparing to unpack .../libspatialindex4v5_1.8.5-5_amd64.deb ...
    Unpacking libspatialindex4v5:amd64 (1.8.5-5) ...
    Selecting previously unselected package libspatialindex-c4v5:amd64.
    Preparing to unpack .../libspatialindex-c4v5_1.8.5-5_amd64.deb ...
    Unpacking libspatialindex-c4v5:amd64 (1.8.5-5) ...
    Selecting previously unselected package python3-pkg-resources.
    Preparing to unpack .../python3-pkg-resources_39.0.1-2_all.deb ...
    Unpacking python3-pkg-resources (39.0.1-2) ...
    Selecting previously unselected package libspatialindex-dev:amd64.
    Preparing to unpack .../libspatialindex-dev_1.8.5-5_amd64.deb ...
    Unpacking libspatialindex-dev:amd64 (1.8.5-5) ...
    Selecting previously unselected package python3-rtree.
    Preparing to unpack .../python3-rtree_0.8.3+ds-1_all.deb ...
    Unpacking python3-rtree (0.8.3+ds-1) ...
    Setting up libspatialindex4v5:amd64 (1.8.5-5) ...
    Setting up python3-pkg-resources (39.0.1-2) ...
    Setting up libspatialindex-c4v5:amd64 (1.8.5-5) ...
    Setting up libspatialindex-dev:amd64 (1.8.5-5) ...
    Setting up python3-rtree (0.8.3+ds-1) ...
    Processing triggers for libc-bin (2.27-3ubuntu1.3) ...
    /sbin/ldconfig.real: /usr/local/lib/python3.7/dist-packages/ideep4py/lib/libmkldnn.so.0 is not a symbolic link

    /usr/local/lib/python3.7/dist-packages/geopandas/_compat.py:115: UserWarning: The Shapely GEOS version (3.10.2-CAPI-1.16.0) is incompatible with the GEOS version PyGEOS was compiled with (3.10.1-CAPI-1.16.0). Conversions between both will be slow.
      shapely_geos_version, geos_capi_version_string

##### Map data source:
[DATA](https://data.austintexas.gov/browse?q=BOUNDARIES_jurisdictions&sortBy=relevance)

```python
# Creating jurisdictions map of Austin
df_austin = gpd.GeoDataFrame.from_file('/content/drive/MyDrive/data/BOUNDARIES_jurisdictions.geojson')
df_austin.plot(figsize=(10,10))
```

```python
# creating a geometry point with GeoPandas to use it later to create a boundary
gdf = gpd.GeoDataFrame(
    austin_restaurants, geometry=gpd.points_from_xy(austin_restaurants.longitude, austin_restaurants.latitude))
gdf.head(5)
```

      business_id
      name
      address
      city
      state
      postal_code
      latitude
      longitude
      stars
      review_count
      is_open
      attributes
      categories
      hours
      geometry

      41
      NRPemqVb4qpWFF0Avq_6OQ
      Eurasia Sushi Bar & Seafood
      7101 W Hwy 71, Ste C-13
      Austin
      TX
      78735
      30.234533
      -97.877262
      4.5
      395
      1
      {'Ambience': '{'touristy': False, 'hipster': F...
      Bars, Nightlife, Cocktail Bars, Seafood, Resta...
      {'Monday': '0:0-0:0', 'Tuesday': '11:0-22:0', ...
      POINT (-97.87726 30.23453)

      61
      bRsDZ44CD3uhGnRY3NeQhQ
      Wendy's
      6247 Mcneil Drive
      Austin
      TX
      78729
      30.441875
      -97.746581
      2.0
      46
      1
      {'RestaurantsPriceRange2': '1', 'OutdoorSeatin...
      Fast Food, Restaurants, Burgers
      {'Monday': '6:30-1:0', 'Tuesday': '6:30-1:0', ...
      POINT (-97.74658 30.44188)

      199
      Pk4ZwXwUU50BDn5gqw_rKg
      Johnny Carino's
      9500 S IH-35 Service Rd
      Austin
      TX
      78748
      30.162081
      -97.789132
      3.0
      136
      1
      {'RestaurantsGoodForGroups': 'True', 'Business...
      Italian, Salad, Pizza, Nightlife, Restaurants,...
      {'Monday': '11:0-21:30', 'Tuesday': '11:0-21:3...
      POINT (-97.78913 30.16208)

      253
      Ieelu69Y23nbjKG3OGfwnw
      McDonald's
      5017 Hwy 290 W
      Austin
      TX
      78735
      30.232133
      -97.823183
      1.5
      9
      1
      {'RestaurantsTakeOut': 'True', 'RestaurantsRes...
      Restaurants, Coffee & Tea, Food, Burgers, Fast...
      {'Monday': '7:0-22:30', 'Tuesday': '7:0-22:30'...
      POINT (-97.82318 30.23213)

      258
      IFB2K3BEZ2L_Mv5AbUD26Q
      Chispas
      214 W 4th St
      Austin
      TX
      78701
      30.266996
      -97.745362
      3.5
      119
      1
      {'RestaurantsTakeOut': 'True', 'OutdoorSeating...
      Tex-Mex, Mexican, Tacos, Restaurants
      {'Monday': '11:0-22:0', 'Tuesday': '11:0-22:0'...
      POINT (-97.74536 30.26700)

      <button class="colab-df-convert" onclick="convertToInteractive('df-34475c52-59ce-4749-9831-15dea55313e3')"
              title="Convert this dataframe to an interactive table."
              style="display:none;">

  <svg xmlns="http://www.w3.org/2000/svg" height="24px"viewBox="0 0 24 24"
       width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"/>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"/><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"/>
  </svg>
      </button>

```python
base = df_austin.plot(linewidth=0.3, color='grey', figsize = (20,20))

pizza_joint.plot(
    kind='scatter',
    x='longitude',
    y='latitude',
    figsize = (10,10),
    ax = base
)
```

##### Pizzerias are concentrated in the middle of the city. The right side of the city has many industrial areas explaining the lack of pizzerias

#### **3.2 How many pizzerias are there per zipcode?**

```python
pizza_per_zip = pizza_joint.groupby('postal_code').name.count()
pizza_per_zip_sorted = pizza_per_zip.sort_values(ascending=False)
pizza_per_zip_sorted
```

    postal_code
    78701    29
    78704    23
    78759    16
    78753    15
    78702    14
    78745    14
    78758    12
    78748    12
    78746    11
    78741    10
    78757    10
    78723    10
    78705    10
    78751     7
    78744     6
    78750     6
    78749     6
    78731     5
    78738     4
    78729     4
    78735     4
    78727     4
    78703     4
    78734     3
    78728     3
    78754     2
    78752     2
    78747     2
    78737     2
    78756     2
    78726     2
    78665     1
    78736     1
    78732     1
    78730     1
    78724     1
    78722     1
    78719     1
    78798     1
    Name: name, dtype: int64

```python
# total pizzerias in Austin
total_pizza_count = pizza_joint.name.count()
print(total_pizza_count)
```

    262

```python
pizza_per_zip.plot(kind='bar')
```

```python
#Top 10 zip codes
pizza_per_zip_sorted.head(10).plot(kind='bar')

```

#### **3.3 Concentration of pizzerias among Austin restaurants**

```python
# Total Restaurants in Austin
total_restaurant_count = austin_restaurants.name.count()
print(total_restaurant_count)
```

    2832

```python
# % of Pizzerias of Total Restaurants in Austin

pizza_percentage = round((total_pizza_count / total_restaurant_count),2)*100
pizza_percentage
```

    9.0

##### 9% of Austin restaurants are pizzerias

```python
# 9% is average, but is it telling the full story? We can validate by checking the distribution of concentration by zip code
restaurant_per_zip = austin_restaurants.groupby('postal_code').name.count()

pizza_and_restaurant = pizza_per_zip.to_frame().merge(restaurant_per_zip.to_frame(), left_on='postal_code', right_on='postal_code')
pizza_and_restaurant

concentration_per_zip = (pizza_and_restaurant["name_x"] / pizza_and_restaurant["name_y"]) * 100
pizza_and_restaurant["concentration"] = concentration_per_zip
print(pizza_and_restaurant)
```

                 name_x  name_y  concentration
    postal_code
    78665             1       1     100.000000
    78701            29     294       9.863946
    78702            14     216       6.481481
    78703             4      57       7.017544
    78704            23     263       8.745247
    78705            10     130       7.692308
    78719             1      27       3.703704
    78722             1      43       2.325581
    78723            10      82      12.195122
    78724             1      11       9.090909
    78726             2      22       9.090909
    78727             4      53       7.547170
    78728             3      29      10.344828
    78729             4      21      19.047619
    78730             1       9      11.111111
    78731             5      38      13.157895
    78732             1      23       4.347826
    78734             3      21      14.285714
    78735             4      37      10.810811
    78736             1      11       9.090909
    78737             2      20      10.000000
    78738             4      23      17.391304
    78741            10      95      10.526316
    78744             6      47      12.765957
    78745            14     163       8.588957
    78746            11      64      17.187500
    78747             2       8      25.000000
    78748            12      98      12.244898
    78749             6      45      13.333333
    78750             6      46      13.043478
    78751             7      73       9.589041
    78752             2      84       2.380952
    78753            15     143      10.489510
    78754             2      17      11.764706
    78756             2      66       3.030303
    78757            10     109       9.174312
    78758            12     167       7.185629
    78759            16     121      13.223140
    78798             1       6      16.666667

```python
# Based on the histogram the concentration is clustured in the 0% to 10% band so 9% is a reasonable representative of the city of Austin
pizza_and_restaurant.concentration.hist(bins=10)
```

##### 9% average concentration tells a reasonable story for the overall Austin as validated by the histogram (most of the concentration in 0-10% range)

#### **3.4 Ratings Distribution and Average of Similar Establishment**

```python
pizza_per_star = pizza_joint.groupby('stars').name.count()
pizza_per_star.sort_values(ascending=False)

```

    stars
    4.0    62
    3.5    49
    4.5    43
    3.0    39
    2.0    26
    2.5    26
    1.5     9
    5.0     8
    Name: name, dtype: int64

```python
pizza_per_star.plot(kind='bar')

```

```python
total_stars_count = pizza_joint.stars.sum()

average_stars = total_stars_count / total_pizza_count
average_stars
```

    3.437022900763359

##### Distribution of stars among pizzerias is slightly left skewed, with an average of 3.4

#### **3.5 Average Number and Distribution of Reviews per Pizzeria**

```python
total_review_count = pizza_joint.review_count.sum()

average_review_count = total_review_count / total_pizza_count
average_review_count
```

    189.83969465648855

```python
pizza_joint.review_count.hist(bins=50)
```

Average review count is 190 but based on the histogram of review counts, 0-50 reviews seem to be the most common amount

#### **3.6 Correlation with Bars**
As an aside, we were curious to see if there is a correlation between location of bars/pubs and pizzerias and to potential identify a location where this synergy is lacking i.e. there are bars, but no pizzeria.

```python
# creating a variable for all austin restaurants containing "Bar" in categories
bars_joint = austin_restaurants[austin_restaurants['categories'].str.contains("Bars", na=False)]
bars_joint.head(5)

```

      business_id
      name
      address
      city
      state
      postal_code
      latitude
      longitude
      stars
      review_count
      is_open
      attributes
      categories
      hours
      geometry

      41
      NRPemqVb4qpWFF0Avq_6OQ
      Eurasia Sushi Bar & Seafood
      7101 W Hwy 71, Ste C-13
      Austin
      TX
      78735
      30.234533
      -97.877262
      4.5
      395
      1
      {'Ambience': '{'touristy': False, 'hipster': F...
      Bars, Nightlife, Cocktail Bars, Seafood, Resta...
      {'Monday': '0:0-0:0', 'Tuesday': '11:0-22:0', ...
      POINT (-97.87726 30.23453)

      199
      Pk4ZwXwUU50BDn5gqw_rKg
      Johnny Carino's
      9500 S IH-35 Service Rd
      Austin
      TX
      78748
      30.162081
      -97.789132
      3.0
      136
      1
      {'RestaurantsGoodForGroups': 'True', 'Business...
      Italian, Salad, Pizza, Nightlife, Restaurants,...
      {'Monday': '11:0-21:30', 'Tuesday': '11:0-21:3...
      POINT (-97.78913 30.16208)

      669
      _rt-Z934kfFzgG19nTrIcQ
      Pelons Tex-Mex
      802 Red River St
      Austin
      TX
      78701
      30.268838
      -97.736549
      3.5
      438
      1
      {'HasTV': 'True', 'BusinessParking': '{'garage...
      Tex-Mex, Restaurants, Tacos, Nightlife, Bars, ...
      {'Tuesday': '16:0-22:0', 'Wednesday': '16:0-22...
      POINT (-97.73655 30.26884)

      778
      J8Ha6yIvGoU-E31jnCq7Ew
      Barley Swine
      6555 Burnet Rd, Ste 400
      Austin
      TX
      78757
      30.341274
      -97.738389
      4.5
      1086
      1
      {'RestaurantsAttire': 'u'casual'', 'GoodForKid...
      Restaurants, Nightlife, American (New), Bars, ...
      {'Monday': '0:0-0:0', 'Tuesday': '17:0-22:0', ...
      POINT (-97.73839 30.34127)

      861
      pCg4oRweZQnoXo2j7_-BqQ
      Hote1e1even
      1123 East 11th St
      Austin
      TX
      78702
      30.268729
      -97.728389
      4.5
      13
      1
      {'WiFi': ''free'', 'RestaurantsPriceRange2': '...
      Hotels, Event Planning & Services, Restaurants...
      None
      POINT (-97.72839 30.26873)

      <button class="colab-df-convert" onclick="convertToInteractive('df-3bec2fca-48eb-44fe-9ab3-df8f075ec16f')"
              title="Convert this dataframe to an interactive table."
              style="display:none;">

  <svg xmlns="http://www.w3.org/2000/svg" height="24px"viewBox="0 0 24 24"
       width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"/>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"/><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"/>
  </svg>
      </button>

```python
# Combining Pizza places and Bars into one scatter plot
base1 = df_austin.plot(linewidth=0.3, color='silver', figsize = (20,20))
pizza_joint.plot(
    kind='scatter',
    x='longitude',
    y='latitude',
    figsize = (10,10),
    ax = base1
)
bars_joint.plot(

    c = "orange",
    s = 10,
    alpha = .50,
    kind='scatter',
    x='longitude',
    y='latitude',
    figsize = (10,10),
    ax = base1
)
```

##### Pizzerias are very much in line with location of bars

### **4. Competitive Landscape for a Given Location**
#### Here we take a look at the competitive landscape for a given location by defining radius for search and creating a scoring system based on our analysis in section 3 above

#### **4.1 Defining Radius for Search**

```python
#creating data frame for 3 sample locations

#Reference point #1
reference_point1 = pd.DataFrame(
    {'location': ['target_point'],
     'Latitude': [30.267255],
     'Longitude': [-97.743626]})

gdf_ref1 = gpd.GeoDataFrame(
    reference_point1, geometry=gpd.points_from_xy(reference_point1.Longitude, reference_point1.Latitude))

#Reference point #2 (commercial area in the NE)
reference_point2 = pd.DataFrame(
    {'location': ['target_point'],
     'Latitude': [30.327068],
     'Longitude': [-97.707002]})

gdf_ref2 = gpd.GeoDataFrame(
    reference_point2, geometry=gpd.points_from_xy(reference_point2.Longitude, reference_point2.Latitude))

#Reference point #3 (South Austin Area)
reference_point3 = pd.DataFrame(
    {'location': ['target_point'],
     'Latitude': [30.202847],
     'Longitude': [-97.806913]})

gdf_ref3 = gpd.GeoDataFrame(
    reference_point3, geometry=gpd.points_from_xy(reference_point3.Longitude, reference_point3.Latitude))

# ref_plot1 = gdf_ref1.plot(linewidth=0.3, color='grey', figsize = (20,20))

```

```python
#Creating dataframe that shows radius from selected point
## i.e. 5*(1/60) is 5 miles radius
ref_radius1 = gdf_ref1.buffer(1.5*(1/60), resolution=16)
ref_radius2 = gdf_ref2.buffer(1.5*(1/60), resolution=16)
ref_radius3 = gdf_ref3.buffer(1.5*(1/60), resolution=16)

# ref_base = ref_radius1.plot(linewidth=0.3, color='grey', figsize = (20,20))
base1 = df_austin.plot(linewidth=0.3, color='silver', figsize = (20,20))
ref_radius1.plot(linewidth=0.3, color='darkred', figsize = (20,20), ax = base1)
ref_radius2.plot(linewidth=0.3, color='green', figsize = (20,20), ax = base1)
ref_radius3.plot(linewidth=0.3, color='navy', figsize = (20,20), ax = base1)
```

```python
base = df_austin.plot(linewidth=0.3, color='silver', figsize = (20,20))
pizza_joint.plot(
    kind='scatter',
    x='longitude',
    y='latitude',
    figsize = (10,10),
    ax = base
)

ref_radius1.plot(
    linewidth=1,
    color='none',
    edgecolor='darkred',
    figsize = (20,20),
    ax = base
)
ref_radius2.plot(
    linewidth=1,
    color='none',
    edgecolor='green',
    figsize = (20,20),
    ax = base
)
ref_radius3.plot(
    linewidth=1,
    color='none',
    edgecolor='navy',
    figsize = (20,20),
    ax = base
)
```

```python
from shapely.geometry import Point, Polygon, LineString
from shapely import geometry

```

```python
# Creating a polygon for from the defined boundary
polys1 = gpd.GeoSeries(ref_radius1)
polys2 = gpd.GeoSeries(ref_radius2)
polys3 = gpd.GeoSeries(ref_radius3)

```

```python
# Creating points from results (all data)
points = austin_restaurants["geometry"]
points
```

    41        POINT (-97.87726 30.23453)
    61        POINT (-97.74658 30.44188)
    199       POINT (-97.78913 30.16208)
    253       POINT (-97.82318 30.23213)
    258       POINT (-97.74536 30.26700)
                         ...
    160413    POINT (-97.89304 30.37022)
    160465    POINT (-97.76447 30.27416)
    160480    POINT (-97.79541 30.21882)
    160517    POINT (-97.78845 30.19675)
    160525    POINT (-97.80443 30.44754)
    Name: geometry, Length: 2832, dtype: geometry

```python
!pip install rtree
```

    Requirement already satisfied: rtree in /usr/local/lib/python3.7/dist-packages (1.0.0)
    Requirement already satisfied: typing-extensions>=3.7 in /usr/local/lib/python3.7/dist-packages (from rtree) (4.1.1)

```python
#checking df types
type(gdf)
```

    geopandas.geodataframe.GeoDataFrame

```python
#checking df types
type(ref_radius1)
```

    geopandas.geoseries.GeoSeries

```python
# creating an envelope so we can work a join with the gp dataframe
envgdf1 = gpd.GeoDataFrame(geometry=gpd.GeoSeries(ref_radius1))
envgdf2 = gpd.GeoDataFrame(geometry=gpd.GeoSeries(ref_radius2))
envgdf3 = gpd.GeoDataFrame(geometry=gpd.GeoSeries(ref_radius3))
print(envgdf1, envgdf2, envgdf3)
```

                                                geometry
    0  POLYGON ((-97.71863 30.26725, -97.71875 30.264...                                             geometry
    0  POLYGON ((-97.68200 30.32707, -97.68212 30.324...                                             geometry
    0  POLYGON ((-97.78191 30.20285, -97.78203 30.200...

```python
# Creating intersection between gdf data frame and envgdf* dataframe
joined_gdf1 = gpd.sjoin(gdf, envgdf1, op='within')
joined_gdf2 = gpd.sjoin(gdf, envgdf2, op='within')
joined_gdf3 = gpd.sjoin(gdf, envgdf3, op='within')

```

    /usr/local/lib/python3.7/dist-packages/IPython/core/interactiveshell.py:2822: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.
      if self.run_code(code, result):
    /usr/local/lib/python3.7/dist-packages/IPython/core/interactiveshell.py:2822: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.
      if self.run_code(code, result):
    /usr/local/lib/python3.7/dist-packages/IPython/core/interactiveshell.py:2822: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.
      if self.run_code(code, result):

#### **4.2 Our Business Criteria for Measuring Competitive Landscape**

1. Number of similar places: -1 for each pizza places as this would mean direct competition
1. Bars: +1 for each bar since bar presence increases the demand for pizza
1. Concentration of pizza places in the radius: if concentration is >10%, then score decreases by 4 since this would mean higher than average concentration of pizzerias in this location (using an even number 10% as a threshold since average concentration was 9%)
1. Quality of competition: if an area is less competitive as measured by the star ratings of restaurants (below 3.5 stars based on our findings in section 3), then increase score by 3

##### *The weights of each criteria were arbitrarily chosen to directionally showcase the favorability of an area; In a given set of few sample locations, the area with the highest score would be the most desirable among the peer set*

```python
def score(location):
  '''
  This function takes one positional argument and outputs the score of the location based on our given criteria and information on each criteria
  Arg: location (dataframe)
  '''
  bar = location['categories'].str.contains("Bars", na=False)
  bar_count = bar.count() - bar.value_counts().loc[False]
  pizza = location['categories'].str.contains("Pizza|Pizzeria|pizza|pizzeria", na=False)
  pizza_count = pizza.value_counts().loc[True]
  total_count = location.name.count()
  avg_stars_in_radius = location.stars.mean()

# 1*count of bars + -1*count of pizzerias
  base = 1*bar_count + (-1)*pizza_count

# if  (pizzeria count / total business count) >= 0.10 then -4
  if pizza_count / total_count > 0.10:
    saturation = + -4
  else:
    saturation = 0

# if  average stars < 3.5 then +3
  if avg_stars_in_radius < 3.50:
    competition_quality = + 3
  else:
    competition_quality = 0

  # return base + saturation + competition_quality
  score_of_location = base + saturation + competition_quality

  print("Score: " + str(score_of_location) + '\n')
  print("Bar count: " + str(bar_count))
  print("Pizza count: " + str(pizza_count))
  print("Total restaurant count: " + str(total_count))
  print("Saturation: " + str(round((pizza_count/total_count),2)*100) + "%")
  print("Competition Level (Avg Star of Area): " + str(round(avg_stars_in_radius,2)))
```

### **5. Result and Conclusion**
#### We chose 3 sample locations (section 4.1) and measure their competitive landscape using the criteria developed previously (section 4.2)
#### In closing, we also address various data sets that would enhance this analysis to be more robust

#### **5.1 Result of Three Sample Locations**

```python
#Sample 1 (Central Austin):
score(joined_gdf1)
```

    Score: 162

    Bar count: 216
    Pizza count: 54
    Total restaurant count: 652
    Saturation: 8.0%
    Competition Level (Avg Star of Area): 3.93

```python
#Sample 2 (North Austin):
score(joined_gdf2)
```

    Score: 15

    Bar count: 30
    Pizza count: 15
    Total restaurant count: 194
    Saturation: 8.0%
    Competition Level (Avg Star of Area): 3.68

```python
#Sample 3 (South Austin):
score(joined_gdf3)
```

    Score: -2

    Bar count: 4
    Pizza count: 6
    Total restaurant count: 63
    Saturation: 10.0%
    Competition Level (Avg Star of Area): 3.76

#### **Result**: Out of the three sample locations, sample 1 (Central Austin) is the most preferred as it has the highest score

#### **5.2 Challenges of this project**
 * Creating the intersection of the selected radius required a number of intermediate steps (creating a geometry from a Geopandas dataset and them creating the intersection itself).
 * Creating the scoring function required full understanding of the data and the various situations when some conditions weren't met.

#### **5.3 In closing, we address various data sets that would enhance this analysis to be more robust**
What kind of information can be layered to take the analysis to the next level?
 * Real estate prices - if a place is good competitively (not too much competition) but too expensive, may be not a feasible option
 * Covid-19 impact on business closures to get a more accurate view of the competitive landscape
 * Demographics to find if demand for your business will be met
 * Pedestrian data to find if a location has good "discoverability" by pedestrians
 * Parking data to see if those travelling by car will not have an issue accessing the business
 * Proximity to "hot spots" like universities or office area (in non-pandemic times)


```python
from IPython.core.display import HTML
HTML("<style>.container { width:95% !important; }</style>")
```

# Lecture 10: Introduction to Multiobjective Optimization

## What means multiobjective?

* Consider several criteria simultaneously

* Examples: Cost (investment vs. operating), quality, safety, profit, reliability, operability, environmental and social impacts, etc.

* Criteria are conflicting (e.g. usually good quality is not cheap) $\Rightarrow$ all the criteria can not be optimized simultaneously (i.e., have different optimal solutions)

* Need for considering compromises between the criteria
* Indeed we search for a set of acceptable solutions (maybe only suboptimal for one objective) instead of a single optimal.

* Compromise can be better than optimal solution in practice (e.g., optimize only costs/profit)

* http://en.wikipedia.org/wiki/Multiobjective_optimization

## Example. Buying a Laptop

##### **Objectives**:
* Min Cost
* Min Weight

* Which solution is the best? (1,A,B,C,2)

* No single optimal solution
* Trade-offs between objectives

### Most of the real-life decision problems have multiple criteria

* Can you name some?

## Example 1. Investment (Portfolio selection)

#### objectives:
* max Return
* min Risk
* Max Liquidity

## Example 2. Supply Chain Management

#### objectives:
* Min cost
* Min $CO_2$ emissions
* Max Liquidity
* Max Social benefits (e.g. job creation)

## Example 3. Engineering Design Problems: (e.g. Cable-Stayed Bridges)

#### objectives:
* Residual error in each cable tension
* Residual error in camber at each node
* Amount of shim adjustment for each cable
* Number of cables to be adjusted

# Multiobjective optimization process

## Example 4: Continuous casting of steel

* Optimal control of the secondary cooling of continuous casting of steel
* Long history of research in the Dept. of Mathematical Information Technology, Univ. of Jyväskylä
  * modelling (1988)
  * single objective optimization (1988-1994)
  * multiobjective optimization (1994-1998)

* Liquid steel enters (tundish)
* Initial cooling by a water cooled mold $\Rightarrow$ thin crust
* Movement supported by rollers
* Secondary cooling by water sprays
* Rest of the cooling by radiation

## Modelling
* Measuring temperature in casting difficult $\Rightarrow$ numerical temperature distribution
* Process modelled as a multiphase heat equation (PDEs, solid & liquid phase) $\Rightarrow$  temperature distribution
* Numerical model by using the finite element method (FEM)
* Dynamic process

## Single-objective optimization

* Secondary cooling significant: intensity of sprays (easy to control) affects significantly to the solidification of steel
* Goal: minimize the amount of defects in steel
* Quality depends on e.g. the temperature distribution at the surface of steel
  * too slow cooling → too long liquid part
  * too fast cooling → defects appear
* Objective function: keep the surface temperature as close to a given profile as possible
* Constraints e.g. for the change of temperature and for the temperature in critical spots

## Single-objective optimization results

* Analysis of single objective optimization problem:
  * constraints tight (based on metallurgy)
  * no feasible solutions
* which constraints to relax?
* $\Rightarrow$ Convert constraints into objective functions      (5 in total)
  * Enables simultaneous relaxation of different constraints
  * Gives information on satisfaction of different constraints and their interdependences

## Multiobjective optimization results

** Found a solution, which only violated one of the constraints**

$\Rightarrow$ satisfactory to the application expert

## Example 5: Data-Based Forest Management with Uncertainties and Multiple Objectives

* A study by Profs Annika Kangas (Forest research institute, Joensuu) and Kaisa Miettinen, PhD Markus Hartikainen and PhD Kyle Eyvindson (University of Helsinki)
* Main research question: How to use multiobjective optimization to handle in forest management simultaneously
  * conflicting objectives **income** and **biodiversity**, and
  * **uncertainties**.

### Main problems

* **Harvesting implies incomes from forests**, but on the other hand, it **diminishes the recreational and esthetical values of the forest**, and it may have **adverse effects on the natural values of the area**, for instance, the biodiversity within the area and the viability of wildlife populations living in the area.

* On the other hand, forest management planning **involves lots of uncertainty**. It is **not possible to measure all trees** within a forest area, so there is **uncertainty concerning the current state** of the forests. **Measuring biodiversity is prohibitively expensive**, so using **proxy variables** (biodiversity indices) is the only possibility.

* All forest decisions **concern the future** (typically the next 5-20 years), so that the **state of the forest stands and biodiversity and the consequences of the treatment options needs to be predicted** using statistical models. As we do not know the exact consequences of the decisions, the **decisions involve uncertainty which the decision makers may wish to manage.**

## The approach

* Model the decision problem as a six-objective optimization problem
* Model uncertainty using scenario based-approach
  * Different scenarios represent possible future states
* Handle the uncertainty using a well known risk measure called "value-at-risk" with different risk levels
* Objectives to be maximized
  1. Expected minimum (over all time periods) income in all the scenarios.
  2. Expected minimum (over all time periods) biodiversity in all the scenarios
  3. Value of the biodiversity at the given risk
  4. Value of the income at the given risk
  5. Probability of the income being greater than the value-at-risk.  The risk level for income is, thus, one minus this probability.
  6. Probability of the biodiversity being greater than the value-at-risk.  The risk level for biodiversity is, thus, one minus this probability.

## Multiobjective optimization results

* The decision maker was able to study interdependencies between income and biodiversity, gains and losses in income and biodiversity at different risk levels and risk levels associated to these
* The results were presented at the MOD2016 workshop

## Example 6: Interactive multiobjective optimization for finding the most preferred exercise therapy modality in knee osteoarthritis

* Babooshka Shavazipour, Bekir Afsar, Juhani Multanen, Kaisa Miettinen & Urho M. Kujala (2022) Interactive multiobjective optimization for finding the most preferred exercise therapy modality in knee osteoarthritis, Annals of Medicine, 54:1, 181-194, DOI:10.1080/07853890.2021.2024876

* A joint study of Faculty of Information Technology and Faculty of Sport and Health Sciences at University of Jyvaskyla.\\

* **Aim:**  Developing a decision support tool to support healthcare professionals in comparing different modalities (in terms of on multiple criterai) and identifying the most preferred one based on a patient’s needs.

* Model the decision problem as a five-objective optimization problem.

**Optimization problem:**

* Minimize the cost of therapy
* Maximize expected net improvement in pain reduction
* Maximize expected net improvement in physical function
* Minimize the number of supervised training sessions
* Minimize the length of treatment

 Subject to one therapy is selected from a list of options:

* Thirty-one exercise therapy modalities were considered
* A novel interactive multiobjective optimization model was designed to characterize the efficacy of an exercise therapy modality based on five objectives
* An interactive model incorporates clinicians’ preferences in finding the most preferred exercise therapy modality for each need.
* The proposed methodology is generic enough to be applied in any field of medical and healthcare settings, where several alternative treatment options exist.

## Mathematical formulation of multiobjective optimization problems

Multiobjective optimization problems are often formulated as
$$
\begin{align} \
\min \quad &\{f_1(x),\ldots,f_k(x)\}\\
\text{s.t.} \quad & g_j(x) \geq 0\text{ for all }j=1,\ldots,J\\
& h_q(x) = 0\text{ for all }q=1,\ldots,Q\\
&a_i\leq x_i\leq b_i\text{ for all } i=1,\ldots,n\\
&x\in \mathbb R^n,
\end{align}
$$
where $$f_1,\ldots,f_k:\{x\in\mathbb R^n: g_j(x) \geq 0 \text{ for all }j=1,\ldots,J \text{ and } h_q(x) = 0\text{ for all }q=1,\ldots,Q\}\mapsto\mathbb R$$ are the objective functions.

## Basic concepts

* Basic concepts of solution, feasible solution, equality and inequality constraints are the same.

* However, all the objectives do not have the same optimal solution

* The concept of optimality needs to redefined. *How to define optimality for multiple objectives?*

## Optimality in the objective space (Image of the feasible region)
*Which solution is better?*

## Optimality in the objective space (Image of the feasible region)
*Which of the red solutions is better?*

## Optimality in the objective space (Image of the feasible region)
*Where are optimal solutions?*

## Optimality in the objective space (Image of the feasible region)
*Optimal solutions are located at the boundary to the down & left (for minimization problems)*

## Pareto optimality
A feasible solution $x_1$ is Pareto optimal to the multiobjective optimization problem, if there does not exist a feasible solution $x_2$, $x_1\neq x_2$, such that
$$
\left\{
\begin{align}
&f_i(x_2)\leq f_i(x_1)\text{ for all }i\in \{1,\ldots,k\}\\
&f_j(x_2)<f_j(x_1)\text{ for some }j\in \{1,\ldots,k\}.\\
\end{align}
\right.
$$

There are now two spaces connected to the problem: the space $\mathbb R^n$ is called the decision space and $\mathbb R^k$ is called the objective space.

**Problem having two objectives is a special case: Let us assume that $x$ is Pareto optimal. if we want to improve one of the objectives at point $x$, we know that the value of the other objective has to impair.**

In other words: **A solution is Pareto optimal if none of the objectives can be improved without impairing at least one of the others**

It means:
$$
\text{“Take from Sami to pay Anna”}
$$

**Usually there exist multiple Pareto optimal solutions to a problem (can be infinitely many).**

**all of them mathematically incomparable**

**How to choose (the best) one?**

**the most preferred one needs to be selected for implementation. Thus, a decision maker is needed.**

Lecture 10, Introduction to multiobjective optimization.ipynb