Food Accessibility in Hudson

Sharvi Jain
Data Mining the City
8 min readDec 10, 2018

Team Members: Sharvi Jain, Devaki Handa

INTRODUCTION:

The city of Hudson lies in the middle of a food desert, which means there are few grocery stores, very few, and those that exist are far apart. The only proper store is Walmart, which lies far off from the heart of the city, making it difficult for most residents to access it. The ones without a car suffer the most, since the public transportation system in the city is practically non-existent.

HUDSON CITY, COLUMBIA COUNTY, NY

To resolve the issue of accessibility, our solution is to flip the narrative, and take the groceries to the people instead of the other way around. By proposing mobile grocery trucks that can go around the city on a need based system, a greater capacity of the residents’ food/grocery needs can be met in the most economical way. In addition, the idea is to prepare an ideal schedule for these trucks in the city in order to benefit those without convenient access to grocery.

The strategy is better than introducing new grocery stores or bodegas because the grocery in the trucks would come from local farms, and hence, it would mean access to healthier food and boost the local business. It’s more convenient since people would practically have home-delivered food. It would also save the cost of fuel.

This would be done by taking into consideration a number of variables such as car ownership, proximity to the existing Walmart and income levels. The conflict points would then be analyzed and the issues would be resolved by creating a dynamic time schedule for grocery trucks throughout the week.

The city of Hudson has a population of 6,549 residents, which comprise of approximately 2,800 households. To try and tackle this issue, the number and households and all the variables related to it have been simplified and taken out 100 as shown in the flow-chart above.

Similar to how a company introduces the idea of a new product and tests whether it will work in the real market before actually launching the product for the world to use, simulating the usability of our product based on a set of variables will help us understand the grocery purchase patterns of people in the city.

TIME OF DAY: 8:00 — 9:00 a.m & 6:00–7:00 p.m
TIME OF DAY: 10:00 a.m–5:00 p.m
TIME OF DAY: 5:00 p.m — 6:00 p.m

VARIABLES:

The variables involved in the simulation testing of the mobile grocery trucks in Hudson are:

  • PROXIMITY TO WALMART:

35% of approximately 6500 residents in the city live within a radius of 1.5 miles from Walmart. This makes it easy for them to walk to the store even if they do not own a car. However, in the case when grocery bags are heavy, it becomes difficult for some people to walk back home with the weight of the bags.

  • CAR OWNERSHIP:

While about 80% of the households in Hudson have a car, others have no means of traveling to and from Walmart. Only the ones who choose to walk can actually access it.

A large percentage (40%) of these households only have one car, which is usually used by the working member of the family (60% of working people in Hudson commute to work by driving alone), which further reduces access to a viable method of reaching the Walmart.

  • WORK TIMINGS/ THE TIME WHEN A PERSON IS AT HOME:

People in the city who have some kind of a job tend to be away from 9 am to 6 pm on an average. The ones who don’t have a job could be at home at any hour of the day. The information is vital in order to understand the schedule of people so that the food truck can have time slots/a schedule that aligns with the availability of most, if not all the residents of the city in order to cater to everyone’s needs.

Commute time to and fro from work will also have to be incorporated to make a make accurate time schedule.

  • GROCERY PRICING (in this particular case, we have chosen apples for the sake of convenience):

Mobile grocery trucks, when introduced, will have fresh organic products from local farms. This means that the cost will be higher than the subsidized rates of products available at Walmart.

  • INCOME LEVELS:

Those with a relatively low mean salary suffer the most especially if they live at a significant distance from Walmart, since presumably they wouldn’t own a car, and can’t access grocery at subsidized rates, or otherwise. (48.7% of the households have an annual income of less than $30,000)

This group is the one that would get the most benefited by the introduction of this new system, presumably, despite the comparatively expensive apple prices of the mobile grocery truck.

  • QUALITY OF FOOD:

For people who find it difficult to afford food in the first place, might not choose to buy organic products if there was a choice. However, since food trucks cut down the need of owning a car, purchasing from trucks could become a viable option.

