Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fixes across Lee and swap to survival function for #243 #245

Merged
merged 9 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
- ci/310-DEV.yaml
- ci/310-numba-DEV.yaml
- ci/311.yaml
- ci/311-numba.yaml
- ci/311-DEV.yaml
- ci/311-numba-DEV.yaml
include:
- environment-file: ci/310-numba.yaml
os: macos-latest
Expand Down
1 change: 1 addition & 0 deletions ci/310-DEV.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.12.0
- shapely>=2
1 change: 1 addition & 0 deletions ci/310-numba-DEV.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.12.0
- shapely>=2
1 change: 1 addition & 0 deletions ci/310.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.7.0
- shapely>=2
28 changes: 28 additions & 0 deletions ci/311-DEV.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: test
channels:
- conda-forge
dependencies:
- python=3.11
# required
- geos
- pandas>=1.0
- scikit-learn
- scipy>=1.0
# testing
- codecov
- matplotlib
- pytest
- pytest-cov
- pytest-xdist
- rtree
# doc build
- nbsphinx
- numpydoc
- sphinx
- sphinxcontrib-bibtex
- sphinxcontrib-napoleon
- sphinx_bootstrap_theme
- pip:
- git+https://github.com/pysal/libpysal@main
- git+https://github.com/geopandas/geopandas@main
- git+https://github.com/toblerity/shapely@main
30 changes: 30 additions & 0 deletions ci/311-numba-DEV.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: test
channels:
- conda-forge
dependencies:
- python=3.11
# required
- geos
- pandas>=1.0
- scikit-learn
- scipy>=1.0
- numba
# testing
- codecov
- matplotlib
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
# doc build
- nbsphinx
- numpydoc
- sphinx
- sphinxcontrib-bibtex
- sphinxcontrib-napoleon
- sphinx_bootstrap_theme
- pip:
- git+https://github.com/pysal/libpysal@main
- git+https://github.com/geopandas/geopandas@main
- git+https://github.com/toblerity/shapely@main
28 changes: 28 additions & 0 deletions ci/311-numba.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: test
channels:
- conda-forge
dependencies:
- python=3.11
# required
- libpysal
- pandas>=1.0
- scikit-learn
- scipy>=1.0
- numba
# testing
- codecov
- matplotlib
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.7.0
- shapely>=2.0
# doc build
- nbsphinx
- numpydoc
- sphinx
- sphinxcontrib-bibtex
- sphinxcontrib-napoleon
- sphinx_bootstrap_theme
1 change: 1 addition & 0 deletions ci/311.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.7.0
- shapely>=2
Expand Down
1 change: 1 addition & 0 deletions ci/38-numba.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.7.0
- shapely>=2
1 change: 1 addition & 0 deletions ci/38.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.7.0
- shapely>=2
1 change: 1 addition & 0 deletions ci/39-numba.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.7.0
- shapely>=2
1 change: 1 addition & 0 deletions ci/39.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-xdist
- rtree
# optional
- geopandas>=0.7.0
- shapely>=2
6 changes: 3 additions & 3 deletions esda/geary.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ def __init__(self, y, w, transformation="r", permutations=999):
self.z_norm = de / self.seC_norm
self.z_rand = de / self.seC_rand
if de > 0:
self.p_norm = 1 - stats.norm.cdf(self.z_norm)
self.p_rand = 1 - stats.norm.cdf(self.z_rand)
self.p_norm = stats.norm.sf(self.z_norm)
self.p_rand = stats.norm.sf(self.z_rand)
else:
self.p_norm = stats.norm.cdf(self.z_norm)
self.p_rand = stats.norm.cdf(self.z_rand)
Expand All @@ -147,7 +147,7 @@ def __init__(self, y, w, transformation="r", permutations=999):
self.seC_sim = np.array(sim).std()
self.VC_sim = self.seC_sim**2
self.z_sim = (self.C - self.EC_sim) / self.seC_sim
self.p_z_sim = 1 - stats.norm.cdf(np.abs(self.z_sim))
self.p_z_sim = stats.norm.sf(np.abs(self.z_sim))

