Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Impact calculation based on SIC code

  • Loading branch information...
commit f0a3b596eab8e69f191c9f0647f3dfdd08d9b11c 1 parent a6d16e2
@ihough ihough authored
View
22 features/purchase_committees.feature
@@ -59,6 +59,16 @@ Feature: Purchase Committee Calculations
Then the committee should have used quorum "default"
And the conclusion of the committee should include a key of "" and value ""
+ Scenario Outline: Trade industry ratios from sic industry
+ Given a characteristic "sic_industry.code" of "<sic>"
+ When the "trade_industry_ratios" committee reports
+ Then the committee should have used quorum "from sic industry"
+ And the conclusion of the committee should include a key of "<key>" and value "<value>"
+ Examples:
+ | sic | key | value |
+ | 5411 | 459000 | 1.0 |
+ | 5419 | 459000 | 0.5 |
+
Scenario: Trade industry ratios from merchant category industries
Given a characteristic "merchant_category.mcc" of "2222"
When the "merchant_category_industries" committee reports
@@ -85,6 +95,18 @@ Feature: Purchase Committee Calculations
Then the committee should have used quorum "default"
And the conclusion of the committee should include a key of "339991" and value "1"
+ Scenario Outline: Non-trade industry from ratios sic industry
+ Given a characteristic "sic_industry.code" of "<sic>"
+ When the "non_trade_industry_ratios" committee reports
+ Then the committee should have used quorum "from sic industry"
+ And the conclusion of the committee should include a key of "<key>" and value "<value>"
+ Examples:
+ | sic | key | value |
+ | 1111 | 111111 | 1.0 |
+ | 2111 | 399100 | 0.5 |
+ | 2111 | 399200 | 0.5 |
+ | 5419 | 399900 | 0.5 |
+
Scenario Outline: Non-trade industry ratios from merchant category industries
Given a characteristic "merchant_category.mcc" of "<mcc>"
When the "merchant_category_industries" committee reports
View
10 features/purchase_impacts.feature
@@ -30,6 +30,16 @@ Feature: Purchase Emissions Calculations
| 1 | 789.625 |
| 2 | 1710.633 |
+ Scenario Outline: Calculations starting from a sic industry
+ Given it has "sic_industry.code" of "<code>"
+ And it is the year "2010"
+ When impacts are calculated
+ Then the amount of "carbon" should be within "0.001" of "<emission>"
+ Examples:
+ | code | emission |
+ | 1111 | 789.625 |
+ | 5419 | 1710.633 |
+
Scenario Outline: Calculations starting from a merchant with purchase amount
Given it has "merchant.id" of "<id>"
And it has "purchase_amount" of "<amount>"
View
7 features/support/db/fixtures/naics_2002.csv
@@ -0,0 +1,7 @@
+code,description
+111111,A simple industry
+339991,The industry whose emissions intensity is closest to that of the entire US economy
+399100,Fantasy creature raising
+399200,Fantasy creature slaughtering
+399900,Fantasy creature processing
+459000,Retail stores specializing in fantasy creature products
View
7 features/support/db/fixtures/naics_2002_sic_1987_concordances.csv
@@ -0,0 +1,7 @@
+naics_2002_code,sic_1987_code
+111111,1111
+399100,2111
+399200,2111
+459000,5411
+399900,5419
+459000,5419
View
5 features/support/db/fixtures/sic_1987.csv
@@ -0,0 +1,5 @@
+code,description
+1111,Simple industries
+2111,Fantasy creature raising and slaughtering
+5411,Fantasy creature product shops
+5419,Fantasy creature and mixed product shops
View
31 lib/purchase/characterization.rb
@@ -13,49 +13,52 @@ def self.included(base)
has :merchant_category do |mc|
mc.description
end
- has :merchant_category_industries do |mci|
+ has :merchant_category_industries do |mci| # for display; not expected to be input
"#{mci.count} merchant category(s)"
end
+ has :sic_industry do |ind|
+ ind.description
+ end
has :industry do |ind|
ind.description
end
- has :trade_industry_ratios do |tir|
+ has :trade_industry_ratios do |tir| # for display; not expected to be input
"#{tir.count} trade industry ratio(s)"
end
- has :non_trade_industry_ratios do |ntir|
+ has :non_trade_industry_ratios do |ntir| # for display; not expected to be input
"#{ntir.count} non-trade industry ratio(s)"
end
- has :product_line_ratios do |plr|
+ has :product_line_ratios do |plr| # for display; not expected to be input
"#{plr.count} product line ratio(s)"
end
- has :product_line_industry_product_ratios do |plipr|
+ has :product_line_industry_product_ratios do |plipr| # for display; not expected to be input
"#{plipr.count} product line industry product ratio(s)"
end
- has :industry_product_ratios do |ipr|
+ has :industry_product_ratios do |ipr| # for display; not expected to be input
"#{ipr.count} industry product ratio(s)"
end
- has :industry_ratios do |ir|
+ has :industry_ratios do |ir| # for display; not expected to be input
"#{ir.count} industry ratio(s)"
end
- has :industry_sector_ratios do |isr|
+ has :industry_sector_ratios do |isr| # for display; not expected to be input
"#{isr.count} industry sector ratio(s)"
end
- has :industry_sector_shares do |isr|
+ has :industry_sector_shares do |isr| # for display; not expected to be input
"#{isr.count} industry sector share(s)"
end
- has :sector_shares do |isr|
+ has :sector_shares do |isr| # for display; not expected to be input
"#{isr.size}-element sector shares vector"
end
- has :sector_direct_requirements do |sdr|
+ has :sector_direct_requirements do |sdr| # for display; not expected to be input
"#{sdr.row_size}x#{sdr.column_size} sector direct requirements matrix"
end
- has :economic_flows do |ef|
+ has :economic_flows do |ef| # for display; not expected to be input
"#{ef.size}-element economic flows vector"
end
- has :impact_vectors do |iv|
+ has :impact_vectors do |iv| # for display; not expected to be input
"#{iv.row_size}x#{iv.column_size} impact vector"
end
- has :impacts do |i|
+ has :impacts do |i| # for display; not expected to be input
"#{i.size}-element impacts vector"
end
end
View
1  lib/purchase/data.rb
@@ -11,6 +11,7 @@ def self.included(base)
base.col :date, :type => :date
base.col :merchant_id
base.col :mcc
+ base.col :sic_1987_code
base.col :naics_code
end
end
View
65 lib/purchase/impact_model.rb
@@ -12,34 +12,34 @@ module Purchase
module ImpactModel
def self.included(base)
base.extend ::Leap::Subject
-
+
base.decide :impact, :with => :characteristics do
committee :carbon do
quorum 'from impacts', :needs => :impacts do |characteristics|
characteristics[:impacts].to_a.sum
end
end
-
+
committee :impacts do
quorum 'from economic flows and impact vectors', :needs => [:economic_flows, :impact_vectors] do |characteristics|
# subverting charisma
characteristics[:impact_vectors].value * characteristics[:economic_flows].value
end
end
-
+
committee :impact_vectors do
quorum 'from database' do
::BrighterPlanet::Purchase.impact_vectors_adapter.matrix
end
end
-
+
committee :economic_flows do
quorum 'from sector shares, a', :needs => [:sector_shares, :sector_direct_requirements] do |characteristics|
# subverting charisma
characteristics[:sector_direct_requirements].value * characteristics[:sector_shares].value
end
end
-
+
committee :sector_direct_requirements do
quorum 'from database' do
BrighterPlanet::Purchase.sector_direct_requirements_adapter.matrix
@@ -54,7 +54,7 @@ def self.included(base)
::Vector[*shares]
end
end
-
+
committee :industry_sector_shares do
quorum 'from industry sector ratios', :needs => [:industry_sector_ratios, :adjusted_cost] do |characteristics|
characteristics[:industry_sector_ratios].inject({}) do |new_ratios, (io_code, ratio)|
@@ -64,7 +64,7 @@ def self.included(base)
end
end
end
-
+
committee :industry_sector_ratios do
quorum 'from industry ratios', :needs => :industry_ratios do |characteristics|
naics_codes = characteristics[:industry_ratios].keys
@@ -81,7 +81,7 @@ def self.included(base)
end
end
end
-
+
# industries = the industries needed to produce the purchased item
# ratios = the portion of the purchase amount that goes to each industry
committee :industry_ratios do
@@ -92,7 +92,7 @@ def self.included(base)
end
end
end
-
+
committee :industry_product_ratios do
quorum 'from product line industry product ratios', :needs => :product_line_industry_product_ratios do |characteristics|
naics_product_codes = characteristics[:product_line_industry_product_ratios].keys
@@ -108,7 +108,7 @@ def self.included(base)
end
end
end
-
+
committee :product_line_industry_product_ratios do
quorum 'from product line ratios', :needs => :product_line_ratios do |characteristics|
ps_codes = characteristics[:product_line_ratios].keys
@@ -123,7 +123,7 @@ def self.included(base)
end
end
end
-
+
committee :product_line_ratios do
quorum 'from trade industry ratios', :needs => :trade_industry_ratios do |characteristics|
naics_codes = characteristics[:trade_industry_ratios].keys
@@ -140,7 +140,7 @@ def self.included(base)
end
end
end
-
+
committee :non_trade_industry_ratios do
quorum 'from industry', :needs => :industry do |characteristics|
if characteristics[:industry].trade_industry?
@@ -149,7 +149,7 @@ def self.included(base)
{ characteristics[:industry].naics_code.to_s => 1 }
end
end
-
+
quorum 'from merchant category industries', :needs => :merchant_category_industries do |characteristics|
characteristics[:merchant_category_industries].
reject { |mci| mci.industry.trade_industry? }.inject({}) do |ntir, merchant_category_industry|
@@ -159,13 +159,25 @@ def self.included(base)
end
end
+ quorum 'from sic industry', :needs => :sic_industry do |characteristics|
+ if (count = characteristics[:sic_industry].industries.count) > 0
+ characteristics[:sic_industry].industries.reject{ |i| i.trade_industry? }.inject({}) do |ntir, industry|
+ ntir[industry.naics_code] ||= 0
+ ntir[industry.naics_code] += 1.0 / count
+ ntir
+ end
+ else
+ nil # return nil if we can't map the SIC industry to any Industries so that we use the default quorum
+ end
+ end
+
# NAICS 339991 chosen because it's emissions intensity is close to the average of the entire U.S. economy
# (calculated by multiplying each sector's emissions intensity by it's share of total 2002 value)
quorum 'default' do
{ '339991' => 1 }
end
end
-
+
committee :trade_industry_ratios do
quorum 'from industry', :needs => :industry do |characteristics|
if characteristics[:industry].trade_industry?
@@ -174,7 +186,7 @@ def self.included(base)
{}
end
end
-
+
quorum 'from merchant category industries', :needs => :merchant_category_industries do |characteristics|
characteristics[:merchant_category_industries].
select { |mci| mci.industry.trade_industry? }.inject({}) do |tir, merchant_category_industry|
@@ -184,18 +196,29 @@ def self.included(base)
end
end
+ quorum 'from sic industry', :needs => :sic_industry do |characteristics|
+ # This will return {} if there are no trade industry ratios but that's ok b/c it's the same as the default
+ if (count = characteristics[:sic_industry].industries.count) > 0
+ characteristics[:sic_industry].industries.select{ |i| i.trade_industry? }.inject({}) do |tir, industry|
+ tir[industry.naics_code] ||= 0
+ tir[industry.naics_code] += 1.0 / count
+ tir
+ end
+ end
+ end
+
quorum 'default' do
{}
end
end
-
+
# a dictionary to go from merchant categories to industries
committee :merchant_category_industries do
quorum 'from merchant category', :needs => :merchant_category do |characteristics|
characteristics[:merchant_category].merchant_category_industries
end
end
-
+
committee :merchant_category do
quorum 'from merchant', :needs => [:merchant] do |characteristics|
characteristics[:merchant].merchant_category
@@ -208,11 +231,11 @@ def self.included(base)
@cpi_lookup ||= {
2009 => 1.189, 2010 => 1.207, 2011 => 1.225, 2012 => 1.245,
2013 => 1.265 }
-
+
date = characteristics[:date]
date = date.is_a?(String) ? Date.parse(date) : date
conversion_factor = @cpi_lookup[date.year] || 1.207
-
+
characteristics[:cost].to_f / conversion_factor
end
@@ -222,7 +245,7 @@ def self.included(base)
517
end
end
-
+
committee :cost do
quorum 'from purchase amount and tax', :needs => [:purchase_amount, :tax] do |characteristics|
characteristics[:purchase_amount].to_f - characteristics[:tax].to_f
@@ -233,7 +256,7 @@ def self.included(base)
characteristics[:purchase_amount].to_f / 1.0711
end
end
-
+
committee :date do
quorum 'default' do
Date.today
View
1  lib/purchase/relationships.rb
@@ -4,6 +4,7 @@ module Relationships
def self.included(target)
target.belongs_to :merchant, :foreign_key => 'merchant_id'
target.belongs_to :merchant_category, :foreign_key => 'mcc'
+ target.belongs_to :sic_industry, :foreign_key => 'sic_1987_code', :class_name => 'Sic1987'
target.belongs_to :industry, :foreign_key => 'naics_code'
end
end
View
3  purchase.gemspec
@@ -21,7 +21,8 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
-
+
+ s.add_runtime_dependency 'earth', '~>0.11.12'
s.add_runtime_dependency 'emitter', '~>0.11.0'
s.add_development_dependency 'sniff', '~>0.11.3'
s.add_development_dependency 'sqlite3'
Please sign in to comment.
Something went wrong with that request. Please try again.