Skip to content

Commit

Permalink
Merge pull request #45 from mattwigway/automated-tests
Browse files Browse the repository at this point in the history
Automated tests
  • Loading branch information
mattwigway authored Sep 24, 2020
2 parents 8be7ec5 + 8772b3f commit 84cf1dc
Show file tree
Hide file tree
Showing 19 changed files with 107 additions and 4 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# run the linter and tests
# copied and lightly edited from https://docs.github.com/en/actions/guides/building-and-testing-python

name: eqsormo

on: [push]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
# only supporting py 3.7/3.8
python-version: [3.7, 3.8]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install -r requirements.txt
- name: Install package
run: |
python setup.py install
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
6 changes: 5 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ dependencies:
- numpy>=1.0
- pandas>=1.0
- dill>=0.3
- scipy>=1.5
- scipy>=1.5
- python>=3.7
# figure out how to mark these as dev dependencies
- flake8>=3.7
- pytest>=6
7 changes: 7 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
statsmodels>=0.11
tqdm>=4.0
numba>=0.51
numpy>=1.0
pandas>=1.0
dill>=0.3
scipy>=1.5
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
max-line-length = 120
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
setup(
name='eqsormo',
version='0.2.3',
packages=find_packages(),
packages=find_packages('src'),
package_dir={'': 'src'},
requirements=['statsmodels>=0.11', 'tqdm>=4.0', 'numba>=0.51', 'numpy>=1.0', 'pandas>=1.0', 'dill>=0.3', 'scipy>=1.5'],
author='Matthew Wigginton Conway',
author_email='[email protected]',
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ def __repr__ (self):
# box-cox transform of income - price
# Box and Cox (1964)
# NB any price > income should be taken care of by a max_rent_to_income parameter
# TODO can we remove the max rent to income param here?
boxcoxdiff = FunctionalForm(lambda income, price, lmbda: scipy.stats.boxcox(np.maximum(income - price, 1), lmbda=lmbda), 'boxcox(income - price)',
n_params=1, param_names=['boxcox_lambda'])

# Form suggested by Stephane Hess in his advanced discrete choice modelling class, London, UK, July 2019
# Note that this will not behave right if called on a subset of the data, since it uses the mean of income
hess = FunctionalForm(lambda income, price, hess_lambda: ((income / np.mean(income)) ** hess_lambda) * price,
'Hess: (income / mean(income)) ^ lambda * price', n_params=1, param_names=['hess_lambda'], starting_values=[-1])
# Removed because these functions are now always called on subsets
# hess = FunctionalForm(lambda income, price, hess_lambda: ((income / np.mean(income)) ** hess_lambda) * price,
# 'Hess: (income / mean(income)) ^ lambda * price', n_params=1, param_names=['hess_lambda'], starting_values=[-1])
File renamed without changes.
File renamed without changes.
49 changes: 49 additions & 0 deletions tests/tra/test_price_income_transformation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright 2020 Matthew Wigginton Conway

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Author: Matthew Wigginton Conway <[email protected]>, School of Geographical Sciences and Urban Planning, Arizona State University

from eqsormo.tra import price_income
import numpy as np
import scipy.stats
import pandas as pd

income = np.array([100, 150, 30, 20, 70])
price = np.array([8, 12, 14, 9, 10])

def test_logdiff ():
assert np.allclose(price_income.logdiff.apply(income, price), np.log(income - price))

def test_sqrtdiff ():
assert np.allclose(price_income.sqrtdiff.apply(income, price), np.sqrt(income - price))

def test_normdiff ():
assert np.allclose(price_income.normdiff.apply(income, price, 200), scipy.stats.norm.cdf(income - price, scale=200))
assert np.allclose(price_income.normdiff.apply(income, price, 300), scipy.stats.norm.cdf(income - price, scale=300))
# make sure the scale param has an effect
assert not np.allclose(price_income.normdiff.apply(income, price, 300), price_income.normdiff.apply(income, price, 200))
# make sure it works with price > income - this transformation can handle this, unlike the other transformations
bigprice = np.array([8, 12, 14, 30, 10])
assert np.any(bigprice > income)
assert not pd.isnull(price_income.normdiff.apply(income, bigprice, 200)).any()

def test_boxcox ():
assert np.allclose(price_income.boxcoxdiff.apply(income, price, 1), scipy.stats.boxcox(income - price, lmbda=1))
assert np.allclose(price_income.boxcoxdiff.apply(income, price, 3), scipy.stats.boxcox(income - price, lmbda=3))
assert not np.allclose(price_income.boxcoxdiff.apply(income, price, 1), price_income.boxcoxdiff.apply(income, price, 3))
# TODO test behavior when price >= income




0 comments on commit 84cf1dc

Please sign in to comment.