From 73a86795ccd72b8c43845ab1c24884c84abcc9cb Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 18:04:31 +0000 Subject: [PATCH 01/29] Include sample --- assesspy/data/IAAO_sample.csv | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 assesspy/data/IAAO_sample.csv diff --git a/assesspy/data/IAAO_sample.csv b/assesspy/data/IAAO_sample.csv new file mode 100644 index 0000000..9b1c85a --- /dev/null +++ b/assesspy/data/IAAO_sample.csv @@ -0,0 +1,18 @@ +estimate, sale_price +87200, 138720 +38240, 59700 +96320, 146400 +68610, 99000 +32960, 47400 +50560, 70500 +61360, 78000 +47360, 60000 +56580, 69000 +47040, 55500 +136000, 154500 +98000, 109500 +56000, 60000 +159100, 168000 +128000, 124500 +132000, 127500 +160000, 150000 \ No newline at end of file From 64019581eec36f6ca10983d605747cfa9053eea1 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 20:45:12 +0000 Subject: [PATCH 02/29] Add working docs --- assesspy/load_data.py | 21 +++++++++++++++++++++ assesspy/tests/conftest.py | 4 ++++ assesspy/tests/test_metrics.py | 20 ++++++++++++++++++++ docs/source/IAAO_sample.rst | 5 +++++ docs/source/reference.rst | 1 + 5 files changed, 51 insertions(+) create mode 100644 docs/source/IAAO_sample.rst diff --git a/assesspy/load_data.py b/assesspy/load_data.py index dcca6c7..bbddd3b 100644 --- a/assesspy/load_data.py +++ b/assesspy/load_data.py @@ -50,3 +50,24 @@ def quintos_sample() -> pd.DataFrame: source = files("assesspy").joinpath("data/quintos_sample.csv") with as_file(source) as file: return pd.read_csv(file) + + +def IAAO_sample() -> pd.DataFrame: + """ + Sample of sales and estimated market values provided by the IAAO in the following report: + + .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf + + :return: + A Pandas DataFrame with 18 observation and 2 variables: + + ======================== ===================================================== + **estimate** (`float`) Assessed fair market value + **sale_price** (`float`) Recorded sale price of this property + ======================== ===================================================== + + :rtype: pd.DataFrame + """ + source = files("assesspy").joinpath("data/IAAO_sample.csv") + with as_file(source) as file: + return pd.read_csv(file) \ No newline at end of file diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index 47239c9..853409d 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -22,6 +22,10 @@ def quintos_data() -> tuple: sample = ap.quintos_sample() return sample.estimate, sample.sale_price +@pt.fixture(scope="session") +def IAAO_data() -> tuple: + sample = ap.IAAO_sample() + return sample.estimate, sample.sale_price @pt.fixture( scope="session", diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 946b237..5cf2e38 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -46,3 +46,23 @@ def test_metric_met_function_thresholds(self, metric, metric_val): "mki": False, } assert getattr(ap, f"{metric}_met")(metric_val) == expected[metric] + +def test_iaao_metrics(IAAO_sample): + """ + Test that COD, PRB, and PRD for the IAAO_sample return expected values. + """ + estimates, sale_prices = IAAO_sample + + # Calculate COD + cod = ap.cod(estimates, sale_prices) + + # Calculate PRB + prb = ap.prb(estimates, sale_prices) + + # Calculate PRD + prd = ap.prd(estimates, sale_prices) + + # Assert the COD, PRB, and PRD are as expected + assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" + assert prb == -0.035, f"Expected PRB to be -0.035, but got {prb}" + assert prd == 0.98, f"Expected PRD to be .98, but got {prd}" diff --git a/docs/source/IAAO_sample.rst b/docs/source/IAAO_sample.rst new file mode 100644 index 0000000..75439bb --- /dev/null +++ b/docs/source/IAAO_sample.rst @@ -0,0 +1,5 @@ +================================ +Sample data from IAAO ratio study +================================ + +.. autofunction:: assesspy.IAAO_sample diff --git a/docs/source/reference.rst b/docs/source/reference.rst index 2c69f82..3d6baed 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -87,5 +87,6 @@ Data :doc:`ccao_sample() ` :doc:`quintos_sample() ` +:doc:`IAAO_sample() ` .. |nbsp| unicode:: 0xA0 From a7c94e2a7f8fc64ea2ac570a4c3e237ee67b5d2e Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 20:47:49 +0000 Subject: [PATCH 03/29] Rename to sample --- assesspy/tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index 853409d..f3c359b 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -23,7 +23,7 @@ def quintos_data() -> tuple: return sample.estimate, sample.sale_price @pt.fixture(scope="session") -def IAAO_data() -> tuple: +def IAAO_sample() -> tuple: sample = ap.IAAO_sample() return sample.estimate, sample.sale_price From 47bb00bac7eea9adb3cfb30591fa4714913a8f01 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 20:48:08 +0000 Subject: [PATCH 04/29] Add init --- assesspy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assesspy/__init__.py b/assesspy/__init__.py index 0284e20..0c8b6ea 100644 --- a/assesspy/__init__.py +++ b/assesspy/__init__.py @@ -4,7 +4,7 @@ prb_ci, prd_ci, ) -from .load_data import ccao_sample, quintos_sample +from .load_data import ccao_sample, quintos_sample, IAAO_sample from .metrics import ( cod, cod_met, From 9c6e5fc066c8ad8c7a4b458f1d48fa2ff4980c5c Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 20:50:53 +0000 Subject: [PATCH 05/29] reorder --- assesspy/__init__.py | 2 +- assesspy/tests/conftest.py | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/assesspy/__init__.py b/assesspy/__init__.py index 0c8b6ea..8636209 100644 --- a/assesspy/__init__.py +++ b/assesspy/__init__.py @@ -4,7 +4,7 @@ prb_ci, prd_ci, ) -from .load_data import ccao_sample, quintos_sample, IAAO_sample +from .load_data import ccao_sample, IAAO_sample, quintos_sample from .metrics import ( cod, cod_met, diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index f3c359b..e47a69c 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -16,15 +16,14 @@ def ccao_data() -> tuple: sample = ap.ccao_sample() return sample.estimate, sample.sale_price - @pt.fixture(scope="session") -def quintos_data() -> tuple: - sample = ap.quintos_sample() +def IAAO_sample() -> tuple: + sample = ap.IAAO_sample() return sample.estimate, sample.sale_price @pt.fixture(scope="session") -def IAAO_sample() -> tuple: - sample = ap.IAAO_sample() +def quintos_data() -> tuple: + sample = ap.quintos_sample() return sample.estimate, sample.sale_price @pt.fixture( From 54e0afe3e3f08ffdc000f09ac129ac982d0a189d Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 20:53:18 +0000 Subject: [PATCH 06/29] RUFF --- assesspy/__init__.py | 2 +- assesspy/load_data.py | 35 +++++++++++++++++------------------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/assesspy/__init__.py b/assesspy/__init__.py index 8636209..e66db49 100644 --- a/assesspy/__init__.py +++ b/assesspy/__init__.py @@ -4,7 +4,7 @@ prb_ci, prd_ci, ) -from .load_data import ccao_sample, IAAO_sample, quintos_sample +from .load_data import IAAO_sample, ccao_sample, quintos_sample from .metrics import ( cod, cod_met, diff --git a/assesspy/load_data.py b/assesspy/load_data.py index bbddd3b..363ad98 100644 --- a/assesspy/load_data.py +++ b/assesspy/load_data.py @@ -26,19 +26,14 @@ def ccao_sample() -> pd.DataFrame: return pd.read_parquet(file) -def quintos_sample() -> pd.DataFrame: +def IAAO_sample() -> pd.DataFrame: """ - Sample of sales and estimated market values provided by Quintos in the - following MKI papers: - - .. Quintos, C. (2020). A Gini measure for vertical equity in property - assessments. https://researchexchange.iaao.org/jptaa/vol17/iss2/2 + Sample of sales and estimated market values provided by the IAAO in the following report: - .. Quintos, C. (2021). A Gini decomposition of the sources of inequality in - property assessments. https://researchexchange.iaao.org/jptaa/vol18/iss2/6 + .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf :return: - A Pandas DataFrame with 30 observation and 2 variables: + A Pandas DataFrame with 18 observation and 2 variables: ======================== ===================================================== **estimate** (`float`) Assessed fair market value @@ -47,19 +42,23 @@ def quintos_sample() -> pd.DataFrame: :rtype: pd.DataFrame """ - source = files("assesspy").joinpath("data/quintos_sample.csv") + source = files("assesspy").joinpath("data/IAAO_sample.csv") with as_file(source) as file: return pd.read_csv(file) - - -def IAAO_sample() -> pd.DataFrame: + +def quintos_sample() -> pd.DataFrame: """ - Sample of sales and estimated market values provided by the IAAO in the following report: + Sample of sales and estimated market values provided by Quintos in the + following MKI papers: - .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf + .. Quintos, C. (2020). A Gini measure for vertical equity in property + assessments. https://researchexchange.iaao.org/jptaa/vol17/iss2/2 + + .. Quintos, C. (2021). A Gini decomposition of the sources of inequality in + property assessments. https://researchexchange.iaao.org/jptaa/vol18/iss2/6 :return: - A Pandas DataFrame with 18 observation and 2 variables: + A Pandas DataFrame with 30 observation and 2 variables: ======================== ===================================================== **estimate** (`float`) Assessed fair market value @@ -68,6 +67,6 @@ def IAAO_sample() -> pd.DataFrame: :rtype: pd.DataFrame """ - source = files("assesspy").joinpath("data/IAAO_sample.csv") + source = files("assesspy").joinpath("data/quintos_sample.csv") with as_file(source) as file: - return pd.read_csv(file) \ No newline at end of file + return pd.read_csv(file) From 3bbcea08ecdd6e5013dfcc4b177000090a70f34f Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 20:54:42 +0000 Subject: [PATCH 07/29] RUFF --- assesspy/load_data.py | 3 ++- assesspy/tests/conftest.py | 3 +++ assesspy/tests/test_metrics.py | 9 +++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/assesspy/load_data.py b/assesspy/load_data.py index 363ad98..c91235d 100644 --- a/assesspy/load_data.py +++ b/assesspy/load_data.py @@ -45,7 +45,8 @@ def IAAO_sample() -> pd.DataFrame: source = files("assesspy").joinpath("data/IAAO_sample.csv") with as_file(source) as file: return pd.read_csv(file) - + + def quintos_sample() -> pd.DataFrame: """ Sample of sales and estimated market values provided by Quintos in the diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index e47a69c..7fc0cd1 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -16,16 +16,19 @@ def ccao_data() -> tuple: sample = ap.ccao_sample() return sample.estimate, sample.sale_price + @pt.fixture(scope="session") def IAAO_sample() -> tuple: sample = ap.IAAO_sample() return sample.estimate, sample.sale_price + @pt.fixture(scope="session") def quintos_data() -> tuple: sample = ap.quintos_sample() return sample.estimate, sample.sale_price + @pt.fixture( scope="session", params=[ diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 5cf2e38..0140581 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -47,21 +47,22 @@ def test_metric_met_function_thresholds(self, metric, metric_val): } assert getattr(ap, f"{metric}_met")(metric_val) == expected[metric] + def test_iaao_metrics(IAAO_sample): """ Test that COD, PRB, and PRD for the IAAO_sample return expected values. """ estimates, sale_prices = IAAO_sample - + # Calculate COD cod = ap.cod(estimates, sale_prices) - + # Calculate PRB prb = ap.prb(estimates, sale_prices) - + # Calculate PRD prd = ap.prd(estimates, sale_prices) - + # Assert the COD, PRB, and PRD are as expected assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" assert prb == -0.035, f"Expected PRB to be -0.035, but got {prb}" From 032f4d2ba5165a34e21dcd44ea92bb89a131b1e8 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 20:57:43 +0000 Subject: [PATCH 08/29] Remove spaces --- assesspy/data/IAAO_sample.csv | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/assesspy/data/IAAO_sample.csv b/assesspy/data/IAAO_sample.csv index 9b1c85a..9380fd7 100644 --- a/assesspy/data/IAAO_sample.csv +++ b/assesspy/data/IAAO_sample.csv @@ -1,18 +1,18 @@ -estimate, sale_price -87200, 138720 -38240, 59700 -96320, 146400 -68610, 99000 -32960, 47400 -50560, 70500 -61360, 78000 -47360, 60000 -56580, 69000 -47040, 55500 -136000, 154500 -98000, 109500 -56000, 60000 -159100, 168000 -128000, 124500 -132000, 127500 -160000, 150000 \ No newline at end of file +estimate,sale_price +87200,138720 +38240,59700 +96320,146400 +68610,99000 +32960,47400 +50560,70500 +61360,78000 +47360,60000 +56580,69000 +47040,55500 +136000,154500 +98000,109500 +56000,60000 +159100,168000 +128000,124500 +132000,127500 +160000,150000 \ No newline at end of file From dbd62276fee1f28d40f1d69ec0b1dc504d461143 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:00:22 +0000 Subject: [PATCH 09/29] Round values --- assesspy/tests/test_metrics.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 0140581..51dae8a 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -47,7 +47,6 @@ def test_metric_met_function_thresholds(self, metric, metric_val): } assert getattr(ap, f"{metric}_met")(metric_val) == expected[metric] - def test_iaao_metrics(IAAO_sample): """ Test that COD, PRB, and PRD for the IAAO_sample return expected values. @@ -55,15 +54,14 @@ def test_iaao_metrics(IAAO_sample): estimates, sale_prices = IAAO_sample # Calculate COD - cod = ap.cod(estimates, sale_prices) + cod = round(ap.cod(estimates, sale_prices), 1) # Calculate PRB - prb = ap.prb(estimates, sale_prices) + prb = round(ap.prb(estimates, sale_prices), 3) # Calculate PRD - prd = ap.prd(estimates, sale_prices) + prd = round(ap.prd(estimates, sale_prices), 2) - # Assert the COD, PRB, and PRD are as expected assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" assert prb == -0.035, f"Expected PRB to be -0.035, but got {prb}" - assert prd == 0.98, f"Expected PRD to be .98, but got {prd}" + assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" From f2a6773ab99b911624e8388f9120715fcb26fd12 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:01:02 +0000 Subject: [PATCH 10/29] Add enter --- assesspy/tests/test_metrics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 51dae8a..ec55432 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -47,6 +47,7 @@ def test_metric_met_function_thresholds(self, metric, metric_val): } assert getattr(ap, f"{metric}_met")(metric_val) == expected[metric] + def test_iaao_metrics(IAAO_sample): """ Test that COD, PRB, and PRD for the IAAO_sample return expected values. From f79028abd30c74802c2d2bfb7784bddc1f444f88 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:01:22 +0000 Subject: [PATCH 11/29] Add enter --- .Rhistory | 0 .Rproj.user/B73446F7/pcs/files-pane.pper | 9 +++++++++ .Rproj.user/B73446F7/pcs/source-pane.pper | 3 +++ .Rproj.user/B73446F7/pcs/windowlayoutstate.pper | 14 ++++++++++++++ .Rproj.user/B73446F7/pcs/workbench-pane.pper | 5 +++++ .Rproj.user/B73446F7/persistent-state | 3 +++ .Rproj.user/B73446F7/saved_source_markers | 1 + 7 files changed, 35 insertions(+) create mode 100644 .Rhistory create mode 100644 .Rproj.user/B73446F7/pcs/files-pane.pper create mode 100644 .Rproj.user/B73446F7/pcs/source-pane.pper create mode 100644 .Rproj.user/B73446F7/pcs/windowlayoutstate.pper create mode 100644 .Rproj.user/B73446F7/pcs/workbench-pane.pper create mode 100644 .Rproj.user/B73446F7/persistent-state create mode 100644 .Rproj.user/B73446F7/saved_source_markers diff --git a/.Rhistory b/.Rhistory new file mode 100644 index 0000000..e69de29 diff --git a/.Rproj.user/B73446F7/pcs/files-pane.pper b/.Rproj.user/B73446F7/pcs/files-pane.pper new file mode 100644 index 0000000..fba389d --- /dev/null +++ b/.Rproj.user/B73446F7/pcs/files-pane.pper @@ -0,0 +1,9 @@ +{ + "sortOrder": [ + { + "columnIndex": 2, + "ascending": true + } + ], + "path": "~/assesspy" +} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/pcs/source-pane.pper b/.Rproj.user/B73446F7/pcs/source-pane.pper new file mode 100644 index 0000000..a528f3b --- /dev/null +++ b/.Rproj.user/B73446F7/pcs/source-pane.pper @@ -0,0 +1,3 @@ +{ + "activeTab": -1 +} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/pcs/windowlayoutstate.pper b/.Rproj.user/B73446F7/pcs/windowlayoutstate.pper new file mode 100644 index 0000000..cc25474 --- /dev/null +++ b/.Rproj.user/B73446F7/pcs/windowlayoutstate.pper @@ -0,0 +1,14 @@ +{ + "left": { + "splitterpos": 324, + "topwindowstate": "HIDE", + "panelheight": 737, + "windowheight": 811 + }, + "right": { + "splitterpos": 486, + "topwindowstate": "NORMAL", + "panelheight": 737, + "windowheight": 811 + } +} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/pcs/workbench-pane.pper b/.Rproj.user/B73446F7/pcs/workbench-pane.pper new file mode 100644 index 0000000..ab5e950 --- /dev/null +++ b/.Rproj.user/B73446F7/pcs/workbench-pane.pper @@ -0,0 +1,5 @@ +{ + "TabSet1": 3, + "TabSet2": 0, + "TabZoom": {} +} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/persistent-state b/.Rproj.user/B73446F7/persistent-state new file mode 100644 index 0000000..c8f5cc7 --- /dev/null +++ b/.Rproj.user/B73446F7/persistent-state @@ -0,0 +1,3 @@ +activeClientUrl="https://datascience.cookcountyassessor.com/rstudio/" +displayName="damajor" +portToken="638499e71068" diff --git a/.Rproj.user/B73446F7/saved_source_markers b/.Rproj.user/B73446F7/saved_source_markers new file mode 100644 index 0000000..2b1bef1 --- /dev/null +++ b/.Rproj.user/B73446F7/saved_source_markers @@ -0,0 +1 @@ +{"active_set":"","sets":[]} \ No newline at end of file From 50feece230ad157368e00ed9f429e43900b63da2 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:02:49 +0000 Subject: [PATCH 12/29] Delete RProj --- .Rproj.user/B73446F7/pcs/files-pane.pper | 9 --------- .Rproj.user/B73446F7/pcs/source-pane.pper | 3 --- .Rproj.user/B73446F7/pcs/windowlayoutstate.pper | 14 -------------- .Rproj.user/B73446F7/pcs/workbench-pane.pper | 5 ----- .Rproj.user/B73446F7/persistent-state | 3 --- .Rproj.user/B73446F7/saved_source_markers | 1 - 6 files changed, 35 deletions(-) delete mode 100644 .Rproj.user/B73446F7/pcs/files-pane.pper delete mode 100644 .Rproj.user/B73446F7/pcs/source-pane.pper delete mode 100644 .Rproj.user/B73446F7/pcs/windowlayoutstate.pper delete mode 100644 .Rproj.user/B73446F7/pcs/workbench-pane.pper delete mode 100644 .Rproj.user/B73446F7/persistent-state delete mode 100644 .Rproj.user/B73446F7/saved_source_markers diff --git a/.Rproj.user/B73446F7/pcs/files-pane.pper b/.Rproj.user/B73446F7/pcs/files-pane.pper deleted file mode 100644 index fba389d..0000000 --- a/.Rproj.user/B73446F7/pcs/files-pane.pper +++ /dev/null @@ -1,9 +0,0 @@ -{ - "sortOrder": [ - { - "columnIndex": 2, - "ascending": true - } - ], - "path": "~/assesspy" -} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/pcs/source-pane.pper b/.Rproj.user/B73446F7/pcs/source-pane.pper deleted file mode 100644 index a528f3b..0000000 --- a/.Rproj.user/B73446F7/pcs/source-pane.pper +++ /dev/null @@ -1,3 +0,0 @@ -{ - "activeTab": -1 -} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/pcs/windowlayoutstate.pper b/.Rproj.user/B73446F7/pcs/windowlayoutstate.pper deleted file mode 100644 index cc25474..0000000 --- a/.Rproj.user/B73446F7/pcs/windowlayoutstate.pper +++ /dev/null @@ -1,14 +0,0 @@ -{ - "left": { - "splitterpos": 324, - "topwindowstate": "HIDE", - "panelheight": 737, - "windowheight": 811 - }, - "right": { - "splitterpos": 486, - "topwindowstate": "NORMAL", - "panelheight": 737, - "windowheight": 811 - } -} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/pcs/workbench-pane.pper b/.Rproj.user/B73446F7/pcs/workbench-pane.pper deleted file mode 100644 index ab5e950..0000000 --- a/.Rproj.user/B73446F7/pcs/workbench-pane.pper +++ /dev/null @@ -1,5 +0,0 @@ -{ - "TabSet1": 3, - "TabSet2": 0, - "TabZoom": {} -} \ No newline at end of file diff --git a/.Rproj.user/B73446F7/persistent-state b/.Rproj.user/B73446F7/persistent-state deleted file mode 100644 index c8f5cc7..0000000 --- a/.Rproj.user/B73446F7/persistent-state +++ /dev/null @@ -1,3 +0,0 @@ -activeClientUrl="https://datascience.cookcountyassessor.com/rstudio/" -displayName="damajor" -portToken="638499e71068" diff --git a/.Rproj.user/B73446F7/saved_source_markers b/.Rproj.user/B73446F7/saved_source_markers deleted file mode 100644 index 2b1bef1..0000000 --- a/.Rproj.user/B73446F7/saved_source_markers +++ /dev/null @@ -1 +0,0 @@ -{"active_set":"","sets":[]} \ No newline at end of file From d8520e01050b7977a632cc4e6f03321a0a246938 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:05:27 +0000 Subject: [PATCH 13/29] Remove prb --- assesspy/tests/test_metrics.py | 1 - 1 file changed, 1 deletion(-) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index ec55432..2866f2d 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -64,5 +64,4 @@ def test_iaao_metrics(IAAO_sample): prd = round(ap.prd(estimates, sale_prices), 2) assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" - assert prb == -0.035, f"Expected PRB to be -0.035, but got {prb}" assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" From 0ac221cb4e732d5e223a5edbfd49ed3638566c1a Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:07:01 +0000 Subject: [PATCH 14/29] Include wrong value --- assesspy/tests/test_metrics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 2866f2d..07ca10a 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -64,4 +64,5 @@ def test_iaao_metrics(IAAO_sample): prd = round(ap.prd(estimates, sale_prices), 2) assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" + assert prb == .001, f"Expected PRB to be .001, but got {prb}" assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" From fcb7ac2cad9a060208283a07f80d9394a9b34db2 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:12:40 +0000 Subject: [PATCH 15/29] Add leading 0 --- assesspy/tests/test_metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 07ca10a..f3a51e6 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -64,5 +64,5 @@ def test_iaao_metrics(IAAO_sample): prd = round(ap.prd(estimates, sale_prices), 2) assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" - assert prb == .001, f"Expected PRB to be .001, but got {prb}" + assert prb == 0.001, f"Expected PRB to be .001, but got {prb}" assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" From a770f9ce902081a6c424954a210a5fe6c297e2bb Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:37:57 +0000 Subject: [PATCH 16/29] Add MKI --- assesspy/tests/test_metrics.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index f3a51e6..b408794 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -66,3 +66,16 @@ def test_iaao_metrics(IAAO_sample): assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" assert prb == 0.001, f"Expected PRB to be .001, but got {prb}" assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" + +def test_mki(quintos_data): + """ + Test that MKI for the quintos_sample returns the expected value. + """ + estimates, sale_prices = quintos_data + + # Calculate MKI + mki = round(ap.mki(estimates, sale_prices), 2) + ki = round(ap.ki(estimates, sale_prices), 2) + + assert mki == 0.79, f"Expected MKI to be 0.79, but got {mki}" + assert ki == -0.06, f"Expected KI to be -0.06, but got {ki}" From f6aa6de559cadc801a5fc3b472ba0ec32c347411 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 21:41:11 +0000 Subject: [PATCH 17/29] RUFF --- assesspy/tests/test_metrics.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index b408794..c1e3650 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -67,6 +67,7 @@ def test_iaao_metrics(IAAO_sample): assert prb == 0.001, f"Expected PRB to be .001, but got {prb}" assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" + def test_mki(quintos_data): """ Test that MKI for the quintos_sample returns the expected value. @@ -77,5 +78,5 @@ def test_mki(quintos_data): mki = round(ap.mki(estimates, sale_prices), 2) ki = round(ap.ki(estimates, sale_prices), 2) - assert mki == 0.79, f"Expected MKI to be 0.79, but got {mki}" + assert mki == 0.79, f"Expected MKI to be 0.79, but got {mki}" assert ki == -0.06, f"Expected KI to be -0.06, but got {ki}" From c6cf1db968c7fa8db6fe4d826c0ea0df706e8783 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 22:19:41 +0000 Subject: [PATCH 18/29] Move to better location --- assesspy/tests/test_metrics.py | 67 ++++++++++++++++------------------ 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index c1e3650..8591de8 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -2,7 +2,6 @@ import assesspy as ap - class TestMetrics: @pt.fixture(params=["cod", "prd", "prb", "mki", "ki"]) def metric(self, request): @@ -14,6 +13,38 @@ def metric_val(self, metric, ccao_data, quintos_data): return getattr(ap, metric)(*quintos_data) return getattr(ap, metric)(*ccao_data) + def test_iaao_metrics(self, IAAO_sample): + """ + Test that COD, PRB, and PRD for the IAAO_sample return expected values. + """ + estimates, sale_prices = IAAO_sample + + # Calculate COD + cod = round(ap.cod(estimates, sale_prices), 1) + + # Calculate PRB + prb = round(ap.prb(estimates, sale_prices), 3) + + # Calculate PRD + prd = round(ap.prd(estimates, sale_prices), 2) + + assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" + assert prb == 0.001, f"Expected PRB to be .001, but got {prb}" + assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" + + def test_mki(self, quintos_data): + """ + Test that MKI for the quintos_sample returns the expected value. + """ + estimates, sale_prices = quintos_data + + # Calculate MKI + mki = round(ap.mki(estimates, sale_prices), 2) + ki = round(ap.ki(estimates, sale_prices), 2) + + assert mki == 0.79, f"Expected MKI to be 0.79, but got {mki}" + assert ki == -0.06, f"Expected KI to be -0.06, but got {ki}" + def test_metric_value_is_correct(self, metric, metric_val): expected = { "cod": 17.81456901196891, @@ -46,37 +77,3 @@ def test_metric_met_function_thresholds(self, metric, metric_val): "mki": False, } assert getattr(ap, f"{metric}_met")(metric_val) == expected[metric] - - -def test_iaao_metrics(IAAO_sample): - """ - Test that COD, PRB, and PRD for the IAAO_sample return expected values. - """ - estimates, sale_prices = IAAO_sample - - # Calculate COD - cod = round(ap.cod(estimates, sale_prices), 1) - - # Calculate PRB - prb = round(ap.prb(estimates, sale_prices), 3) - - # Calculate PRD - prd = round(ap.prd(estimates, sale_prices), 2) - - assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" - assert prb == 0.001, f"Expected PRB to be .001, but got {prb}" - assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" - - -def test_mki(quintos_data): - """ - Test that MKI for the quintos_sample returns the expected value. - """ - estimates, sale_prices = quintos_data - - # Calculate MKI - mki = round(ap.mki(estimates, sale_prices), 2) - ki = round(ap.ki(estimates, sale_prices), 2) - - assert mki == 0.79, f"Expected MKI to be 0.79, but got {mki}" - assert ki == -0.06, f"Expected KI to be -0.06, but got {ki}" From 563bcf1138bd1b6ae610ca952fc4c3b47ef62b3e Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Tue, 26 Nov 2024 22:51:30 +0000 Subject: [PATCH 19/29] RUFF --- assesspy/tests/test_metrics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 8591de8..f2e07f8 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -2,6 +2,7 @@ import assesspy as ap + class TestMetrics: @pt.fixture(params=["cod", "prd", "prb", "mki", "ki"]) def metric(self, request): From c189bb45c4d27d17d4ee87e156ced3d73cfd060b Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Wed, 27 Nov 2024 15:16:46 +0000 Subject: [PATCH 20/29] Add table D1 --- assesspy/__init__.py | 2 +- assesspy/data/IAAO_sample.csv | 18 -------- assesspy/data/IAAO_sample_1_4.csv | 26 +++++++++++ assesspy/data/IAAO_sample_d_1.csv | 25 +++++++++++ assesspy/load_data.py | 27 ++++++++++-- assesspy/tests/conftest.py | 9 +++- assesspy/tests/test_metrics.py | 43 +++++++++++++------ docs/source/IAAO_sample_1_4.rst | 5 +++ .../{IAAO_sample.rst => IAAO_sample_d_1.rst} | 2 +- 9 files changed, 118 insertions(+), 39 deletions(-) delete mode 100644 assesspy/data/IAAO_sample.csv create mode 100644 assesspy/data/IAAO_sample_1_4.csv create mode 100644 assesspy/data/IAAO_sample_d_1.csv create mode 100644 docs/source/IAAO_sample_1_4.rst rename docs/source/{IAAO_sample.rst => IAAO_sample_d_1.rst} (70%) diff --git a/assesspy/__init__.py b/assesspy/__init__.py index e66db49..93637de 100644 --- a/assesspy/__init__.py +++ b/assesspy/__init__.py @@ -4,7 +4,7 @@ prb_ci, prd_ci, ) -from .load_data import IAAO_sample, ccao_sample, quintos_sample +from .load_data import IAAO_sample_1_4, IAAO_sample_d_1, ccao_sample, quintos_sample from .metrics import ( cod, cod_met, diff --git a/assesspy/data/IAAO_sample.csv b/assesspy/data/IAAO_sample.csv deleted file mode 100644 index 9380fd7..0000000 --- a/assesspy/data/IAAO_sample.csv +++ /dev/null @@ -1,18 +0,0 @@ -estimate,sale_price -87200,138720 -38240,59700 -96320,146400 -68610,99000 -32960,47400 -50560,70500 -61360,78000 -47360,60000 -56580,69000 -47040,55500 -136000,154500 -98000,109500 -56000,60000 -159100,168000 -128000,124500 -132000,127500 -160000,150000 \ No newline at end of file diff --git a/assesspy/data/IAAO_sample_1_4.csv b/assesspy/data/IAAO_sample_1_4.csv new file mode 100644 index 0000000..2d501ca --- /dev/null +++ b/assesspy/data/IAAO_sample_1_4.csv @@ -0,0 +1,26 @@ +estimate,sale_price +116700,114500 +130300,121000 +130200,133900 +145500,139000 +134100,145000 +153900,156500 +143400,161100 +156900,169500 +169000,175000 +149200,181000 +160100,188900 +191400,205000 +177200,216150 +205500,219000 +206500,235000 +243800,249000 +211600,258900 +242500,263000 +258400,305900 +265900,312500 +305700,336000 +291600,360000 +312800,399900 +352200,418500 +354900,459000 diff --git a/assesspy/data/IAAO_sample_d_1.csv b/assesspy/data/IAAO_sample_d_1.csv new file mode 100644 index 0000000..c2fecdc --- /dev/null +++ b/assesspy/data/IAAO_sample_d_1.csv @@ -0,0 +1,25 @@ +estimate,sale_price +130300,121000 +130200,133900 +145500,739000 +134100,145000 +153900,156500 +183400,161100 +156900,169500 +169000,175000 +149200,181000 +160100,188900 +191400,205000 +177200,216150 +205500,719000 +206500,235000 +243800,249000 +211600,258900 +242500,263000 +258400,305900 +265900,312500 +305700,336000 +291600,360000 +312800,399900 +352200,418500 +354900,459000 diff --git a/assesspy/load_data.py b/assesspy/load_data.py index c91235d..2a61194 100644 --- a/assesspy/load_data.py +++ b/assesspy/load_data.py @@ -26,9 +26,9 @@ def ccao_sample() -> pd.DataFrame: return pd.read_parquet(file) -def IAAO_sample() -> pd.DataFrame: +def IAAO_sample_1_4() -> pd.DataFrame: """ - Sample of sales and estimated market values provided by the IAAO in the following report: + Sample of sales and estimated market values provided in table 1.4 by the IAAO in the following report: .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf @@ -42,11 +42,32 @@ def IAAO_sample() -> pd.DataFrame: :rtype: pd.DataFrame """ - source = files("assesspy").joinpath("data/IAAO_sample.csv") + source = files("assesspy").joinpath("data/IAAO_sample_1_4.csv") with as_file(source) as file: return pd.read_csv(file) +def IAAO_sample_d_1() -> pd.DataFrame: + """ + Sample of sales and estimated market values provided in table D.1 by the IAAO in the following report: + + .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf + + :return: + A Pandas DataFrame with 25 observation and 2 variables: + + ======================== ===================================================== + **estimate** (`float`) Assessed fair market value + **sale_price** (`float`) Recorded sale price of this property + ======================== ===================================================== + + :rtype: pd.DataFrame + """ + source = files("assesspy").joinpath("data/IAAO_sample_d_1.csv") + with as_file(source) as file: + return pd.read_csv(file) + + def quintos_sample() -> pd.DataFrame: """ Sample of sales and estimated market values provided by Quintos in the diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index 7fc0cd1..4d12193 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -18,8 +18,13 @@ def ccao_data() -> tuple: @pt.fixture(scope="session") -def IAAO_sample() -> tuple: - sample = ap.IAAO_sample() +def IAAO_sample_1_4() -> tuple: + sample = ap.IAAO_sample_1_4() + return sample.estimate, sample.sale_price + +@pt.fixture(scope="session") +def IAAO_sample_d_1() -> tuple: + sample = ap.IAAO_sample_d_1() return sample.estimate, sample.sale_price diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index f2e07f8..a0e668e 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -14,24 +14,39 @@ def metric_val(self, metric, ccao_data, quintos_data): return getattr(ap, metric)(*quintos_data) return getattr(ap, metric)(*ccao_data) - def test_iaao_metrics(self, IAAO_sample): - """ - Test that COD, PRB, and PRD for the IAAO_sample return expected values. - """ - estimates, sale_prices = IAAO_sample - - # Calculate COD +def test_iaao_metrics(self, IAAO_samples): + """ + Test that COD, PRB, and PRD for the IAAO samples return expected values. + """ + # List of datasets and expected values + datasets = [ + { + "name": "1_4", + "data": IAAO_samples["IAAO_sample_1_4"], + "expected": {"cod": 7.5, "prb": 0.135, "prd": 1.03}, + }, + { + "name": "d_1", + "data": IAAO_samples["IAAO_sample_d_1"], + "expected": {"cod": 7.5, "prb": -0.120, "prd": 1.03}, + }, + ] + + # Iterate through datasets and perform tests + for dataset in datasets: + estimates, sale_prices = dataset["data"] + expected = dataset["expected"] + + # Calculate metrics cod = round(ap.cod(estimates, sale_prices), 1) - - # Calculate PRB prb = round(ap.prb(estimates, sale_prices), 3) - - # Calculate PRD prd = round(ap.prd(estimates, sale_prices), 2) - assert cod == 14.5, f"Expected COD to be 14.5, but got {cod}" - assert prb == 0.001, f"Expected PRB to be .001, but got {prb}" - assert prd == 0.98, f"Expected PRD to be 0.98, but got {prd}" + # Assertions + assert cod == expected["cod"], f"Expected COD for {dataset['name']} to be {expected['cod']}, but got {cod}" + assert prb == expected["prb"], f"Expected PRB for {dataset['name']} to be {expected['prb']}, but got {prb}" + assert prd == expected["prd"], f"Expected PRD for {dataset['name']} to be {expected['prd']}, but got {prd}" + def test_mki(self, quintos_data): """ diff --git a/docs/source/IAAO_sample_1_4.rst b/docs/source/IAAO_sample_1_4.rst new file mode 100644 index 0000000..1cb6d2d --- /dev/null +++ b/docs/source/IAAO_sample_1_4.rst @@ -0,0 +1,5 @@ +================================ +Sample data from IAAO ratio study table 1.4 +================================ + +.. autofunction:: assesspy.IAAO_sample_1_4 diff --git a/docs/source/IAAO_sample.rst b/docs/source/IAAO_sample_d_1.rst similarity index 70% rename from docs/source/IAAO_sample.rst rename to docs/source/IAAO_sample_d_1.rst index 75439bb..9adec4f 100644 --- a/docs/source/IAAO_sample.rst +++ b/docs/source/IAAO_sample_d_1.rst @@ -1,5 +1,5 @@ ================================ -Sample data from IAAO ratio study +Sample data from IAAO ratio study table D.1 ================================ .. autofunction:: assesspy.IAAO_sample From 72a0898a5877b987c169668670af5f5c3efdaf44 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Wed, 27 Nov 2024 15:41:02 +0000 Subject: [PATCH 21/29] Add D2 --- assesspy/data/IAAO_sample_d_2.csv | 17 +++++++++ assesspy/load_data.py | 20 ++++++++++ assesspy/tests/conftest.py | 4 ++ assesspy/tests/test_metrics.py | 61 +++++++++++++++++-------------- docs/source/IAAO_sample_d_2.rst | 5 +++ docs/source/reference.rst | 4 +- 6 files changed, 82 insertions(+), 29 deletions(-) create mode 100644 assesspy/data/IAAO_sample_d_2.csv create mode 100644 docs/source/IAAO_sample_d_2.rst diff --git a/assesspy/data/IAAO_sample_d_2.csv b/assesspy/data/IAAO_sample_d_2.csv new file mode 100644 index 0000000..44ceb5d --- /dev/null +++ b/assesspy/data/IAAO_sample_d_2.csv @@ -0,0 +1,17 @@ +estimate,sale_price +50000,45000 +100000,100000 +150000,165000 +200000,180000 +250000,250000 +300000,330000 +350000,315000 +400000,400000 +450000,495000 +500000,450000 +550000,550000 +600000,660000 +650000,585000 +700000,700000 +750000,825000 +2500000,1875000 diff --git a/assesspy/load_data.py b/assesspy/load_data.py index 2a61194..029ce32 100644 --- a/assesspy/load_data.py +++ b/assesspy/load_data.py @@ -67,6 +67,26 @@ def IAAO_sample_d_1() -> pd.DataFrame: with as_file(source) as file: return pd.read_csv(file) +def IAAO_sample_d_2() -> pd.DataFrame: + """ + Sample of sales and estimated market values provided in table D.2 by the IAAO in the following report: + + .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf + + :return: + A Pandas DataFrame with 16 observation and 2 variables: + + ======================== ===================================================== + **estimate** (`float`) Assessed fair market value + **sale_price** (`float`) Recorded sale price of this property + ======================== ===================================================== + + :rtype: pd.DataFrame + """ + source = files("assesspy").joinpath("data/IAAO_sample_d_1.csv") + with as_file(source) as file: + return pd.read_csv(file) + def quintos_sample() -> pd.DataFrame: """ diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index 4d12193..5a9b9fb 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -27,6 +27,10 @@ def IAAO_sample_d_1() -> tuple: sample = ap.IAAO_sample_d_1() return sample.estimate, sample.sale_price +@pt.fixture(scope="session") +def IAAO_sample_d_2() -> tuple: + sample = ap.IAAO_sample_d_2() + return sample.estimate, sample.sale_price @pt.fixture(scope="session") def quintos_data() -> tuple: diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index a0e668e..7b1458f 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -14,38 +14,43 @@ def metric_val(self, metric, ccao_data, quintos_data): return getattr(ap, metric)(*quintos_data) return getattr(ap, metric)(*ccao_data) -def test_iaao_metrics(self, IAAO_samples): - """ - Test that COD, PRB, and PRD for the IAAO samples return expected values. - """ - # List of datasets and expected values - datasets = [ - { - "name": "1_4", - "data": IAAO_samples["IAAO_sample_1_4"], - "expected": {"cod": 7.5, "prb": 0.135, "prd": 1.03}, - }, - { - "name": "d_1", - "data": IAAO_samples["IAAO_sample_d_1"], - "expected": {"cod": 7.5, "prb": -0.120, "prd": 1.03}, - }, - ] - - # Iterate through datasets and perform tests - for dataset in datasets: - estimates, sale_prices = dataset["data"] - expected = dataset["expected"] - - # Calculate metrics + def test_iaao_metrics_1_4(self, IAAO_sample_1_4): + """ + Test that COD, PRB, and PRD for the IAAO_sample return expected values. + """ + estimates, sale_prices = IAAO_sample_1_4 + + # Calculate COD cod = round(ap.cod(estimates, sale_prices), 1) + + # Calculate PRB prb = round(ap.prb(estimates, sale_prices), 3) + + # Calculate PRD + prd = round(ap.prd(estimates, sale_prices), 2) + + assert cod == 7.5, f"Expected COD to be 7.5, but got {cod}" + assert prb == 0.135, f"Expected PRB to be .135, but got {prb}" + assert prd == 1.03, f"Expected PRD to be 0.98, but got {prd}" + + def test_iaao_metrics_d_1(self, IAAO_sample_d_1): + """ + Test that COD, PRB, and PRD for the IAAO_sample return expected values. + """ + estimates, sale_prices = IAAO_sample_d_1 + + # Calculate COD + cod = round(ap.cod(estimates, sale_prices), 1) + + # Calculate PRB + prb = round(ap.prb(estimates, sale_prices), 3) + + # Calculate PRD prd = round(ap.prd(estimates, sale_prices), 2) - # Assertions - assert cod == expected["cod"], f"Expected COD for {dataset['name']} to be {expected['cod']}, but got {cod}" - assert prb == expected["prb"], f"Expected PRB for {dataset['name']} to be {expected['prb']}, but got {prb}" - assert prd == expected["prd"], f"Expected PRD for {dataset['name']} to be {expected['prd']}, but got {prd}" + assert cod == 7.5, f"Expected COD to be .075, but got {cod}" + assert prb == -0.120, f"Expected PRB to be .0.120, but got {prb}" + assert prd == 1.03, f"Expected PRD to be 1.03, but got {prd}" def test_mki(self, quintos_data): diff --git a/docs/source/IAAO_sample_d_2.rst b/docs/source/IAAO_sample_d_2.rst new file mode 100644 index 0000000..c28f327 --- /dev/null +++ b/docs/source/IAAO_sample_d_2.rst @@ -0,0 +1,5 @@ +================================ +Sample data from IAAO ratio study table D.2 +================================ + +.. autofunction:: assesspy.IAAO_sample_d_2 diff --git a/docs/source/reference.rst b/docs/source/reference.rst index 3d6baed..c853d58 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -87,6 +87,8 @@ Data :doc:`ccao_sample() ` :doc:`quintos_sample() ` -:doc:`IAAO_sample() ` +:doc:`IAAO_sample_1_4() ` +:doc:`IAAO_sample_d_1() ` +:doc:`IAAO_sample_d_2() ` .. |nbsp| unicode:: 0xA0 From f933e78192c8bd4849a5cf30244bb14364528592 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Wed, 27 Nov 2024 15:41:56 +0000 Subject: [PATCH 22/29] Add to init --- assesspy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assesspy/__init__.py b/assesspy/__init__.py index 93637de..ff26de9 100644 --- a/assesspy/__init__.py +++ b/assesspy/__init__.py @@ -4,7 +4,7 @@ prb_ci, prd_ci, ) -from .load_data import IAAO_sample_1_4, IAAO_sample_d_1, ccao_sample, quintos_sample +from .load_data import IAAO_sample_1_4, IAAO_sample_d_1, IAAO_sample_d_2, ccao_sample, quintos_sample from .metrics import ( cod, cod_met, From 91f655d9279451e717db3935ef16ac3c3774da42 Mon Sep 17 00:00:00 2001 From: Damonamajor Date: Wed, 27 Nov 2024 15:44:39 +0000 Subject: [PATCH 23/29] RUFF --- assesspy/__init__.py | 8 +++++++- assesspy/load_data.py | 5 +++-- assesspy/tests/conftest.py | 3 +++ assesspy/tests/test_metrics.py | 1 - 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/assesspy/__init__.py b/assesspy/__init__.py index ff26de9..b67f57d 100644 --- a/assesspy/__init__.py +++ b/assesspy/__init__.py @@ -4,7 +4,13 @@ prb_ci, prd_ci, ) -from .load_data import IAAO_sample_1_4, IAAO_sample_d_1, IAAO_sample_d_2, ccao_sample, quintos_sample +from .load_data import ( + IAAO_sample_1_4, + IAAO_sample_d_1, + IAAO_sample_d_2, + ccao_sample, + quintos_sample, +) from .metrics import ( cod, cod_met, diff --git a/assesspy/load_data.py b/assesspy/load_data.py index 029ce32..a4d4841 100644 --- a/assesspy/load_data.py +++ b/assesspy/load_data.py @@ -66,7 +66,8 @@ def IAAO_sample_d_1() -> pd.DataFrame: source = files("assesspy").joinpath("data/IAAO_sample_d_1.csv") with as_file(source) as file: return pd.read_csv(file) - + + def IAAO_sample_d_2() -> pd.DataFrame: """ Sample of sales and estimated market values provided in table D.2 by the IAAO in the following report: @@ -86,7 +87,7 @@ def IAAO_sample_d_2() -> pd.DataFrame: source = files("assesspy").joinpath("data/IAAO_sample_d_1.csv") with as_file(source) as file: return pd.read_csv(file) - + def quintos_sample() -> pd.DataFrame: """ diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index 5a9b9fb..6e9c77e 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -22,16 +22,19 @@ def IAAO_sample_1_4() -> tuple: sample = ap.IAAO_sample_1_4() return sample.estimate, sample.sale_price + @pt.fixture(scope="session") def IAAO_sample_d_1() -> tuple: sample = ap.IAAO_sample_d_1() return sample.estimate, sample.sale_price + @pt.fixture(scope="session") def IAAO_sample_d_2() -> tuple: sample = ap.IAAO_sample_d_2() return sample.estimate, sample.sale_price + @pt.fixture(scope="session") def quintos_data() -> tuple: sample = ap.quintos_sample() diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 7b1458f..03ff14c 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -52,7 +52,6 @@ def test_iaao_metrics_d_1(self, IAAO_sample_d_1): assert prb == -0.120, f"Expected PRB to be .0.120, but got {prb}" assert prd == 1.03, f"Expected PRD to be 1.03, but got {prd}" - def test_mki(self, quintos_data): """ Test that MKI for the quintos_sample returns the expected value. From 9cef6d762cc6378496b5d165da163c4773a78c64 Mon Sep 17 00:00:00 2001 From: Dan Snow Date: Wed, 27 Nov 2024 17:39:30 +0000 Subject: [PATCH 24/29] Remove export of IAAO test data --- assesspy/__init__.py | 3 -- assesspy/load_data.py | 63 --------------------------------- docs/source/IAAO_sample_1_4.rst | 5 --- docs/source/IAAO_sample_d_1.rst | 5 --- docs/source/IAAO_sample_d_2.rst | 5 --- docs/source/reference.rst | 3 -- 6 files changed, 84 deletions(-) delete mode 100644 docs/source/IAAO_sample_1_4.rst delete mode 100644 docs/source/IAAO_sample_d_1.rst delete mode 100644 docs/source/IAAO_sample_d_2.rst diff --git a/assesspy/__init__.py b/assesspy/__init__.py index b67f57d..5907c87 100644 --- a/assesspy/__init__.py +++ b/assesspy/__init__.py @@ -5,9 +5,6 @@ prd_ci, ) from .load_data import ( - IAAO_sample_1_4, - IAAO_sample_d_1, - IAAO_sample_d_2, ccao_sample, quintos_sample, ) diff --git a/assesspy/load_data.py b/assesspy/load_data.py index a4d4841..dcca6c7 100644 --- a/assesspy/load_data.py +++ b/assesspy/load_data.py @@ -26,69 +26,6 @@ def ccao_sample() -> pd.DataFrame: return pd.read_parquet(file) -def IAAO_sample_1_4() -> pd.DataFrame: - """ - Sample of sales and estimated market values provided in table 1.4 by the IAAO in the following report: - - .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf - - :return: - A Pandas DataFrame with 18 observation and 2 variables: - - ======================== ===================================================== - **estimate** (`float`) Assessed fair market value - **sale_price** (`float`) Recorded sale price of this property - ======================== ===================================================== - - :rtype: pd.DataFrame - """ - source = files("assesspy").joinpath("data/IAAO_sample_1_4.csv") - with as_file(source) as file: - return pd.read_csv(file) - - -def IAAO_sample_d_1() -> pd.DataFrame: - """ - Sample of sales and estimated market values provided in table D.1 by the IAAO in the following report: - - .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf - - :return: - A Pandas DataFrame with 25 observation and 2 variables: - - ======================== ===================================================== - **estimate** (`float`) Assessed fair market value - **sale_price** (`float`) Recorded sale price of this property - ======================== ===================================================== - - :rtype: pd.DataFrame - """ - source = files("assesspy").joinpath("data/IAAO_sample_d_1.csv") - with as_file(source) as file: - return pd.read_csv(file) - - -def IAAO_sample_d_2() -> pd.DataFrame: - """ - Sample of sales and estimated market values provided in table D.2 by the IAAO in the following report: - - .. IAAO. (2013). Standard on Ratio Studies. https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf - - :return: - A Pandas DataFrame with 16 observation and 2 variables: - - ======================== ===================================================== - **estimate** (`float`) Assessed fair market value - **sale_price** (`float`) Recorded sale price of this property - ======================== ===================================================== - - :rtype: pd.DataFrame - """ - source = files("assesspy").joinpath("data/IAAO_sample_d_1.csv") - with as_file(source) as file: - return pd.read_csv(file) - - def quintos_sample() -> pd.DataFrame: """ Sample of sales and estimated market values provided by Quintos in the diff --git a/docs/source/IAAO_sample_1_4.rst b/docs/source/IAAO_sample_1_4.rst deleted file mode 100644 index 1cb6d2d..0000000 --- a/docs/source/IAAO_sample_1_4.rst +++ /dev/null @@ -1,5 +0,0 @@ -================================ -Sample data from IAAO ratio study table 1.4 -================================ - -.. autofunction:: assesspy.IAAO_sample_1_4 diff --git a/docs/source/IAAO_sample_d_1.rst b/docs/source/IAAO_sample_d_1.rst deleted file mode 100644 index 9adec4f..0000000 --- a/docs/source/IAAO_sample_d_1.rst +++ /dev/null @@ -1,5 +0,0 @@ -================================ -Sample data from IAAO ratio study table D.1 -================================ - -.. autofunction:: assesspy.IAAO_sample diff --git a/docs/source/IAAO_sample_d_2.rst b/docs/source/IAAO_sample_d_2.rst deleted file mode 100644 index c28f327..0000000 --- a/docs/source/IAAO_sample_d_2.rst +++ /dev/null @@ -1,5 +0,0 @@ -================================ -Sample data from IAAO ratio study table D.2 -================================ - -.. autofunction:: assesspy.IAAO_sample_d_2 diff --git a/docs/source/reference.rst b/docs/source/reference.rst index c853d58..2c69f82 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -87,8 +87,5 @@ Data :doc:`ccao_sample() ` :doc:`quintos_sample() ` -:doc:`IAAO_sample_1_4() ` -:doc:`IAAO_sample_d_1() ` -:doc:`IAAO_sample_d_2() ` .. |nbsp| unicode:: 0xA0 From e96ed28037f53440b2b1dde2e2efd58259d10425 Mon Sep 17 00:00:00 2001 From: Dan Snow Date: Wed, 27 Nov 2024 17:52:59 +0000 Subject: [PATCH 25/29] Move data to test fixtures dir --- assesspy/data/IAAO_sample_1_4.csv | 26 ------------- assesspy/tests/fixtures/iaao_table_1_1.csv | 37 +++++++++++++++++++ assesspy/tests/fixtures/iaao_table_1_4.csv | 18 +++++++++ .../fixtures/iaao_table_d_1.csv} | 0 .../fixtures/iaao_table_d_2.csv} | 0 5 files changed, 55 insertions(+), 26 deletions(-) delete mode 100644 assesspy/data/IAAO_sample_1_4.csv create mode 100644 assesspy/tests/fixtures/iaao_table_1_1.csv create mode 100644 assesspy/tests/fixtures/iaao_table_1_4.csv rename assesspy/{data/IAAO_sample_d_1.csv => tests/fixtures/iaao_table_d_1.csv} (100%) rename assesspy/{data/IAAO_sample_d_2.csv => tests/fixtures/iaao_table_d_2.csv} (100%) diff --git a/assesspy/data/IAAO_sample_1_4.csv b/assesspy/data/IAAO_sample_1_4.csv deleted file mode 100644 index 2d501ca..0000000 --- a/assesspy/data/IAAO_sample_1_4.csv +++ /dev/null @@ -1,26 +0,0 @@ -estimate,sale_price -116700,114500 -130300,121000 -130200,133900 -145500,139000 -134100,145000 -153900,156500 -143400,161100 -156900,169500 -169000,175000 -149200,181000 -160100,188900 -191400,205000 -177200,216150 -205500,219000 -206500,235000 -243800,249000 -211600,258900 -242500,263000 -258400,305900 -265900,312500 -305700,336000 -291600,360000 -312800,399900 -352200,418500 -354900,459000 diff --git a/assesspy/tests/fixtures/iaao_table_1_1.csv b/assesspy/tests/fixtures/iaao_table_1_1.csv new file mode 100644 index 0000000..9df1de4 --- /dev/null +++ b/assesspy/tests/fixtures/iaao_table_1_1.csv @@ -0,0 +1,37 @@ +estimate,sale_price +48000,138000 +28800,59250 +78400,157500 +39840,74400 +68160,114900 +94400,159000 +67200,111900 +56960,93000 +87200,138720 +38240,59700 +96320,146400 +67680,99000 +32960,47400 +50560,70500 +61360,78000 +47360,60000 +58080,69000 +47040,55500 +136000,154500 +103200,109500 +59040,60000 +168000,168000 +128000,124500 +132000,127500 +160000,150000 +160000,141000 +200000,171900 +184000,157500 +160000,129600 +157200,126000 +99200,77700 +200000,153000 +64000,48750 +192000,144000 +190400,141000 +65440,48000 diff --git a/assesspy/tests/fixtures/iaao_table_1_4.csv b/assesspy/tests/fixtures/iaao_table_1_4.csv new file mode 100644 index 0000000..8448635 --- /dev/null +++ b/assesspy/tests/fixtures/iaao_table_1_4.csv @@ -0,0 +1,18 @@ +estimate,sale_price +87200,138720 +38240,59700 +96320,146400 +68610,99000 +32960,47400 +50560,70500 +61360,78000 +47360,60000 +56580,69000 +47040,55500 +136000,154500 +98000,109500 +56000,60000 +159100,168000 +128000,124500 +132000,127500 +160000,150000 diff --git a/assesspy/data/IAAO_sample_d_1.csv b/assesspy/tests/fixtures/iaao_table_d_1.csv similarity index 100% rename from assesspy/data/IAAO_sample_d_1.csv rename to assesspy/tests/fixtures/iaao_table_d_1.csv diff --git a/assesspy/data/IAAO_sample_d_2.csv b/assesspy/tests/fixtures/iaao_table_d_2.csv similarity index 100% rename from assesspy/data/IAAO_sample_d_2.csv rename to assesspy/tests/fixtures/iaao_table_d_2.csv From b252abf5901fb38a53e2115c45ca0bbdcf6a40a4 Mon Sep 17 00:00:00 2001 From: Dan Snow Date: Wed, 27 Nov 2024 18:12:57 +0000 Subject: [PATCH 26/29] Update README SRS link --- README.md | 2 +- docs/source/index.rst | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1c8a038..03bec39 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ AssessPy is a software package for Python developed by the Cook County Assessor’s (CCAO) Data Department. It contains many of the functions necessary to perform a standard -[sales ratio study](https://www.iaao.org/media/standards/Standard_on_Ratio_Studies.pdf). +[sales ratio study](https://www.iaao.org/wp-content/uploads/Standard_on_Ratio_Studies.pdf). For assessors, we believe that this package will reduce the complexity of calculating ratio statistics and detecting sales chasing. We also hope that reporters, taxpayers, diff --git a/docs/source/index.rst b/docs/source/index.rst index e94ccc1..59f0a28 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -22,16 +22,14 @@ AssessPy package Source Code AssessPy is a software package for Python developed by the Cook County -Assessor's (CCAO) Data Department. The codebase for the CCAO's CAMA system -uses a wide range of functions regularly, and packaging these functions -streamlines and standardizes their use. The CCAO is publishing this package -to make it available to assessors, reporters, and citizens everywhere. - -For assessors, we believe that this package will reduce the complexity -of calculating ratio statistics and detecting sales chasing. We also -believe that reporters, taxpayers, and members of academia will find -this package helpful in monitoring the performance of local assessors -and conducting research. +Assessor’s (CCAO) Data Department. It contains many of the functions necessary +to perform a standard +`sales ratio study `_ + +For assessors, we believe that this package will reduce the complexity of +calculating ratio statistics and detecting sales chasing. We also hope that +reporters, taxpayers, and members of academia will find this package helpful +in monitoring the performance of local assessors and conducting research. For detailed documentation on included functions and data, :doc:`visit the full reference list `. From 9bca2367be44e71fdc22f9a6ba4d43e412db5f87 Mon Sep 17 00:00:00 2001 From: Dan Snow Date: Wed, 27 Nov 2024 19:05:29 +0000 Subject: [PATCH 27/29] Fix table data order and values --- assesspy/tests/fixtures/iaao_table_d_1.csv | 7 ++++--- assesspy/tests/fixtures/iaao_table_d_2.csv | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/assesspy/tests/fixtures/iaao_table_d_1.csv b/assesspy/tests/fixtures/iaao_table_d_1.csv index c2fecdc..2d501ca 100644 --- a/assesspy/tests/fixtures/iaao_table_d_1.csv +++ b/assesspy/tests/fixtures/iaao_table_d_1.csv @@ -1,17 +1,18 @@ estimate,sale_price +116700,114500 130300,121000 130200,133900 -145500,739000 +145500,139000 134100,145000 153900,156500 -183400,161100 +143400,161100 156900,169500 169000,175000 149200,181000 160100,188900 191400,205000 177200,216150 -205500,719000 +205500,219000 206500,235000 243800,249000 211600,258900 diff --git a/assesspy/tests/fixtures/iaao_table_d_2.csv b/assesspy/tests/fixtures/iaao_table_d_2.csv index 44ceb5d..5623b7a 100644 --- a/assesspy/tests/fixtures/iaao_table_d_2.csv +++ b/assesspy/tests/fixtures/iaao_table_d_2.csv @@ -1,17 +1,17 @@ estimate,sale_price -50000,45000 +45000,50000 100000,100000 -150000,165000 -200000,180000 +165000,150000 +180000,200000 250000,250000 -300000,330000 -350000,315000 +330000,300000 +315000,350000 400000,400000 -450000,495000 -500000,450000 +495000,450000 +450000,500000 550000,550000 -600000,660000 -650000,585000 +660000,600000 +585000,650000 700000,700000 -750000,825000 -2500000,1875000 +825000,750000 +1875000,2500000 From 7806ac15838435f62fd491189036a8d2be02aee6 Mon Sep 17 00:00:00 2001 From: Dan Snow Date: Wed, 27 Nov 2024 19:06:08 +0000 Subject: [PATCH 28/29] Add tests using IAAO data fixtures --- assesspy/tests/conftest.py | 28 ++++------- assesspy/tests/test_metrics.py | 87 +++++++++++++--------------------- 2 files changed, 43 insertions(+), 72 deletions(-) diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index 6e9c77e..9505996 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -1,9 +1,13 @@ +import pathlib + import numpy as np import pandas as pd import pytest as pt import assesspy as ap +FIXTURE_DIR = pathlib.Path(__file__).parent / "fixtures" + @pt.fixture(autouse=True, scope="function") def set_seed() -> None: @@ -17,30 +21,18 @@ def ccao_data() -> tuple: return sample.estimate, sample.sale_price -@pt.fixture(scope="session") -def IAAO_sample_1_4() -> tuple: - sample = ap.IAAO_sample_1_4() - return sample.estimate, sample.sale_price - - -@pt.fixture(scope="session") -def IAAO_sample_d_1() -> tuple: - sample = ap.IAAO_sample_d_1() - return sample.estimate, sample.sale_price - - -@pt.fixture(scope="session") -def IAAO_sample_d_2() -> tuple: - sample = ap.IAAO_sample_d_2() - return sample.estimate, sample.sale_price - - @pt.fixture(scope="session") def quintos_data() -> tuple: sample = ap.quintos_sample() return sample.estimate, sample.sale_price +@pt.fixture(scope="module", params=["1_1", "1_4", "d_1", "d_2"]) +def iaao_data(request) -> tuple: + sample = pd.read_csv(FIXTURE_DIR / f"iaao_table_{request.param}.csv") + return request.param, sample.estimate, sample.sale_price + + @pt.fixture( scope="session", params=[ diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 4a0c474..300f171 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -14,58 +14,7 @@ def metric_val(self, metric, ccao_data, quintos_data): return getattr(ap, metric)(*quintos_data) return getattr(ap, metric)(*ccao_data) - def test_iaao_metrics_1_4(self, IAAO_sample_1_4): - """ - Test that COD, PRB, and PRD for the IAAO_sample return expected values. - """ - estimates, sale_prices = IAAO_sample_1_4 - - # Calculate COD - cod = round(ap.cod(estimates, sale_prices), 1) - - # Calculate PRB - prb = round(ap.prb(estimates, sale_prices), 3) - - # Calculate PRD - prd = round(ap.prd(estimates, sale_prices), 2) - - assert cod == 7.5, f"Expected COD to be 7.5, but got {cod}" - assert prb == 0.135, f"Expected PRB to be .135, but got {prb}" - assert prd == 1.03, f"Expected PRD to be 0.98, but got {prd}" - - def test_iaao_metrics_d_1(self, IAAO_sample_d_1): - """ - Test that COD, PRB, and PRD for the IAAO_sample return expected values. - """ - estimates, sale_prices = IAAO_sample_d_1 - - # Calculate COD - cod = round(ap.cod(estimates, sale_prices), 1) - - # Calculate PRB - prb = round(ap.prb(estimates, sale_prices), 3) - - # Calculate PRD - prd = round(ap.prd(estimates, sale_prices), 2) - - assert cod == 7.5, f"Expected COD to be .075, but got {cod}" - assert prb == -0.120, f"Expected PRB to be .0.120, but got {prb}" - assert prd == 1.03, f"Expected PRD to be 1.03, but got {prd}" - - def test_mki(self, quintos_data): - """ - Test that MKI for the quintos_sample returns the expected value. - """ - estimates, sale_prices = quintos_data - - # Calculate MKI - mki = round(ap.mki(estimates, sale_prices), 2) - ki = round(ap.ki(estimates, sale_prices), 2) - - assert mki == 0.79, f"Expected MKI to be 0.79, but got {mki}" - assert ki == -0.06, f"Expected KI to be -0.06, but got {ki}" - - def test_metric_value_is_correct(self, metric, metric_val): + def test_metric_value_is_correct_ccao(self, metric, metric_val): expected = { "cod": 17.81456901196891, "prd": 1.0484192615223522, @@ -73,7 +22,37 @@ def test_metric_value_is_correct(self, metric, metric_val): "mki": 0.794, "ki": -0.06, } - assert pt.approx(metric_val, rel=0.02) == expected[metric] + assert pt.approx(metric_val, rel=0.01) == expected[metric] + + def test_metric_value_is_correct_iaao(self, metric, iaao_data): + if metric in ["mki", "ki"]: + return None + else: + table_name, estimate, sale_price = iaao_data + result = getattr(ap, metric)(estimate, sale_price) + expected = { + "1_1": { + "cod": 29.8, + "prd": 0.98, + "prb": 0.232, + }, + "1_4": { + "cod": 14.5, + "prd": 0.98, + "prb": 0.135, + }, + "d_1": { + "cod": 7.5, + "prd": 1.027, + "prb": -0.120, + }, + "d_2": { + "cod": 7.8, + "prd": 1.056, + "prb": -0.011, + }, + } + assert pt.approx(result, rel=0.02) == expected[table_name][metric] def test_metric_has_numeric_output(self, metric_val): assert type(metric_val) is float @@ -89,7 +68,7 @@ def test_metric_succeeds_on_good_input(self, metric, good_input): def test_metric_met_function_thresholds(self, metric, metric_val): if metric == "ki": - pt.skip("Skipping test for 'ki' metric (ki_met does not exist)") + return None expected = { "cod": False, "prd": False, From 0d84a32a84c61bcc3fc602cf7bd06080e1cfeb49 Mon Sep 17 00:00:00 2001 From: Dan Snow Date: Wed, 27 Nov 2024 19:45:50 +0000 Subject: [PATCH 29/29] Update test fixture structure --- assesspy/tests/conftest.py | 13 +++++++++---- assesspy/tests/test_metrics.py | 11 +++++++---- assesspy/tests/test_sales_chasing.py | 28 +++++++++++++++------------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/assesspy/tests/conftest.py b/assesspy/tests/conftest.py index 9505996..725e6d4 100644 --- a/assesspy/tests/conftest.py +++ b/assesspy/tests/conftest.py @@ -27,10 +27,15 @@ def quintos_data() -> tuple: return sample.estimate, sample.sale_price -@pt.fixture(scope="module", params=["1_1", "1_4", "d_1", "d_2"]) -def iaao_data(request) -> tuple: - sample = pd.read_csv(FIXTURE_DIR / f"iaao_table_{request.param}.csv") - return request.param, sample.estimate, sample.sale_price +@pt.fixture(scope="session", params=["1_1", "1_4", "d_1", "d_2"]) +def iaao_data_name(request): + return request.param + + +@pt.fixture(scope="session") +def iaao_data(iaao_data_name) -> tuple: + sample = pd.read_csv(FIXTURE_DIR / f"iaao_table_{iaao_data_name}.csv") + return sample.estimate, sample.sale_price @pt.fixture( diff --git a/assesspy/tests/test_metrics.py b/assesspy/tests/test_metrics.py index 300f171..50603c6 100644 --- a/assesspy/tests/test_metrics.py +++ b/assesspy/tests/test_metrics.py @@ -24,12 +24,13 @@ def test_metric_value_is_correct_ccao(self, metric, metric_val): } assert pt.approx(metric_val, rel=0.01) == expected[metric] - def test_metric_value_is_correct_iaao(self, metric, iaao_data): + def test_metric_value_is_correct_iaao( + self, metric, iaao_data_name, iaao_data + ): if metric in ["mki", "ki"]: return None else: - table_name, estimate, sale_price = iaao_data - result = getattr(ap, metric)(estimate, sale_price) + result = getattr(ap, metric)(*iaao_data) expected = { "1_1": { "cod": 29.8, @@ -52,7 +53,9 @@ def test_metric_value_is_correct_iaao(self, metric, iaao_data): "prb": -0.011, }, } - assert pt.approx(result, rel=0.02) == expected[table_name][metric] + assert ( + pt.approx(result, rel=0.02) == expected[iaao_data_name][metric] + ) def test_metric_has_numeric_output(self, metric_val): assert type(metric_val) is float diff --git a/assesspy/tests/test_sales_chasing.py b/assesspy/tests/test_sales_chasing.py index f7f5bc3..076208e 100644 --- a/assesspy/tests/test_sales_chasing.py +++ b/assesspy/tests/test_sales_chasing.py @@ -13,33 +13,37 @@ def sample_dist(self, ccao_data): return ratio @pt.fixture(params=["normal", "chased", "sample"]) - def distribution(self, request, ccao_data, sample_dist): - return request.param, { + def distribution_name(self, request): + return request.param + + @pt.fixture + def distribution(self, distribution_name, ccao_data, sample_dist): + return { "normal": np.random.normal(1, size=1000).tolist(), "chased": np.append( np.random.normal(1, 0.15, 900), [1] * 100 ).tolist(), "sample": sample_dist, - }[request.param] + }[distribution_name] @pt.fixture(params=["cdf", "dist", "both"]) def method(self, request): return request.param def test_is_sales_chased_output_is_boolean(self, distribution, method): - dist_name, dist_data = distribution - assert isinstance(ap.is_sales_chased(dist_data, method), bool) + assert isinstance(ap.is_sales_chased(distribution, method), bool) - def test_is_sales_chased_has_expected_output(self, distribution, method): - dist_name, dist_data = distribution + def test_is_sales_chased_has_expected_output( + self, distribution_name, distribution, method + ): expected = { "normal": {"cdf": False, "dist": False, "both": False}, "chased": {"cdf": True, "dist": True, "both": True}, "sample": {"cdf": False, "dist": True, "both": False}, } assert ( - ap.is_sales_chased(dist_data, method) - == expected[dist_name][method] + ap.is_sales_chased(distribution, method) + == expected[distribution_name][method] ) @pt.mark.parametrize( @@ -61,13 +65,11 @@ def test_is_sales_chased_raises_on_invalid_values( self, input_data, distribution, method ): with pt.raises(Exception): - dist_name, dist_data = distribution - ap.is_outlier(input_data(dist_data), method) + ap.is_outlier(input_data(distribution), method) def test_is_sales_chased_raises_on_invalid_method(self, distribution): with pt.raises(Exception): - dist_name, dist_data = distribution - ap.is_sales_chased(dist_data, method="hug") + ap.is_sales_chased(distribution, method="hug") def test_is_sales_chased_warns_on_small_sample(self): with pt.warns(UserWarning):