@property
def _statistic(self):
Expand Down
4 changes: 2 additions & 2 deletions esda/getisord.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ def __init__(
self.permutations = permutations
self.star = star
self.calc()
self.p_norm = 1 - stats.norm.cdf(np.abs(self.Zs))
self.p_norm = stats.norm.sf(np.abs(self.Zs))
if permutations:
self.p_sim, self.rGs = _crand_plus(
y,
Expand All @@ -432,7 +432,7 @@ def __init__(
self.seG_sim = sim.std(axis=0)
self.VG_sim = self.seG_sim * self.seG_sim
self.z_sim = (self.Gs - self.EG_sim) / self.seG_sim
self.p_z_sim = 1 - stats.norm.cdf(np.abs(self.z_sim))
self.p_z_sim = stats.norm.sf(np.abs(self.z_sim))

def __crand(self, keep_simulations):
y = self.y
Expand Down
10 changes: 5 additions & 5 deletions esda/lee.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def fit(self, x, y):
Z = numpy.column_stack((x, y))

standard_connectivity = sparse.csc_matrix(
self.connectivity / self.connectivity.sum(axis=1)
self.connectivity / self.connectivity.sum(axis=1).reshape(-1, 1)
)

n, _ = x.shape
Expand Down Expand Up @@ -221,11 +221,11 @@ def fit(self, x, y):
random_neighbor_y = y[random_neighbors]

self.reference_distribution_[i] = (
(weight * random_neighbor_y - y.mean()).sum(axis=1).squeeze()
)
(weight * random_neighbor_y).sum(axis=1) - y.mean()
).squeeze()
self.reference_distribution_[i] *= (
(weight * random_neighbor_x - x.mean()).sum(axis=1).squeeze()
)
(weight * random_neighbor_x).sum(axis=1) - x.mean()
).squeeze()
above = self.reference_distribution_ >= self.associations_.reshape(-1, 1)
larger = above.sum(axis=1)
extreme = numpy.minimum(larger, self.permutations - larger)
Expand Down
12 changes: 6 additions & 6 deletions esda/moran.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ def __init__(
self.z_rand = (self.I - self.EI) / self.seI_rand

if self.z_norm > 0:
self.p_norm = 1 - stats.norm.cdf(self.z_norm)
self.p_rand = 1 - stats.norm.cdf(self.z_rand)
self.p_norm = stats.norm.sf(self.z_norm)
self.p_rand = stats.norm.sf(self.z_rand)
else:
self.p_norm = stats.norm.cdf(self.z_norm)
self.p_rand = stats.norm.cdf(self.z_rand)
Expand All @@ -193,7 +193,7 @@ def __init__(
self.VI_sim = self.seI_sim**2
self.z_sim = (self.I - self.EI_sim) / self.seI_sim
if self.z_sim > 0:
self.p_z_sim = 1 - stats.norm.cdf(self.z_sim)
self.p_z_sim = stats.norm.sf(self.z_sim)
else:
self.p_z_sim = stats.norm.cdf(self.z_sim)

Expand Down Expand Up @@ -424,7 +424,7 @@ def __init__(self, x, y, w, transformation="r", permutations=PERMUTATIONS):
self.VI_sim = self.seI_sim**2
self.z_sim = (self.I - self.EI_sim) / self.seI_sim
if self.z_sim > 0:
self.p_z_sim = 1 - stats.norm.cdf(self.z_sim)
self.p_z_sim = stats.norm.sf(self.z_sim)
else:
self.p_z_sim = stats.norm.cdf(self.z_sim)

Expand Down Expand Up @@ -1056,7 +1056,7 @@ def __init__(
self.seI_sim = self.sim.std(axis=0)
self.VI_sim = self.seI_sim * self.seI_sim
self.z_sim = (self.Is - self.EI_sim) / self.seI_sim
self.p_z_sim = 1 - stats.norm.cdf(np.abs(self.z_sim))
self.p_z_sim = stats.norm.sf(np.abs(self.z_sim))
else:
self.sim = self.rlisas = None
self.EI_sim = np.nan
Expand Down Expand Up @@ -1361,7 +1361,7 @@ def __init__(
self.seI_sim = sim.std(axis=0)
self.VI_sim = self.seI_sim * self.seI_sim
self.z_sim = (self.Is - self.EI_sim) / self.seI_sim
self.p_z_sim = 1 - stats.norm.cdf(np.abs(self.z_sim))
self.p_z_sim = stats.norm.sf(np.abs(self.z_sim))

def __calc(self, w, zx, zy):
zly = slag(w, zy)
Expand Down
84 changes: 84 additions & 0 deletions esda/tests/test_lee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import unittest
import libpysal
import geopandas
from libpysal.common import pandas, RTOL, ATOL
from .. import lee
import numpy


PANDAS_EXTINCT = pandas is None

class Lee_Tester(unittest.TestCase):
def setUp(self):
self.data = geopandas.read_file(libpysal.examples.get_path("columbus.shp"))
self.w = libpysal.weights.Queen.from_dataframe(self.data)
self.w.transform = 'r'
self.x = self.data[['HOVAL']].values
self.y = self.data[['CRIME']].values

def test_global(self):
numpy.random.seed(2478879)
result = lee.Spatial_Pearson(connectivity=self.w.sparse).fit(self.x, self.y)
known = numpy.array([[ 0.30136527, -0.23625603],
[-0.23625603, 0.53512008]])
numpy.testing.assert_allclose(known,result.association_, rtol=RTOL, atol=ATOL)
numpy.testing.assert_array_equal(result.reference_distribution_.shape, (999,2,2))
first_rep = numpy.array([[ 0.22803705, -0.08053692],
[-0.08053692, 0.18897318]])

second_rep = numpy.array([[ 0.14179274, -0.06962692],
[-0.06962692, 0.13688337]])
numpy.testing.assert_allclose(first_rep, result.reference_distribution_[0],
rtol=RTOL, atol=ATOL)
numpy.testing.assert_allclose(second_rep, result.reference_distribution_[1],
rtol=RTOL, atol=ATOL)

known_significance = numpy.array([[0.125, 0.026],
[0.026, 0.001]])
numpy.testing.assert_allclose(known_significance, result.significance_,
rtol=RTOL, atol=ATOL)

def test_local(self):
numpy.random.seed(2478879)
result = lee.Spatial_Pearson_Local(connectivity=self.w.sparse).fit(self.x, self.y)
known_locals = numpy.array([ 0.10246023, -0.24169198, -0.1308714 ,
0.00895543, -0.16080899, -0.00950808,
-0.14615398, -0.0627634 , 0.00661232,
-0.42354628, -0.73121006, 0.02060548,
0.05187356, 0.06515283, -0.64400723,
-0.37489818, -2.06573667, -0.10931854,
0.50823848, -0.06338637, -0.10559429,
0.03282849, -0.86618915, -0.62333825,
-0.40910044,-0.41866868, -0.00702983,
-0.4246288 , -0.52142507, -0.22481772,
0.1931263 , -1.39355214, 0.02036755,
0.22896308, -0.00240854, -0.30405211,
-0.66950406, -0.21481868, -0.60320158,
-0.38117303, -0.45584563, 0.32019362,
-0.02818729, -0.02214172, 0.05587915,
0.0295999 , -0.78818135, 0.16854472,
0.2378127 ])
numpy.testing.assert_allclose(known_locals, result.associations_,
rtol=RTOL, atol=ATOL)
significances = numpy.array([0.154, 0.291, 0.358, 0.231, 0.146,
0.335, 0.325, 0.388, 0.244, 0.111,
0.019, 0.165, 0.136, 0.073, 0.014,
0.029, 0.002, 0.376, 0.003, 0.265,
0.449, 0.121, 0.072, 0.006, 0.036,
0.06 , 0.355, 0.01 , 0.017, 0.168,
0.022, 0.003, 0.217, 0.016, 0.337,
0.137, 0.015, 0.128, 0.11 , 0.09 ,
0.168, 0.031, 0.457, 0.44 , 0.141,
0.249, 0.158, 0.018, 0.031])
numpy.testing.assert_allclose(significances, result.significance_,
rtol=RTOL, atol=ATOL)

suite = unittest.TestSuite()
test_classes = [Lee_Tester]
for i in test_classes:
a = unittest.TestLoader().loadTestsFromTestCase(i)
suite.addTest(a)

if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite)