0% found this document useful (0 votes)
13 views27 pages

Code Doc

The document outlines a data-driven analysis of restaurant demand for FoodHub, a food aggregator app in New York. It details the objectives of analyzing customer order data to enhance service, including identifying qualifying restaurants for promotions and calculating revenue and delivery metrics. The analysis includes data descriptions, exploratory data analysis, and insights into customer behavior and order patterns.

Uploaded by

shekhu_fid
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views27 pages

Code Doc

The document outlines a data-driven analysis of restaurant demand for FoodHub, a food aggregator app in New York. It details the objectives of analyzing customer order data to enhance service, including identifying qualifying restaurants for promotions and calculating revenue and delivery metrics. The analysis includes data descriptions, exploratory data analysis, and insights into customer behavior and order patterns.

Uploaded by

shekhu_fid
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Data-Driven Insights for FoodHub’s Restaurant Demand Analysis¶

Context

The number of restaurants in New York is increasing day by day. Lots of


students and busy professionals rely on those restaurants due to their hectic
lifestyles. Online food delivery service is a great option for them. It provides
them with good food from their favorite restaurants. A food aggregator
company FoodHub offers access to multiple restaurants through a single
smartphone app.

The app allows the restaurants to receive a direct online order from a
customer. The app assigns a delivery person from the company to pick up
the order after it is confirmed by the restaurant. The delivery person then
uses the map to reach the restaurant and waits for the food package. Once
the food package is handed over to the delivery person, he/she confirms the
pick-up in the app and travels to the customer's location to deliver the food.
The delivery person confirms the drop-off in the app after delivering the food
package to the customer. The customer can rate the order in the app. The
food aggregator earns money by collecting a fixed margin of the delivery
order from the restaurants.

Objective

As a Data Scientist for a food aggregator company, tasked with enhancing


customer experience, the objective is to analyze the stored data of customer
orders on the online portal. The company aims to understand restaurant
demand for improved service. Specific tasks include identifying restaurants
meeting criteria for a promotional offer based on rating count (more than 50)
and average rating (greater than 4). Additionally, calculating net revenue by
applying appropriate charges on orders (25% on the orders having cost
greater than 20 dollars and 15% on the orders having cost greater than 5
dollars), analyzing the percentage of orders taking more than 60 minutes for
delivery, and assessing mean delivery times on weekdays and weekends.
Finally, the company plans to reward its top 3 frequent customers with 20%
discount vouchers, requiring the identification of these customers and the
number of orders they've placed.

Data Description

The data contains the different data related to a food order. The detailed
data dictionary is given below.

Data Dictionary
 order_id: Unique ID of the order

 customer_id: ID of the customer who ordered the food

 restaurant_name: Name of the restaurant

 cuisine_type: Cuisine ordered by the customer

 cost: Cost of the order

 day_of_the_week: Indicates whether the order is placed on a weekday


or weekend (The weekday is from Monday to Friday and the weekend is
Saturday and Sunday)

 rating: Rating given by the customer out of 5

 food_preparation_time: Time (in minutes) taken by the restaurant to


prepare the food. This is calculated by taking the difference between
the timestamps of the restaurant's order confirmation and the delivery
person's pick-up confirmation.

 delivery_time: Time (in minutes) taken by the delivery person to


deliver the food package. This is calculated by taking the difference
between the timestamps of the delivery person's pick-up confirmation
and drop-off information

Let us start by importing the required libraries

# import libraries for data manipulation

import numpy as np

import pandas as pd

# import libraries for data visualization

import [Link] as plt

import seaborn as sns

# to suppress warnings

import warnings

[Link]('ignore')

Understanding the structure of the data


# read the data