On the other hand, people who own a car have a choice — buying from mobile grocery trucks because the quality of food will be better versus buying cheaper, but relatively unhealthy food from Walmart.

  • COST OF FUEL:

This variable applies to those who own a car and have the luxury of choosing between purchasing groceries from Walmart versus purchasing from the mobile grocery trucks. It is a question of whether people choose to spend money on fuel and buy cheaper food versus if they choose to spend money on fresh food and convenience and not spend anything on the fuel.

CODE:

#CLASS FOR THE BALL
class Ball(object):
import random
def __init__(self,x,y):
self.name = "ball"
self.x = x
self.y = y


#this is where you create your percentages for each level
#Walkability
self.chance = 0 if random(0,1) < 0.35 else 1

#Car ownership
self.chance2 = 0 if random(0,1) < 0.85 else 1

#At Home
self.chance3 = 0 if random(0,1) < 0.3 else 1

#Time
self.chance4 = 0 if random(0,1) < 1.0 else 1

#change probability according to timing.
self.chance5 = 0 if random(0,1) < 0.7 else 1
def display (self):
fill(255, 255, 0)
speed = 1
self.y += speed
ellipse(self.x,self.y,20,20)

def check_if_down(self):
if self.y >= 150 and self.y <= 250:
if self.chance==0:
self.x += 1
else:
self.x -= 1

if self.y >= 350 and self.y <= 400:
if self.chance2==0:
self.x += 1
else:
self.x -= 1

if self.y >= 500 and self.y <= 525:
if self.chance3==0:
self.x += 1
else:
self.x -= 1

#4a
if self.x >= 312.5 and self.y >= 575 and self.x <=337.5 and self.y <= 587.5:
if self.chance4==0:
self.x += 1
else:
self.x -= 1
#4b
if self.x >= 362.5 and self.y >= 575 and self.x <=387.5 and self.y <= 587.5:
if self.chance5==0:
self.x += 1
else:
self.x -= 1


#4c
if self.x >= 412.5 and self.y >= 575 and self.x <= 437.5 and self.y <= 587.5:
if self.chance4==0:
self.x += 1
else:
self.x -= 1
#4d
if self.x >= 462.5 and self.y >= 575 and self.x <=487.5 and self.y <= 587.5:
if self.chance5==0:
self.x += 1
else:
self.x -= 1
#4e
if self.x >= 512.5 and self.y >= 575 and self.x <= 537.5 and self.y <= 587.5:
if self.chance4==0:
self.x += 1
else:
self.x -= 1
#4f
if self.x >= 562.5 and self.y >= 575 and self.x <=587.5 and self.y <= 587.5:
if self.chance5==0:
self.x += 1
else:
self.x -= 1
#4g
if self.x >= 612.5 and self.y >= 575 and self.x <= 637.5 and self.y <= 587.5:
if self.chance4==0:
self.x += 1
else:
self.x -= 1
#4h
if self.x >= 662.5 and self.y >= 575 and self.x <=687.5 and self.y <= 587.5:
if self.chance5==0:
self.x += 1
else:
self.x -= 1
#MAIN SKETCH
from ball import Ball
# x = []
# y = []
householdNumber = 100
# for i in range(householdNumber):
# x.append(random(0,800))
# y.append(random(0,800))
def setup():

global allBalls, b1

size(1000, 1000)

allBalls = []
b1 = Ball(-100, -100)
def draw():
global allBalls

background(0)
strokeWeight(4)
stroke(255)

#==================================

#first branch

line(500, 50, 500, 150)

stroke(255,0,0)
line(500, 150, 400, 250)
stroke(0,255,0)
line(500, 150, 600, 250)

#second branch
#right
stroke(255)
line(600, 250, 600, 350)

stroke(255,0,0)
line(600, 350, 550, 400)
stroke(0,255,0)
line(600, 350, 650, 400)
#left

stroke(255)
line(400, 250, 400, 350)
stroke(255,0,0)
line(400, 350, 350, 400)
stroke(0,255,0)
line(400, 350, 450, 400)

