class Eaternet::Agencies::Nyc
A data source for New York City food service health inspections. It retrieves the latest CSV export from [the official source](data.cityofnewyork.us/Health/DOHMH-New-York-City-Restaurant-Inspection-Results/xx67-kt59) and makes it easy to work with. See our [NYC wiki page](github.com/eaternet/adapters/wiki/Agency:-New-York-City) for details about the data set.
Output is produced in the [LIVES 1.0](www.yelp.com/healthscores) format developed by Yelp and the cities of San Francisco and New York.
The downloaded CSV is cached for twelve hours in a temporary file.
@example Print the names of all the restaurants in New York City
require 'eaternet' nyc = Eaternet::Nyc.new puts nyc.businesses.map(&:name)
@example Compute the average inspection score
# The library is optimized for memory use at the expense # of speed. E.g., each call to #inspections will iterate # through the raw CSV. So here, we first retrieve the # inspections into an array. inspections = nyc.inspections.to_a sum = inspections .map(&:score) .reduce(0, :+) count = inspections.count puts "Average inspection score: #{sum / count}"
@example See the Instance Method Details for more examples.
@see data.cityofnewyork.us/Health/DOHMH-New-York-City-Restaurant-Inspection-Results/xx67-kt59 NYC health scores official data, hosted on Socrata
Public Class Methods
Create an NYC data-source, ready for querying.
@example
nyc = Eaternet::Nyc.new
@param [String] csv_path for unit testing
# File lib/eaternet/agencies/nyc.rb, line 59 def initialize(csv_path: nil) @fixture_table_file = csv_path end
Private Class Methods
# File lib/eaternet/agencies/nyc.rb, line 206 def self.csv_url Eaternet::Socrata.csv_url domain: 'data.cityofnewyork.us', dataset: 'xx67-kt59' end
Fastest method for downloading all data but may be non-standard for Socrata
.
# File lib/eaternet/agencies/nyc.rb, line 202 def self.download_via_url Eaternet::Util.download_and_cache(source: csv_url, dest: Tempfile.new('nyc')) end
Public Instance Methods
@private
# File lib/eaternet/agencies/nyc.rb, line 139 def business(row) address = "#{row['BUILDING']} #{row['STREET']}" Eaternet::Lives_1_0::Business.new do |b| b.business_id = business_id(row) b.name = row['DBA'] b.address = address b.city = row['BORO'] b.postal_code = row['ZIPCODE'] b.state = 'NY' b.phone_number = row['PHONE'] end end
@example Print the number of restaurants in New York.
puts nyc.businesses.count
@return [Enumerable<Business>]
# File lib/eaternet/agencies/nyc.rb, line 67 def businesses map_csv { |row| try_to_create(:business, from_csv_row: row) } .uniq .compact end
@example Print the name & URL of NYC's health agency.
puts nyc.feed_info.municipality_name puts nyc.feed_info.municipality_url
@return [FeedInfo]
# File lib/eaternet/agencies/nyc.rb, line 104 def feed_info # Anyone know a contact email? Eaternet::Lives_1_0::FeedInfo.new do |fi| fi.feed_date = Date.today fi.feed_version = '1.0' fi.municipality_name = 'New York City' fi.municipality_url = 'http://www.nyc.gov/html/doh/html/services/restaurant-inspection.shtml' end end
@example Compute the average inspection score for NYC.
# The library is optimized for memory use at the expense # of speed. E.g., each call to #inspections will iterate # through the raw CSV. So here, we first retrieve the # inspections into an array. inspections = nyc.inspections.to_a sum = inspections .map(&:score) .reduce(0, :+) count = inspections.count puts "Average inspection score: #{sum / count}"
@return [Enumerable<Inspection>]
# File lib/eaternet/agencies/nyc.rb, line 87 def inspections map_csv { |row| skip_inspection?(row) ? nil : try_to_create(:inspection, from_csv_row: row) } .uniq .compact end
@return [Enumerable<Legend>]
# File lib/eaternet/agencies/nyc.rb, line 115 def legends Eaternet::Lives_1_0::LegendGroup.new do |lg| lg.legends = [ Eaternet::Lives_1_0::Legend.new do |l| l.minimum_score = 87 l.maximum_score = 100 l.description = 'A' end, Eaternet::Lives_1_0::Legend.new do |l| l.minimum_score = 73 l.maximum_score = 86 l.description = 'B' end, Eaternet::Lives_1_0::Legend.new do |l| l.minimum_score = 0 l.maximum_score = 72 l.description = 'C' end ] end.legends end
@return [Enumerable<Violation>]
# File lib/eaternet/agencies/nyc.rb, line 94 def violations map_csv { |row| skip_violation?(row) ? nil : violation(row) } .compact end
Private Instance Methods
# File lib/eaternet/agencies/nyc.rb, line 210 def adapter_name 'NYC' end
# File lib/eaternet/agencies/nyc.rb, line 180 def business_id(row) row['CAMIS'] end
# File lib/eaternet/agencies/nyc.rb, line 164 def inspection(row) Eaternet::Lives_1_0::Inspection.new do |i| i.business_id = business_id(row) i.date = Date.strptime(row['INSPECTION DATE'], '%m/%d/%Y') i.score = 100 - row['SCORE'].to_i end end
# File lib/eaternet/agencies/nyc.rb, line 176 def skip_inspection?(row) transfat_inspection?(row) end
# File lib/eaternet/agencies/nyc.rb, line 172 def skip_violation?(row) transfat_inspection?(row) || violation_code(row).nil? end
# File lib/eaternet/agencies/nyc.rb, line 196 def table_file @fixture_table_file || Nyc.download_via_url end
# File lib/eaternet/agencies/nyc.rb, line 188 def transfat_inspection?(row) if row['INSPECTION TYPE'] row['INSPECTION TYPE'].include?('Trans Fat') else false end end
# File lib/eaternet/agencies/nyc.rb, line 155 def violation(row) Eaternet::Lives_1_0::Violation.new do |v| v.business_id = business_id(row) v.date = Date.strptime(row['INSPECTION DATE'], '%m/%d/%Y') v.code = violation_code(row) v.description = row['VIOLATION DESCRIPTION'] end end
# File lib/eaternet/agencies/nyc.rb, line 184 def violation_code(row) row['VIOLATION CODE'] end