df = pd.read_csv('/kaggle/input/food-ordering-and-delivery-app-dataset/
food_order.csv')

# returns the first 5 rows

[Link]()

ra
ord custo restaur cuisi cost_of_ day_of_ food_prep deliv
ti
er_i mer_i ant_na ne_ty the_ord the_we aration_ti ery_ti
n
d d me pe er ek me me
g

N
147 ot
3375 Hanga Kore Weeke
0 714 30.75 gi 25 20
25 wi an nd
7 ve
n

N
Blue
147 ot
3581 Ribbon Japan Weeke
1 768 12.08 gi 25 23
41 Sushi ese nd
5 ve
Izakaya
n

147 Cafe
6639 Mexi Weekd
2 707 Haban 12.23 5 23 28
3 can ay
0 a

Blue
147 Ribbon
1069 Amer Weeke
3 733 Fried 29.20 3 25 15
68 ican nd
4 Chicke
n

147 Dirty
7694 Amer Weekd
4 824 Bird to 11.59 4 25 24
2 ican ay
9 Go

Observations:¶
The DataFrame has 9 columns as mentioned in the Data Dictionary. Data in
each row corresponds to the order placed by a customer.

# The shape attribute returns a tuple with the number of rows and the
number of columns

[Link]

(1898, 9)

Observations:

There are 1898 rows, i.e. 1898 orders.

There are 9 columns, i.e. 9 data for each registered order.

# Use info() to print a concise summary of the DataFrame

[Link]()

<class '[Link]'>

RangeIndex: 1898 entries, 0 to 1897

Data columns (total 9 columns):

# Column Non-Null Count Dtype

--- ------ -------------- -----

0 order_id 1898 non-null int64

1 customer_id 1898 non-null int64

2 restaurant_name 1898 non-null object

3 cuisine_type 1898 non-null object

4 cost_of_the_order 1898 non-null float64

5 day_of_the_week 1898 non-null object

6 rating 1898 non-null object

7 food_preparation_time 1898 non-null int64

8 delivery_time 1898 non-null int64

dtypes: float64(1), int64(4), object(4)

memory usage: 133.6+ KB


Observations:

 There are three different datatypes: int64 (represents discrete


numerical values), float64 (represents continuous numerical values)
and object (represents categorial variables).

 order_id, customer_id, food_preparation_time and delivery_time have


int64 datatype.

 cost_of_the_order has float64 datatype.

 restaurant_name, cuisine_type, day_of_the_week and rating are of


datatype object.

 Note 1: Time is normally a continous variable therefore it should be


defined as float64. However, it is indicated in the problem statement
that time for food_preparation_time and delivery_time is measured in
minutes thus it is detected as int64.

 Note 2: rating is detected as object but it should be int64 since the


value is defined between 0 and 5. This indicates that there are missing
values or non-numerical entries in the data.

# Checking missing values

[Link]().sum()

order_id 0

customer_id 0

restaurant_name 0

cuisine_type 0

cost_of_the_order 0

day_of_the_week 0

rating 0

food_preparation_time 0

delivery_time 0

dtype: int64

# Count the occurences for each category

[Link].value_counts()
rating

Not given 736

5 588

4 386

3 188

Name: count, dtype: int64

Observations:

From previous observations, there are either missing values or non-numerical


entries in the rating column.

There are 736 not rated orders, that is almost 39% of the orders.

From the analyses above, ratings were not given for almost 39% of the
orders. We'll treat 'Not given' as another categorical variable.

# Descriptive statistics for the numerical variables

[Link]().T

co
mean std min 25% 50% 75% max
unt

18 1.4774 1476 1477 1477 1.4779 1478


548.04
order_id 98. 96e+0 547.0 021.2 495.5 70e+0 444.0
9724
0 6 0 5 0 6 0

18 1.7116 113698 2.7052


customer_i 1311. 7778 1286 4053
98. 85e+0 .13974 50e+0
d 00 7.75 00.00 34.00
0 5 3 5

18 1.6498 2.2297
cost_of_th 7.4838
98. 85e+0 4.47 12.08 14.14 50e+0 35.41
e_order 12
0 1 1

food_prepa 18 2.7371 3.1000


4.6324
ration_tim 98. 97e+0 20.00 23.00 27.00 00e+0 35.00
81
e 0 1 1

delivery_ti 18 2.4161 4.9726 15.00 20.00 25.00 2.8000 33.00


co
mean std min 25% 50% 75% max
unt

98. 75e+0 00e+0


me 37
0 1 1

Observations:

The minimum time it takes for food to be prepared is 20 minutes whereas


the maximum is 35 minutes. Aditionally, the average is 27.37 minutes.

Question 5: How many orders are not rated?

Exploratory Data Analysis (EDA)

Univariate Analysis

# Boxplot for the order_id variable

[Link](data=df, x='order_id');

Observations:
 The maximum and minimum of order_id is 1898. This is exactly, the
number of rows of the data set thus this colum is just a numbering of
the orders.

# Histogram for the customer_id variable

[Link](data=df, x='customer_id', kde=True); # kde to see the


distribution

[Link](rotation=45) # rotate the ticks of x axis to better visualization

[Link]()

Observations:

 The distribution ranges between 0 and 400000.

 The user with id between 3000 and 16000 order food most often than
the other users.

 There are two peaks in the distribution. One around 8000 and the
second around 36000 thousand. This is a bimode distribution.
# Bar plot for the cuisine_type variable

[Link](data=df, x='cuisine_type');

[Link](rotation=90) # rotate the ticks of x axis to better visualization

[Link]()

Observations:

 The three most order foods are American, Japanese and Italian in this
order.

 The three least order foods are Vietnamese, Korean and Spanish in this
order.

# Histogram for the cost_of_the_order variable

[Link](data=df, x='cost_of_the_order', kde=True);


[Link]()

# Boxplot for cost_of_the_order variable

[Link](data=df, x='cost_of_the_order')

[Link]()
Observations:

 The data for cost_of_the_order ranges between 5 and 35.

 50% of the data lies between 12 and 22, aproximately.

 There are no outliers.

 There are three peaks on the distribution. One of them is around 13.5
which almost coincide with the median of 14 (aproximately).

# Bar plot for day_of_the_week variable

[Link](data=df, x='day_of_the_week');

[Link]()
Observations:

 Most of the orders are made during the weekend. That is around 1350
orders.

# Bar plot for rating variable

[Link](data=df, x='rating')

[Link]()
Observtions:

 Almost 39% of the orders have no rating.

 ~31% of the orders have 5 as rating.

 A rating of 4 was given to ~20% of the orders.

 Finally, ~9% of the orders were rated with 3.

# Bar plot for food_preparation_time variable

[Link](data=df, x='food_preparation_time');

[Link]()
Observations:

 Since we treat time as a discreate variable, we use a bar graph.

 It seems that the distribution behaves as a uniform distribution.

# Histogram for delivery_time variable

[Link](data=df, x='delivery_time', kde=True);

[Link]()
# Boxplot for delivery_time variable

[Link](data=df, x='delivery_time')

[Link]()
Observations:

 The median of the data is 25.

 There's a single peak at 26.

 50% of the data is between 20 and 28.

 The data seems to follow a normal distribution around 25.

# Counts the number of ocurrences for category in restaurant_name variable

df.restaurant_name.value_counts()

restaurant_name

Shake Shack 219

The Meatball Shop 132

Blue Ribbon Sushi 119

Blue Ribbon Fried Chicken 96

Parm 68
...

Sushi Choshi 1

Dos Caminos Soho 1

La Follia 1

Philippe Chow 1

'wichcraft 1

Name: count, Length: 178, dtype: int64

Observations:

The top five restaurants are Shake Shack with 219 orders, The Meatball Shop
with 132 orders, Blue Ribbon Sushi with 119 orders, Blue Ribbon Fried
Chicken with 96 orders and Parm with 68 orders.

# Filter the data by 'Weekend' and count cuisine_type occurences

df[df['day_of_the_week'] == 'Weekend'].cuisine_type.value_counts()

cuisine_type

American 415

Japanese 335

Italian 207

Chinese 163

Mexican 53

Indian 49

Mediterranean 32

Middle Eastern 32

Thai 15

French 13

Korean 11

Southern 11

Spanish 11
Vietnamese 4

Name: count, dtype: int64

Observations:

The most popular cuisine on weekens is the American cuisine with 415
orders.

# Filter the data by order with cost greater than 20

# then divide by the total number of orders times 100

percent_orders = df[df['cost_of_the_order'] > 20].shape[0] / [Link][0] *


100

print(percent_orders)

29.24130663856691

Observations:

29.24% of the orders cost more than 20 dollars.

# Calculate the mean of the delivery_time variable

df['delivery_time'].mean()

24.161749209694417

Observations:

The mean order deliver time is 24.16

# Count the ocurrences for each category in the custimer_id variable

df.customer_id.value_counts()

customer_id

52832 13

47440 10

83287 9

250494 8

259341 7

..
385426 1

254913 1

289597 1

74412 1

397537 1

Name: count, Length: 1200, dtype: int64

Observations:

The users that will obtain the 20% discount vouchers are customer 52832
with 13 orders, customer 47440 with 10 orders and 83287 with 9 orders.

Multivariate Analysis

# Heatmap of the three main numerical variables

[Link](data=df[['cost_of_the_order', 'food_preparation_time',
'delivery_time']].corr(numeric_only=True), annot=True, cmap='YlGnBu');
Observations:

 We can observe that there is no correaltion among the


variables cost_of_the_order, food_preparation_time and delivery_time s
ince all the correlation coefficients are near zero.

# Boxplots of the cost_of_the_order by cuisine_type

[Link](data=df, x='cuisine_type', y='cost_of_the_order') ;

[Link](rotation=90)

[Link]()
Observations:

 The most expensive cuisines are French, Spanish and Southern.

 The least expensive cuisines are Vietnamese and Korean.

# Bar plot comparing the food_preparation_time by cuisine_type and


day_of_the_week

[Link](data=df, x="cuisine_type", y="food_preparation_time",


hue="day_of_the_week", kind='bar', palette='pastel');

[Link](rotation=90)

[Link]()
Observations:

 Generally, the preparation time is relatively similiar for every cuisine


either in weekend or weekdays

 It seems to take longer to prepare Spanish food on weedays.

# Boxplots of the delivery_time by day_of_the_week

[Link](data=df, x='day_of_the_week', y='delivery_time') ;

[Link]()
Observations:

 It is clear that there are higher delivery times during weekdays than in
weeknds

 The minimum wating time during weekdays is of around 24, almost


two thirds more compared to 15 minutes from weekends.

Here, we find the restaurants fulfilling the criteria to get the promotional
offer

df3 = df[df['rating'] != 'Not given'] # filtering the data

df3['rating'] = df3['rating'].astype(int) # change datatype of the rating


column

means = [Link]("restaurant_name")['rating'].mean() # calculate the


mean for each group

means = means[means > 4] # filtering the data

counts = [Link]("restaurant_name")['rating'].sum() # aggregation per


group
counts = counts.sort_values(ascending = False) # sorting the values

counts = counts[counts > 50] # filtering the data

for res, val in [Link]():

if means[res]: # checking if the restaurant meets both conditions

print(res)

Shake Shack

The Meatball Shop

Blue Ribbon Sushi

Blue Ribbon Fried Chicken

RedFarm Broadway

Parm

RedFarm Hudson

TAO

Han Dynasty

Blue Ribbon Sushi Bar & Grill

Nobu Next Door

Rubirosa

Momoya

Tamarind TriBeCa

Five Guys Burgers and Fries

Jack's Wife Freda

Blue Ribbon Sushi Izakaya

Sushi of Gari 46

Bareburger

Chipotle Mexican Grill $1.99 Delivery

Sushi of Gari Tribeca

ilili Restaurant
Cafe Mogador

J. G. Melon

The Smile

Observations:

These resutrants get the promotionl offer: Shake Shack, The Meatball Shop,
Blue Ribbon Sushi, Blue Ribbon Fried Chicken, RedFarm Broadway, Parm,
RedFarm Hudson, TAO, Han Dynasty, Blue Ribbon Sushi Bar & Grill, Nobu
Next Door, Rubirosa, Momoya, Tamarind TriBeCa, Five Guys Burgers and
Fries, Jack's Wife Freda, Blue Ribbon Sushi Izakaya, Sushi of Gari 46,
Bareburger, Chipotle Mexican Grill $1.99 Delivery, Sushi of Gari Tribeca, ilili
Restaurant, Cafe Mogador, J. G. Melon, The Smile.

Next, we find the net revenue generated by the company across all orders

# revenue for orders with cost greater than 20

revenue1 = df[df['cost_of_the_order'] > 20]['cost_of_the_order'].sum()

#revenue for orders with cost between 5 and 20

revenue2 = df[(df['cost_of_the_order'] <= 20) & (df['cost_of_the_order'] > 5)]


['cost_of_the_order'].sum()

revenue = revenue1*0.25 + revenue2*0.15 # calculating the revenue foe


the company

revenue

6166.303

Observations:

The net revenue for the company is of 6166.303 dollars.

The percentage of orders taking more than 60 minutes to get delivered is


calculated as follows.

# creating new column with the total time preparation + delivery

df['total_time'] = df['delivery_time'] + df['food_preparation_time']


# calculating the percentage

orders_more_than_60 = df[df['total_time'] >


60]['total_time'].shape[0]/[Link][0] *100

orders_more_than_60

10.537407797681771

Observations:

10.53% of orders take more than 60 minutes to get delivered.

The mean delivery time vary during weekdays and weekends as follows.

# grouping by day of the week and calculating the mean per category

weekdays_mean = [Link]('day_of_the_week')['delivery_time'].mean()

weekdays_mean

day_of_the_week

Weekday 28.340037

Weekend 22.470022

Name: delivery_time, dtype: float64

Observations:

There is a difference of ~6 minutes of delivery time between weekdays and


weekends. Weekdays having the largest delivery time.

Conclusion and Recommendations

Conclusions:

 A great amount of orders do not have a rating, ~39% of them.

 The delivery time has a percentage increase of ~26% on weekdays


compared to weekends.

 From around 1900 orders, only 6166$ were accumulated as revenue.

 There's no correlation between the continouos variables.

 Not many (less than 11%) of the deliveries take longer than one hour.

 People order more food on weekends.

Recommendations:
 Incentivize the customers to leave a rating to the restaurant such as a
discount on future orders. In this way, more clients will be attracted to
new restaurants.

 Change the charges to the restaurant, for example 15% for orders
betweem 5 and 15, 20% for orders between 15 and 25 and 25% for
orders greater than 25. This will incurr in higher revenues.

 The delivery time is higher on weekdays maybe because there is not a


large amount of courier. The company should incetivize the courier to
work during weekdays.

 Set a higher fee for restaurants during weekends.

You might also like