stroke(255)
line(350,400,350,500)

stroke(255,0,0)
line(350,500, 325,525)

stroke(0,255,0)
line(350,500,375,525)

stroke(255)
line(450,400,450,500)

stroke(255,0,0)
line(450,500,425,525)
stroke(0,255,0)
line(450,500,475,525)

stroke(255)
line(550,400,550,500)
line(650,400, 650,500)

stroke(255,0,0)
line(550,500,525,525)
stroke(0,255,0)
line(550,500,575,525)
stroke(255,0,0)
line(650,500,625,525)
stroke(0,255,0)
line(650,500,675,525)

stroke(255)
line (675,525,675,575)
line (625,525,625,575)
line (575,525,575,575)
line(525,525,525,575)

line (475,525,475,575)
line (425,525,425,575)
line (375,525,375,575)
line (325,525,325,575)

stroke(255,0,0)
line (325,575,312.5,587.5)
stroke(0,255,0)
line (325,575,337.5,587.5)

stroke(255,0,0)
line(375,575,362.5,587.5)
stroke(0,255,0)
line(375,575,387.5,587.5)

stroke(255,0,0)
line(425,575, 412.5,587.5)
stroke(0,255,0)
line(425,575, 437.5,587.5)

stroke(255,0,0)
line(475,575, 462.5,587.5)
stroke(0,255,0)
line(475,575, 487.5,587.5)

stroke(255,0,0)
line(525,575, 512.5,587.5)
stroke(0,255,0)
line(525,575, 537.5,587.5)

stroke(255,0,0)
line(575,575, 562.5,587.5)
stroke(0,255,0)
line(575,575, 587.5,587.5)

stroke(255,0,0)
line(625,575, 612.5,587.5)
stroke(0,255,0)
line(625,575, 637.5,587.5)

stroke(255,0,0)
line(675,575, 662.5,587.5)
stroke(0,255,0)
line(675,575, 687.5,587.5)

# rect(312.5, 575, 25, 12)

f=createFont("Corbel",60,True)
textFont(f,20)
fill (255)
text("WALKABILITY",120,145)
text("CAR OWNERSHIP",120,345)
text("EMPLOYED",120,495)
text("TIME",120,570)


stroke (150)
strokeWeight(1)
line(120,150,850,150)
line(120,350,850,350)
line(120,500,850,500)
line(120,575,850,575)
#==================================

noStroke()
noFill()
for ball in allBalls:
ball.display()
ball.check_if_down()


fill(255)
f=createFont("Corbel",60,True)
textFont(f,20)
# text("HOUSEHOLDS THAT HAVE ACCESS", 100,700,60)
text("NO. OF HOUSEHOLDS " + str(len(allBalls)),408,30,60)

fill(255,0, 0)
text("HOUSEHOLDS THAT DON'T HAVE ACCESS: ", 530,700,60)

fill(0, 255, 0)
text("HOUSEHOLDS THAT HAVE ACCESS", 100,700,60)

def mousePressed():
global allBalls, b1

fill(255)
b1 = Ball(500,50)
allBalls.append(b1)

OUTCOMES:

After considering the four major parameters — walkability to Walmart, car ownership, number of people employed and their work timings, we found out that 6:00–10:00 am and 5:00 -10:00 pm are the time slots that were more suitable than others to provide a greater food access through mobile grocery trucks to the households in the city of Hudson.

For the sake of this simulation only the major parameters were taken into consideration, others could be added to get more fine-tuned results.

FUTURE OF SIMULATION:

Due to the dynamic nature of this scheduling framework, it could be implemented in a number of other cities having similar issues. Depending on the importance of certain variables, depending on the city, the weightage of certain aspects could be altered to get completely different results. It could act as a different version of a multi-criteria decision making analysis tool.

REFERENCES:

https://censusreporter.org/profiles/16000US3635969-hudson-ny/

https://datausa.io/profile/geo/hudson-ny/#num_vehicles

--

--