├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── doc
├── Makefile
├── _static
│ ├── images
│ │ └── pysal_favicon.ico
│ ├── pysal-styles.css
│ └── references.bib
├── api.rst
├── conf.py
├── generated
│ ├── spint.dispersion.alpha_disp.rst
│ ├── spint.dispersion.phi_disp.rst
│ ├── spint.gravity.Attraction.rst
│ ├── spint.gravity.BaseGravity.rst
│ ├── spint.gravity.Doubly.rst
│ ├── spint.gravity.Gravity.rst
│ └── spint.gravity.Production.rst
├── index.rst
├── installation.rst
├── make.bat
└── references.rst
├── notebooks
├── 4d_distance.ipynb
├── Example_NYCBikes_AllFeatures.ipynb
├── NYC_Bike_Example.ipynb
├── New_DistanceBand.ipynb
├── ODW_example.ipynb
├── OD_weights.ipynb
├── autograd_test.ipynb
├── dispersion_test.ipynb
├── exampe_accessibility.ipynb
├── glm_speed.ipynb
├── local_SI.ipynb
├── netW.ipynb
├── sparse_categorical.ipynb
├── sparse_categorical_bottleneck.ipynb
├── sparse_categorical_speed.ipynb
├── sparse_grav.ipynb
├── sparse_scipy_optim.ipynb
├── sparse_vs_dense_grav.ipynb
├── test_grav.ipynb
└── validate_gravity.ipynb
├── readthedocs.yml
├── requirements.txt
├── requirements_docs.txt
├── requirements_tests.txt
├── setup.cfg
├── setup.py
├── spint
├── __init__.py
├── count_model.py
├── dispersion.py
├── flow_accessibility.py
├── gravity.py
├── primer
│ ├── SpIntPrimer.pdf
│ ├── austria.csv
│ ├── austria.dbf
│ ├── austria.prj
│ ├── austria.qpj
│ ├── austria.shp
│ └── austria.shx
├── tests
│ ├── __init__.py
│ ├── test_accessibility.py
│ ├── test_count_model.py
│ ├── test_dispersion.py
│ ├── test_gravity.py
│ ├── test_universal.py
│ └── test_vec_SA.py
├── universal.py
├── utils.py
└── vec_SA.py
└── tools
└── gitcount.ipynb
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | *.swp
3 | *.pyc
4 | .rope*
5 | .idea/
6 | notebooks/.ipynb_checkpoints/
7 | .DS_Store
8 | .ipynb_checkpoints/
9 | *.bak
10 | .eggs/
11 | *.egg-info/
12 |
13 | # Packages
14 | *.egg
15 | *.egg-info
16 | dist
17 | build
18 | eggs
19 | parts
20 | bin
21 | var
22 | sdist
23 | develop-eggs
24 | .installed.cfg
25 | lib
26 | lib64
27 | _build
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | dist: xenial
3 | sudo: true
4 | branches:
5 | only:
6 | - master
7 | python:
8 | - 3.6
9 | - 3.7
10 |
11 | env:
12 | - PYSAL_PYPI=true #testing on dependencies libpysal, esda, mapcalssify on pypi
13 | - PYSAL_PYPI=false
14 |
15 | matrix:
16 | allow_failures:
17 | - python: 3.6
18 | env: PYSAL_PYPI=false
19 | - python: 3.7
20 | env: PYSAL_PYPI=false
21 |
22 | before_install:
23 | - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
24 | - chmod +x miniconda.sh
25 | - ./miniconda.sh -b -p ./miniconda
26 | - export PATH=`pwd`/miniconda/bin:$PATH
27 | - conda update --yes conda
28 | - conda config --append channels conda-forge
29 | - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION
30 | - source activate test-env
31 |
32 | install:
33 | - conda install --yes pip
34 | - pip install -r requirements.txt
35 | - pip install -r requirements_tests.txt
36 | - if "$PYSAL_PYPI"; then
37 | echo 'testing pypi libpysal spreg spglm';
38 | else
39 | echo 'testing git libpysal spreg spglm';
40 | git clone https://github.com/pysal/libpysal.git;
41 | cd libpysal; pip install .; cd ../;
42 | git clone https://github.com/pysal/spreg.git;
43 | cd spreg; pip install .; cd ../;
44 | git clone https://github.com/pysal/spglm.git;
45 | cd spglm; pip install .; cd ../;
46 | fi;
47 |
48 | script:
49 | - python setup.py sdist >/dev/null
50 | - python setup.py install
51 | - python -c 'import libpysal; libpysal.examples.load_example("nyc_bikes")'
52 | - nosetests --verbose --with-doctest --with-coverage --cover-package=spint;
53 |
54 | notifications:
55 | email:
56 | recipients:
57 | - tayoshan@gmail.com
58 | on_change: change
59 | on_failure: always
60 |
61 | after_success:
62 | - coveralls
63 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # Changes
3 |
4 | Version 1.0.7 (2020-09-08)
5 |
6 | We closed a total of 10 issues (enhancements and bug fixes) through 5 pull requests, since our last release on 2019-07-22.
7 |
8 | ## Issues Closed
9 | - update travis (#25)
10 | - addressing pysal/pysal#1145 (#24)
11 | - bump version for release (#23)
12 | - update log (#22)
13 | - Updates (#21)
14 |
15 | ## Pull Requests
16 | - update travis (#25)
17 | - addressing pysal/pysal#1145 (#24)
18 | - bump version for release (#23)
19 | - update log (#22)
20 | - Updates (#21)
21 |
22 | The following individuals contributed to this release:
23 |
24 | - Taylor Oshan
25 | - James Gaboardi
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2018, Python Spatial Analysis Library
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE MANIFEST.in requirements_docs.txt requirements_tests.txt requirements.txt
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Spatial Interaction Modeling Package
2 | ===========================================
3 |
4 | [](https://travis-ci.org/pysal/spint)
5 | [](https://spint.readthedocs.io/en/latest/?badge=latest)
6 | [](https://badge.fury.io/py/spint)
7 |
8 |
9 | The **Sp**atial **Int**eraction Modeling (SpInt) module seeks to provide a collection of tools to study spatial interaction processes and analyze spatial interaction data.
10 |
11 | The [initial development](https://github.com/pysal/pysal/wiki/SpInt-Development) of the module was carried out as a Google Summer of Code
12 | project (summer 2016). Documentation of the project progress can be found on the
13 | [project blog](https://tayloroshan.github.io/).
14 |
15 | The module currently supports the calibration of the 'family' of spatial interaction models (Wilson, 1971) which are derived using an entropy maximizing (EM) framework or the equivalent information minimizing (IM) framework. As such, it is able to derive parameters for the following Poisson count models:
16 |
17 | Models
18 | ------
19 |
20 | - unconstrained gravity model
21 | - production-constrained model (origin-constrained)
22 | - attraction-constrained model (destination-constrained)
23 | - doubly-constrained model
24 |
25 | Calibration is carried out using iteratively weighted least squares in a generalized linear modleing framework (Cameron & Trivedi, 2013). These model results have been verified against comparable routines laid out in (Fotheringham and O’Kelly, 1989; Willimans and Fotheringham, 1984) and functions avaialble in R such as GL or Pythons statsmodels. The estimation of the constrained routines are carried out using sparse data strucutres for lower memory overhead and faster computations.
26 |
27 | Additional Features
28 | -------------------
29 |
30 | - QuasiPoisson model estimation
31 | - Regression-based tests for overdispersion
32 | - Model fit statistics including typical GLM metrics, standardized root mean
33 | square error, and Sorensen similarit index
34 | - Vector-based Moran's I statistic for testing for spatial autcorrelation in
35 | spatial interaction data
36 | - Local subset model calibration for mappable sets of parameter estimates and model
37 | diagnostics
38 | - Three types of spatial interaction spatial weights: origin-destination
39 | contiguity weights, network-based weights, and vector-based distance weights
40 |
41 | In Progress
42 | -----------
43 |
44 | - Spatial Autoregressive (Lag) model spatial interaction specification
45 |
46 | Future Work
47 | -----------
48 |
49 | - Parameter estimation via maximum likelihood and gradient-based optimization
50 | - Zero-inflated Poisson model
51 | - Negative Binomial model/zero-inflated negative binomial model
52 | - Functions to compute competing destinations
53 | - Functions to compute eigenvector spatial filters
54 | - Parameter estimation via neural networks
55 | - Universal (determinsitic) models such as the Radiation model and Inverse
56 | Population Weighted model
57 |
58 | Cameron, C. A. and Trivedi, P. K. (2013). Regression analyis of count data.
59 | Cambridge University Press, 1998.
60 |
61 | Fotheringham, A. S. and O'Kelly, M. E. (1989). Spatial Interaction Models: Formulations and Applications. London: Kluwer Academic Publishers.
62 |
63 | Williams, P. A. and A. S. Fotheringham (1984), The Calibration of Spatial Interaction
64 | Models by Maximum Likelihood Estimation with Program SIMODEL, Geographic Monograph
65 | Series, 7, Department of Geography, Indiana University.
66 |
67 | Wilson, A. G. (1971). A family of spatial interaction models, and associated developments. Environment and
68 | Planning A, 3, 1–32.
69 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SPHINXPROJ = spint
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
22 | clean:
23 | rm -rf $(BUILDDIR)/*
24 | rm -rf auto_examples/
25 |
--------------------------------------------------------------------------------
/doc/_static/images/pysal_favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spint/050865acae4054b8ac30b12e6d38ca884e7a43cc/doc/_static/images/pysal_favicon.ico
--------------------------------------------------------------------------------
/doc/_static/pysal-styles.css:
--------------------------------------------------------------------------------
1 | /* Make thumbnails with equal heights */
2 | @media only screen and (min-width : 481px) {
3 | .row.equal-height {
4 | display: flex;
5 | flex-wrap: wrap;
6 | }
7 | .row.equal-height > [class*='col-'] {
8 | display: flex;
9 | flex-direction: column;
10 | }
11 | .row.equal-height.row:after,
12 | .row.equal-height.row:before {
13 | display: flex;
14 | }
15 |
16 | .row.equal-height > [class*='col-'] > .thumbnail,
17 | .row.equal-height > [class*='col-'] > .thumbnail > .caption {
18 | display: flex;
19 | flex: 1 0 auto;
20 | flex-direction: column;
21 | }
22 | .row.equal-height > [class*='col-'] > .thumbnail > .caption > .flex-text {
23 | flex-grow: 1;
24 | }
25 | .row.equal-height > [class*='col-'] > .thumbnail > img {
26 | width: 100%;
27 | height: 200px; /* force image's height */
28 |
29 | /* force image fit inside it's "box" */
30 | -webkit-object-fit: cover;
31 | -moz-object-fit: cover;
32 | -ms-object-fit: cover;
33 | -o-object-fit: cover;
34 | object-fit: cover;
35 | }
36 | }
37 |
38 | .row.extra-bottom-padding{
39 | margin-bottom: 20px;
40 | }
41 |
42 |
43 | .topnavicons {
44 | margin-left: 10% !important;
45 | }
46 |
47 | .topnavicons li {
48 | margin-left: 0px !important;
49 | min-width: 100px;
50 | text-align: center;
51 | }
52 |
53 | .topnavicons .thumbnail {
54 | margin-right: 10px;
55 | border: none;
56 | box-shadow: none;
57 | text-align: center;
58 | font-size: 85%;
59 | font-weight: bold;
60 | line-height: 10px;
61 | height: 100px;
62 | }
63 |
64 | .topnavicons .thumbnail img {
65 | display: block;
66 | margin-left: auto;
67 | margin-right: auto;
68 | }
69 |
70 |
71 | /* Table with a scrollbar */
72 | .bodycontainer { max-height: 600px; width: 100%; margin: 0; overflow-y: auto; }
73 | .table-scrollable { margin: 0; padding: 0; }
--------------------------------------------------------------------------------
/doc/_static/references.bib:
--------------------------------------------------------------------------------
1 | %% This BibTeX bibliography file was created using BibDesk.
2 | %% http://bibdesk.sourceforge.net/
3 |
4 | %% Created for Wei Kang at 2018-08-05 16:12:26 -0700
5 |
6 |
7 | %% Saved with string encoding Unicode (UTF-8)
8 |
9 |
10 |
11 | @book{Press2007,
12 | Address = {Cambridge},
13 | Author = {Press, William H and Teukolsky, Saul A and Vetterling, William T and Flannery, Brian P},
14 | Date-Added = {2018-06-12 22:53:57 +0000},
15 | Date-Modified = {2018-06-12 22:54:05 +0000},
16 | Edition = {3rd},
17 | Keywords = {rank.py},
18 | Publisher = {Cambridge Univ Pr},
19 | Title = {Numerical recipes: the art of scientific computing},
20 | Year = {2007}}
21 |
--------------------------------------------------------------------------------
/doc/api.rst:
--------------------------------------------------------------------------------
1 | .. _api_ref:
2 |
3 | .. currentmodule:: spint
4 |
5 | API reference
6 | =============
7 |
8 | .. _spint_api:
9 |
10 | Gravity-type spatial interaction models
11 | ----------------------------------------
12 |
13 | .. autosummary::
14 | :toctree: generated/
15 |
16 | spint.gravity.BaseGravity
17 | spint.gravity.Gravity
18 | spint.gravity.Production
19 | spint.gravity.Attraction
20 | spint.gravity.Doubly
21 |
22 | Tests for overdispersion
23 | -------------------------
24 |
25 | .. autosummary::
26 | :toctree: generated/
27 |
28 | spint.dispersion.alpha_disp
29 | spint.dispersion.phi_disp
30 |
31 |
--------------------------------------------------------------------------------
/doc/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # giddy documentation build configuration file, created by
4 | # sphinx-quickstart on Wed Jun 6 15:54:22 2018.
5 | #
6 | # This file is execfile()d with the current directory set to its
7 | # containing dir.
8 | #
9 | # Note that not all possible configuration values are present in this
10 | # autogenerated file.
11 | #
12 | # All configuration values have a default; values that are commented out
13 | # serve to show the default.
14 |
15 | # If extensions (or modules to document with autodoc) are in another directory,
16 | # add these directories to sys.path here. If the directory is relative to the
17 | # documentation root, use os.path.abspath to make it absolute, like shown here.
18 | #
19 | import sys, os
20 | import sphinx_bootstrap_theme
21 |
22 |
23 | sys.path.insert(0, os.path.abspath('../../'))
24 |
25 | #import your package to obtain the version info to display on the docs website
26 | import spint
27 |
28 |
29 | # -- General configuration ------------------------------------------------
30 |
31 | # If your documentation needs a minimal Sphinx version, state it here.
32 | #
33 | # needs_sphinx = '1.0'
34 | # Add any Sphinx extension module names here, as strings. They can be
35 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
36 | # ones.
37 | extensions = [#'sphinx_gallery.gen_gallery',
38 | 'sphinx.ext.autodoc',
39 | 'sphinx.ext.autosummary',
40 | 'sphinx.ext.viewcode',
41 | 'sphinxcontrib.bibtex',
42 | 'sphinx.ext.mathjax',
43 | 'sphinx.ext.doctest',
44 | 'sphinx.ext.intersphinx',
45 | 'numpydoc',
46 | 'matplotlib.sphinxext.plot_directive']
47 |
48 |
49 | # Add any paths that contain templates here, relative to this directory.
50 | templates_path = ['_templates']
51 |
52 | # The suffix(es) of source filenames.
53 | # You can specify multiple suffix as a list of string:
54 | #
55 | # source_suffix = ['.rst', '.md']
56 | source_suffix = '.rst'
57 |
58 | # The master toctree document.
59 | master_doc = 'index'
60 |
61 | # General information about the project.
62 | project = "spint" # string of your project name, for example, 'giddy'
63 | copyright = '2018, pysal developers'
64 | author = 'pysal developers'
65 |
66 | # The version info for the project you're documenting, acts as replacement for
67 | # |version| and |release|, also used in various other places throughout the
68 | # built documents.
69 | #
70 | # The full version.
71 | version = spint.__version__ #should replace it with your PACKAGE_NAME
72 | release = spint.__version__ #should replace it with your PACKAGE_NAME
73 |
74 | # The language for content autogenerated by Sphinx. Refer to documentation
75 | # for a list of supported languages.
76 | #
77 | # This is also used if you do content translation via gettext catalogs.
78 | # Usually you set "language" from the command line for these cases.
79 | language = None
80 |
81 | # List of patterns, relative to source directory, that match files and
82 | # directories to ignore when looking for source files.
83 | # This patterns also effect to html_static_path and html_extra_path
84 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'tests/*']
85 |
86 | # The name of the Pygments (syntax highlighting) style to use.
87 | pygments_style = 'sphinx'
88 |
89 | # If true, `todo` and `todoList` produce output, else they produce nothing.
90 | todo_include_todos = False
91 |
92 | # -- Options for HTML output ----------------------------------------------
93 |
94 | # The theme to use for HTML and HTML Help pages. See the documentation for
95 | # a list of builtin themes.
96 | #
97 | # html_theme = 'alabaster'
98 | html_theme = 'bootstrap'
99 | html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
100 | html_title = "%s v%s Manual" % (project, version)
101 |
102 | # (Optional) Logo of your package. Should be small enough to fit the navbar (ideally 24x24).
103 | # Path should be relative to the ``_static`` files directory.
104 | #html_logo = "_static/images/package_logo.jpg"
105 |
106 | # (Optional) PySAL favicon
107 | html_favicon = "_static/images/pysal_favicon.ico"
108 |
109 |
110 | # Theme options are theme-specific and customize the look and feel of a theme
111 | # further. For a list of options available for each theme, see the
112 | # documentation.
113 | #
114 | html_theme_options = {
115 |
116 | # Navigation bar title. (Default: ``project`` value)
117 | 'navbar_title': "spint", # string of your project name, for example, 'giddy'
118 |
119 | # Render the next and previous page links in navbar. (Default: true)
120 | 'navbar_sidebarrel': False,
121 |
122 | # Render the current pages TOC in the navbar. (Default: true)
123 | #'navbar_pagenav': True,
124 | #'navbar_pagenav': False,
125 |
126 | # No sidebar
127 | 'nosidebar': True,
128 |
129 | # Tab name for the current pages TOC. (Default: "Page")
130 | #'navbar_pagenav_name': "Page",
131 |
132 | # Global TOC depth for "site" navbar tab. (Default: 1)
133 | # Switching to -1 shows all levels.
134 | 'globaltoc_depth': 2,
135 |
136 | # Include hidden TOCs in Site navbar?
137 | #
138 | # Note: If this is "false", you cannot have mixed ``:hidden:`` and
139 | # non-hidden ``toctree`` directives in the same page, or else the build
140 | # will break.
141 | #
142 | # Values: "true" (default) or "false"
143 | 'globaltoc_includehidden': "true",
144 |
145 | # HTML navbar class (Default: "navbar") to attach to
element.
146 | # For black navbar, do "navbar navbar-inverse"
147 | #'navbar_class': "navbar navbar-inverse",
148 |
149 | # Fix navigation bar to top of page?
150 | # Values: "true" (default) or "false"
151 | 'navbar_fixed_top': "true",
152 |
153 |
154 | # Location of link to source.
155 | # Options are "nav" (default), "footer" or anything else to exclude.
156 | 'source_link_position': 'footer',
157 |
158 | # Bootswatch (http://bootswatch.com/) theme.
159 | #
160 | # Options are nothing (default) or the name of a valid theme
161 | # such as "amelia" or "cosmo", "yeti", "flatly".
162 | 'bootswatch_theme': "yeti",
163 |
164 | # Choose Bootstrap version.
165 | # Values: "3" (default) or "2" (in quotes)
166 | 'bootstrap_version': "3",
167 |
168 | # Navigation bar menu
169 | 'navbar_links': [
170 | ("Installation", "installation"),
171 | ("API", "api"),
172 | ("References", "references"),
173 | ],
174 |
175 | }
176 |
177 | # Add any paths that contain custom static files (such as style sheets) here,
178 | # relative to this directory. They are copied after the builtin static files,
179 | # so a file named "default.css" will overwrite the builtin "default.css".
180 | html_static_path = ['_static']
181 |
182 | # Custom sidebar templates, maps document names to template names.
183 | #html_sidebars = {}
184 | # html_sidebars = {'sidebar': ['localtoc.html', 'sourcelink.html', 'searchbox.html']}
185 |
186 | # -- Options for HTMLHelp output ------------------------------------------
187 |
188 | # Output file base name for HTML help builder.
189 | htmlhelp_basename = 'spint'+'doc'
190 |
191 |
192 | # -- Options for LaTeX output ---------------------------------------------
193 |
194 | latex_elements = {
195 | # The paper size ('letterpaper' or 'a4paper').
196 | #
197 | # 'papersize': 'letterpaper',
198 |
199 | # The font size ('10pt', '11pt' or '12pt').
200 | #
201 | # 'pointsize': '10pt',
202 |
203 | # Additional stuff for the LaTeX preamble.
204 | #
205 | # 'preamble': '',
206 |
207 | # Latex figure (float) alignment
208 | #
209 | # 'figure_align': 'htbp',
210 | }
211 |
212 | # Grouping the document tree into LaTeX files. List of tuples
213 | # (source start file, target name, title,
214 | # author, documentclass [howto, manual, or own class]).
215 | latex_documents = [
216 | (master_doc, 'spint.tex', u'spint Documentation',
217 | u'pysal developers', 'manual'),
218 | ]
219 |
220 |
221 | # -- Options for manual page output ---------------------------------------
222 |
223 | # One entry per manual page. List of tuples
224 | # (source start file, name, description, authors, manual section).
225 | man_pages = [
226 | (master_doc, 'spint', u'spint Documentation',
227 | [author], 1)
228 | ]
229 |
230 |
231 | # -- Options for Texinfo output -------------------------------------------
232 |
233 | # Grouping the document tree into Texinfo files. List of tuples
234 | # (source start file, target name, title, author,
235 | # dir menu entry, description, category)
236 | texinfo_documents = [
237 | (master_doc, 'spint', u'spint Documentation',
238 | author, 'spint', 'One line description of project.',
239 | 'Miscellaneous'),
240 | ]
241 |
242 |
243 | # -----------------------------------------------------------------------------
244 | # Autosummary
245 | # -----------------------------------------------------------------------------
246 |
247 | # Generate the API documentation when building
248 | autosummary_generate = True
249 | numpydoc_show_class_members = True
250 | class_members_toctree = True
251 | numpydoc_show_inherited_class_members = True
252 | numpydoc_use_plots = True
253 |
254 | # display the source code for Plot directive
255 | plot_include_source = True
256 |
257 | def setup(app):
258 | app.add_stylesheet("pysal-styles.css")
259 |
260 | # Example configuration for intersphinx: refer to the Python standard library.
261 | intersphinx_mapping = {'https://docs.python.org/3.6/': None}
262 |
263 |
--------------------------------------------------------------------------------
/doc/generated/spint.dispersion.alpha_disp.rst:
--------------------------------------------------------------------------------
1 | spint.dispersion.alpha\_disp
2 | ============================
3 |
4 | .. currentmodule:: spint.dispersion
5 |
6 | .. autofunction:: alpha_disp
--------------------------------------------------------------------------------
/doc/generated/spint.dispersion.phi_disp.rst:
--------------------------------------------------------------------------------
1 | spint.dispersion.phi\_disp
2 | ==========================
3 |
4 | .. currentmodule:: spint.dispersion
5 |
6 | .. autofunction:: phi_disp
--------------------------------------------------------------------------------
/doc/generated/spint.gravity.Attraction.rst:
--------------------------------------------------------------------------------
1 | spint.gravity.Attraction
2 | ========================
3 |
4 | .. currentmodule:: spint.gravity
5 |
6 | .. autoclass:: Attraction
7 |
8 |
9 | .. automethod:: __init__
10 |
11 |
12 | .. rubric:: Methods
13 |
14 | .. autosummary::
15 |
16 | ~Attraction.SRMSE
17 | ~Attraction.SSI
18 | ~Attraction.__init__
19 | ~Attraction.fit
20 | ~Attraction.local
21 | ~Attraction.reshape
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/doc/generated/spint.gravity.BaseGravity.rst:
--------------------------------------------------------------------------------
1 | spint.gravity.BaseGravity
2 | =========================
3 |
4 | .. currentmodule:: spint.gravity
5 |
6 | .. autoclass:: BaseGravity
7 |
8 |
9 | .. automethod:: __init__
10 |
11 |
12 | .. rubric:: Methods
13 |
14 | .. autosummary::
15 |
16 | ~BaseGravity.SRMSE
17 | ~BaseGravity.SSI
18 | ~BaseGravity.__init__
19 | ~BaseGravity.fit
20 | ~BaseGravity.reshape
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/doc/generated/spint.gravity.Doubly.rst:
--------------------------------------------------------------------------------
1 | spint.gravity.Doubly
2 | ====================
3 |
4 | .. currentmodule:: spint.gravity
5 |
6 | .. autoclass:: Doubly
7 |
8 |
9 | .. automethod:: __init__
10 |
11 |
12 | .. rubric:: Methods
13 |
14 | .. autosummary::
15 |
16 | ~Doubly.SRMSE
17 | ~Doubly.SSI
18 | ~Doubly.__init__
19 | ~Doubly.fit
20 | ~Doubly.local
21 | ~Doubly.reshape
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/doc/generated/spint.gravity.Gravity.rst:
--------------------------------------------------------------------------------
1 | spint.gravity.Gravity
2 | =====================
3 |
4 | .. currentmodule:: spint.gravity
5 |
6 | .. autoclass:: Gravity
7 |
8 |
9 | .. automethod:: __init__
10 |
11 |
12 | .. rubric:: Methods
13 |
14 | .. autosummary::
15 |
16 | ~Gravity.SRMSE
17 | ~Gravity.SSI
18 | ~Gravity.__init__
19 | ~Gravity.fit
20 | ~Gravity.local
21 | ~Gravity.reshape
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/doc/generated/spint.gravity.Production.rst:
--------------------------------------------------------------------------------
1 | spint.gravity.Production
2 | ========================
3 |
4 | .. currentmodule:: spint.gravity
5 |
6 | .. autoclass:: Production
7 |
8 |
9 | .. automethod:: __init__
10 |
11 |
12 | .. rubric:: Methods
13 |
14 | .. autosummary::
15 |
16 | ~Production.SRMSE
17 | ~Production.SSI
18 | ~Production.__init__
19 | ~Production.fit
20 | ~Production.local
21 | ~Production.reshape
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | .. documentation master file
2 |
3 | SPatial INTeraction models (SPINT)
4 |
5 | .. toctree::
6 | :hidden:
7 | :maxdepth: 3
8 | :caption: Contents:
9 |
10 | Installation
11 | API
12 | References
13 |
14 |
15 | .. _PySAL: https://github.com/pysal/pysal
16 |
--------------------------------------------------------------------------------
/doc/installation.rst:
--------------------------------------------------------------------------------
1 | .. Installation
2 |
3 | Installation
4 | ============
5 |
6 |
7 | spint supports python `3.5`_ and `3.6`_ only. Please make sure that you are
8 | operating in a python 3 environment.
9 |
10 | Installing released version
11 | ---------------------------
12 |
13 | spint is available on the `Python Package Index`_. Therefore, you can either
14 | install directly with `pip` from the command line::
15 |
16 | pip install -U spint
17 |
18 |
19 | or download the source distribution (.tar.gz) and decompress it to your selected
20 | destination. Open a command shell and navigate to the decompressed folder.
21 | Type::
22 |
23 | pip install .
24 |
25 | Installing development version
26 | ------------------------------
27 |
28 | Potentially, you might want to use the newest features in the development
29 | version of spint on github - `pysal/spint`_ while have not been incorporated
30 | in the Pypi released version. You can achieve that by installing `pysal/spint`_
31 | by running the following from a command shell::
32 |
33 | pip install https://github.com/pysal/spint/archive/master.zip
34 |
35 | You can also `fork`_ the `pysal/spint`_ repo and create a local clone of
36 | your fork. By making changes
37 | to your local clone and submitting a pull request to `pysal/spint`_, you can
38 | contribute to the mgwr development.
39 |
40 | .. _3.5: https://docs.python.org/3.5/
41 | .. _3.6: https://docs.python.org/3.6/
42 | .. _Python Package Index: https://pypi.org/project/spglm/
43 | .. _pysal/spint: https://github.com/pysal/spint
44 | .. _fork: https://help.github.com/articles/fork-a-repo/
45 |
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=python -msphinx
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 | set SPHINXPROJ=spint
13 |
14 | if "%1" == "" goto help
15 |
16 | %SPHINXBUILD% >NUL 2>NUL
17 | if errorlevel 9009 (
18 | echo.
19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed,
20 | echo.then set the SPHINXBUILD environment variable to point to the full
21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the
22 | echo.Sphinx directory to PATH.
23 | echo.
24 | echo.If you don't have Sphinx installed, grab it from
25 | echo.http://sphinx-doc.org/
26 | exit /b 1
27 | )
28 |
29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
30 | goto end
31 |
32 | :help
33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
34 |
35 | :end
36 | popd
37 |
--------------------------------------------------------------------------------
/doc/references.rst:
--------------------------------------------------------------------------------
1 | .. reference for the docs
2 |
3 | References
4 | ==========
5 |
6 | .. bibliography:: _static/references.bib
7 | :cited:
8 |
--------------------------------------------------------------------------------
/notebooks/New_DistanceBand.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": false,
8 | "jupyter": {
9 | "outputs_hidden": false
10 | }
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import numpy as np\n",
15 | "from scipy.spatial import distance\n",
16 | "import scipy.spatial as spatial\n",
17 | "from pysal.weights import W\n",
18 | "from pysal.weights.util import isKDTree\n",
19 | "from pysal.weights import Distance as Distance\n",
20 | "from pysal.weights import WSP, WSP2W\n",
21 | "from scipy.spatial import distance_matrix\n",
22 | "import scipy.sparse as sp\n",
23 | "from pysal.common import KDTree"
24 | ]
25 | },
26 | {
27 | "cell_type": "code",
28 | "execution_count": 2,
29 | "metadata": {
30 | "collapsed": false,
31 | "jupyter": {
32 | "outputs_hidden": false
33 | }
34 | },
35 | "outputs": [],
36 | "source": [
37 | "class DistanceBand(W):\n",
38 | " \"\"\"\n",
39 | " Spatial weights based on distance band.\n",
40 | "\n",
41 | " Parameters\n",
42 | " ----------\n",
43 | "\n",
44 | " data : array\n",
45 | " (n,k) or KDTree where KDtree.data is array (n,k)\n",
46 | " n observations on k characteristics used to measure\n",
47 | " distances between the n objects\n",
48 | " threshold : float\n",
49 | " distance band\n",
50 | " p : float\n",
51 | " Minkowski p-norm distance metric parameter:\n",
52 | " 1<=p<=infinity\n",
53 | " 2: Euclidean distance\n",
54 | " 1: Manhattan distance\n",
55 | " binary : boolean\n",
56 | " If true w_{ij}=1 if d_{i,j}<=threshold, otherwise w_{i,j}=0\n",
57 | " If false wij=dij^{alpha}\n",
58 | " alpha : float\n",
59 | " distance decay parameter for weight (default -1.0)\n",
60 | " if alpha is positive the weights will not decline with\n",
61 | " distance. If binary is True, alpha is ignored\n",
62 | "\n",
63 | " ids : list\n",
64 | " values to use for keys of the neighbors and weights dicts\n",
65 | "\n",
66 | " Attributes\n",
67 | " ----------\n",
68 | " weights : dict\n",
69 | " of neighbor weights keyed by observation id\n",
70 | "\n",
71 | " neighbors : dict\n",
72 | " of neighbors keyed by observation id\n",
73 | "\n",
74 | "\n",
75 | "\n",
76 | " \"\"\"\n",
77 | "\n",
78 | " def __init__(self, data, threshold, p=2, alpha=-1.0, binary=True, ids=None, build_sp=True):\n",
79 | " \"\"\"Casting to floats is a work around for a bug in scipy.spatial.\n",
80 | " See detail in pysal issue #126.\n",
81 | "\n",
82 | " \"\"\"\n",
83 | " self.p = p\n",
84 | " self.threshold = threshold\n",
85 | " self.binary = binary\n",
86 | " self.alpha = alpha\n",
87 | " self.build_sp = build_sp\n",
88 | " \n",
89 | " if isKDTree(data):\n",
90 | " self.kd = data\n",
91 | " self.data = self.kd.data\n",
92 | " else:\n",
93 | " if self.build_sp:\n",
94 | " try:\n",
95 | " data = np.asarray(data)\n",
96 | " if data.dtype.kind != 'f':\n",
97 | " data = data.astype(float)\n",
98 | " self.data = data\n",
99 | " self.kd = KDTree(self.data)\n",
100 | " except:\n",
101 | " raise ValueError(\"Could not make array from data\") \n",
102 | " else:\n",
103 | " self.data = data\n",
104 | " self.kd = None \n",
105 | " \n",
106 | "\n",
107 | " self._band()\n",
108 | " neighbors, weights = self._distance_to_W(ids)\n",
109 | " W.__init__(self, neighbors, weights, ids)\n",
110 | "\n",
111 | " def _band(self):\n",
112 | " \"\"\"Find all pairs within threshold.\n",
113 | "\n",
114 | " \"\"\"\n",
115 | " if self.build_sp: \n",
116 | " self.dmat = self.kd.sparse_distance_matrix(\n",
117 | " self.kd, max_distance=self.threshold)\n",
118 | " else:\n",
119 | " self.dmat = self._spdistance_matrix(self.data, self.data, self.threshold)\n",
120 | " \n",
121 | " def _distance_to_W(self, ids=None):\n",
122 | " if self.binary:\n",
123 | " self.dmat[self.dmat>0] = 1\n",
124 | " tempW = WSP2W(WSP(self.dmat))\n",
125 | " return tempW.neighbors, tempW.weights\n",
126 | "\n",
127 | " else:\n",
128 | " weighted = self.dmat.power(self.alpha)\n",
129 | " weighted[weighted==np.inf] = 0\n",
130 | " tempW = WSP2W(WSP(weighted))\n",
131 | " return tempW.neighbors, tempW.weights\n",
132 | " \n",
133 | " def _spdistance_matrix(self, x,y, threshold=None):\n",
134 | " dist = distance_matrix(x,y)\n",
135 | " if threshold is not None:\n",
136 | " zeros = dist > threshold\n",
137 | " dist[zeros] = 0\n",
138 | " return sp.csr_matrix(dist)"
139 | ]
140 | },
141 | {
142 | "cell_type": "code",
143 | "execution_count": 21,
144 | "metadata": {
145 | "collapsed": true,
146 | "jupyter": {
147 | "outputs_hidden": true
148 | }
149 | },
150 | "outputs": [],
151 | "source": [
152 | "x = np.random.randint(0, 1000, 1000)\n",
153 | "y = np.random.randint(0, 1000, 1000)\n",
154 | "w = np.random.randint(0, 1000, 1000)\n",
155 | "z = np.random.randint(0, 1000, 1000)\n",
156 | "\n",
157 | "data = zip(x.ravel(), y.ravel(), w.ravel(), z.ravel())\n",
158 | "tree = KDTree(data)"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 22,
164 | "metadata": {
165 | "collapsed": false,
166 | "jupyter": {
167 | "outputs_hidden": false
168 | }
169 | },
170 | "outputs": [],
171 | "source": [
172 | "#print np.allclose(Distance.DistanceBand(tree, threshold=500, alpha=-1.5, binary=True).full()[0], DistanceBand(tree, threshold=500, alpha=-1.5, binary=True).full()[0])\n",
173 | "#print np.allclose(Distance.DistanceBand(tree, threshold=500, alpha=-1.5, binary=False).full()[0], DistanceBand(tree, threshold=500, alpha=-1.5, binary=False).full()[0])"
174 | ]
175 | },
176 | {
177 | "cell_type": "code",
178 | "execution_count": 23,
179 | "metadata": {
180 | "collapsed": false,
181 | "jupyter": {
182 | "outputs_hidden": false
183 | }
184 | },
185 | "outputs": [
186 | {
187 | "name": "stdout",
188 | "output_type": "stream",
189 | "text": [
190 | "CPU times: user 1.42 s, sys: 17.9 ms, total: 1.44 s\n",
191 | "Wall time: 1.44 s\n",
192 | "CPU times: user 366 ms, sys: 11.3 ms, total: 377 ms\n",
193 | "Wall time: 376 ms\n"
194 | ]
195 | },
196 | {
197 | "data": {
198 | "text/plain": [
199 | "<__main__.DistanceBand at 0x10c0aedd0>"
200 | ]
201 | },
202 | "execution_count": 23,
203 | "metadata": {},
204 | "output_type": "execute_result"
205 | }
206 | ],
207 | "source": [
208 | "%time Distance.DistanceBand(tree, threshold=500, alpha=-1.5, binary=True)\n",
209 | "%time DistanceBand(tree, threshold=500, alpha=-1.5, binary=True, build_sp=True)\n"
210 | ]
211 | },
212 | {
213 | "cell_type": "code",
214 | "execution_count": 24,
215 | "metadata": {
216 | "collapsed": false,
217 | "jupyter": {
218 | "outputs_hidden": false
219 | }
220 | },
221 | "outputs": [
222 | {
223 | "name": "stdout",
224 | "output_type": "stream",
225 | "text": [
226 | "CPU times: user 1.37 s, sys: 21.7 ms, total: 1.39 s\n",
227 | "Wall time: 1.4 s\n",
228 | "CPU times: user 69.9 ms, sys: 4.84 ms, total: 74.7 ms\n",
229 | "Wall time: 74.7 ms\n"
230 | ]
231 | },
232 | {
233 | "data": {
234 | "text/plain": [
235 | "<__main__.DistanceBand at 0x117d18c90>"
236 | ]
237 | },
238 | "execution_count": 24,
239 | "metadata": {},
240 | "output_type": "execute_result"
241 | }
242 | ],
243 | "source": [
244 | "%time Distance.DistanceBand(tree, threshold=500, alpha=-1.5, binary=True)\n",
245 | "%time DistanceBand(tree, threshold=500, alpha=-1.5, binary=True, build_sp=False)"
246 | ]
247 | },
248 | {
249 | "cell_type": "code",
250 | "execution_count": 25,
251 | "metadata": {
252 | "collapsed": false,
253 | "jupyter": {
254 | "outputs_hidden": false
255 | }
256 | },
257 | "outputs": [
258 | {
259 | "name": "stdout",
260 | "output_type": "stream",
261 | "text": [
262 | "CPU times: user 1.28 s, sys: 44 ms, total: 1.32 s\n",
263 | "Wall time: 1.3 s\n",
264 | "CPU times: user 199 ms, sys: 10.9 ms, total: 210 ms\n",
265 | "Wall time: 210 ms\n"
266 | ]
267 | },
268 | {
269 | "data": {
270 | "text/plain": [
271 | "<__main__.DistanceBand at 0x117d18a10>"
272 | ]
273 | },
274 | "execution_count": 25,
275 | "metadata": {},
276 | "output_type": "execute_result"
277 | }
278 | ],
279 | "source": [
280 | "%time Distance.DistanceBand(tree, threshold=500, alpha=-1.5, binary=False)\n",
281 | "%time DistanceBand(tree, threshold=500, alpha=-1.5, binary=False, build_sp=True)"
282 | ]
283 | },
284 | {
285 | "cell_type": "code",
286 | "execution_count": 26,
287 | "metadata": {
288 | "collapsed": false,
289 | "jupyter": {
290 | "outputs_hidden": false
291 | }
292 | },
293 | "outputs": [
294 | {
295 | "name": "stdout",
296 | "output_type": "stream",
297 | "text": [
298 | "CPU times: user 1.5 s, sys: 46.3 ms, total: 1.54 s\n",
299 | "Wall time: 1.53 s\n",
300 | "CPU times: user 67.1 ms, sys: 5.1 ms, total: 72.2 ms\n",
301 | "Wall time: 72.2 ms\n"
302 | ]
303 | },
304 | {
305 | "data": {
306 | "text/plain": [
307 | "<__main__.DistanceBand at 0x117d18e90>"
308 | ]
309 | },
310 | "execution_count": 26,
311 | "metadata": {},
312 | "output_type": "execute_result"
313 | }
314 | ],
315 | "source": [
316 | "%time Distance.DistanceBand(tree, threshold=500, alpha=-1.5, binary=False)\n",
317 | "%time DistanceBand(tree, threshold=500, alpha=-1.5, binary=False, build_sp=False)"
318 | ]
319 | },
320 | {
321 | "cell_type": "code",
322 | "execution_count": null,
323 | "metadata": {
324 | "collapsed": true,
325 | "jupyter": {
326 | "outputs_hidden": true
327 | }
328 | },
329 | "outputs": [],
330 | "source": []
331 | },
332 | {
333 | "cell_type": "code",
334 | "execution_count": null,
335 | "metadata": {
336 | "collapsed": true,
337 | "jupyter": {
338 | "outputs_hidden": true
339 | }
340 | },
341 | "outputs": [],
342 | "source": []
343 | }
344 | ],
345 | "metadata": {
346 | "anaconda-cloud": {},
347 | "kernelspec": {
348 | "display_name": "Python 3",
349 | "language": "python",
350 | "name": "python3"
351 | },
352 | "language_info": {
353 | "codemirror_mode": {
354 | "name": "ipython",
355 | "version": 3
356 | },
357 | "file_extension": ".py",
358 | "mimetype": "text/x-python",
359 | "name": "python",
360 | "nbconvert_exporter": "python",
361 | "pygments_lexer": "ipython3",
362 | "version": "3.9.4"
363 | }
364 | },
365 | "nbformat": 4,
366 | "nbformat_minor": 4
367 | }
368 |
--------------------------------------------------------------------------------
/notebooks/ODW_example.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 4,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import sys\n",
12 | "sys.path.append('/Users/toshan/dev/pysal/pysal/weights')\n",
13 | "from spintW import ODW\n",
14 | "import pysal as ps"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {},
20 | "source": [
21 | "# With an equal number of origins and destinations (n=16)"
22 | ]
23 | },
24 | {
25 | "cell_type": "code",
26 | "execution_count": 33,
27 | "metadata": {
28 | "collapsed": true
29 | },
30 | "outputs": [],
31 | "source": [
32 | "origins = ps.weights.lat2W(4,4)\n",
33 | "dests = ps.weights.lat2W(4,4)"
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": 34,
39 | "metadata": {
40 | "collapsed": false
41 | },
42 | "outputs": [
43 | {
44 | "data": {
45 | "text/plain": [
46 | "16"
47 | ]
48 | },
49 | "execution_count": 34,
50 | "metadata": {},
51 | "output_type": "execute_result"
52 | }
53 | ],
54 | "source": [
55 | "origins.n"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": 35,
61 | "metadata": {
62 | "collapsed": false
63 | },
64 | "outputs": [
65 | {
66 | "data": {
67 | "text/plain": [
68 | "16"
69 | ]
70 | },
71 | "execution_count": 35,
72 | "metadata": {},
73 | "output_type": "execute_result"
74 | }
75 | ],
76 | "source": [
77 | "dests.n"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": 36,
83 | "metadata": {
84 | "collapsed": true
85 | },
86 | "outputs": [],
87 | "source": [
88 | "ODw = ODW(origins, dests)"
89 | ]
90 | },
91 | {
92 | "cell_type": "code",
93 | "execution_count": 37,
94 | "metadata": {
95 | "collapsed": false
96 | },
97 | "outputs": [
98 | {
99 | "name": "stdout",
100 | "output_type": "stream",
101 | "text": [
102 | "256 256\n"
103 | ]
104 | }
105 | ],
106 | "source": [
107 | "print ODw.n, 16*16"
108 | ]
109 | },
110 | {
111 | "cell_type": "code",
112 | "execution_count": 38,
113 | "metadata": {
114 | "collapsed": false
115 | },
116 | "outputs": [
117 | {
118 | "data": {
119 | "text/plain": [
120 | "(256, 256)"
121 | ]
122 | },
123 | "execution_count": 38,
124 | "metadata": {},
125 | "output_type": "execute_result"
126 | }
127 | ],
128 | "source": [
129 | "ODw.full()[0].shape"
130 | ]
131 | },
132 | {
133 | "cell_type": "markdown",
134 | "metadata": {},
135 | "source": [
136 | " # With non-equal number of origins (n=9) and destinations (m=25)"
137 | ]
138 | },
139 | {
140 | "cell_type": "code",
141 | "execution_count": 39,
142 | "metadata": {
143 | "collapsed": true
144 | },
145 | "outputs": [],
146 | "source": [
147 | "origins = ps.weights.lat2W(3,3)"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": 40,
153 | "metadata": {
154 | "collapsed": true
155 | },
156 | "outputs": [],
157 | "source": [
158 | "dests = ps.weights.lat2W(5,5)"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 41,
164 | "metadata": {
165 | "collapsed": false
166 | },
167 | "outputs": [
168 | {
169 | "data": {
170 | "text/plain": [
171 | "9"
172 | ]
173 | },
174 | "execution_count": 41,
175 | "metadata": {},
176 | "output_type": "execute_result"
177 | }
178 | ],
179 | "source": [
180 | "origins.n"
181 | ]
182 | },
183 | {
184 | "cell_type": "code",
185 | "execution_count": 42,
186 | "metadata": {
187 | "collapsed": false
188 | },
189 | "outputs": [
190 | {
191 | "data": {
192 | "text/plain": [
193 | "25"
194 | ]
195 | },
196 | "execution_count": 42,
197 | "metadata": {},
198 | "output_type": "execute_result"
199 | }
200 | ],
201 | "source": [
202 | "dests.n"
203 | ]
204 | },
205 | {
206 | "cell_type": "code",
207 | "execution_count": 43,
208 | "metadata": {
209 | "collapsed": true
210 | },
211 | "outputs": [],
212 | "source": [
213 | "ODw = ODW(origins, dests)"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": 44,
219 | "metadata": {
220 | "collapsed": false
221 | },
222 | "outputs": [
223 | {
224 | "name": "stdout",
225 | "output_type": "stream",
226 | "text": [
227 | "225 225\n"
228 | ]
229 | }
230 | ],
231 | "source": [
232 | "print ODw.n, 9*25"
233 | ]
234 | },
235 | {
236 | "cell_type": "code",
237 | "execution_count": 45,
238 | "metadata": {
239 | "collapsed": false
240 | },
241 | "outputs": [
242 | {
243 | "data": {
244 | "text/plain": [
245 | "(225, 225)"
246 | ]
247 | },
248 | "execution_count": 45,
249 | "metadata": {},
250 | "output_type": "execute_result"
251 | }
252 | ],
253 | "source": [
254 | "ODw.full()[0].shape"
255 | ]
256 | },
257 | {
258 | "cell_type": "code",
259 | "execution_count": null,
260 | "metadata": {
261 | "collapsed": true
262 | },
263 | "outputs": [],
264 | "source": []
265 | }
266 | ],
267 | "metadata": {
268 | "kernelspec": {
269 | "display_name": "Python [Root]",
270 | "language": "python",
271 | "name": "Python [Root]"
272 | },
273 | "language_info": {
274 | "codemirror_mode": {
275 | "name": "ipython",
276 | "version": 2
277 | },
278 | "file_extension": ".py",
279 | "mimetype": "text/x-python",
280 | "name": "python",
281 | "nbconvert_exporter": "python",
282 | "pygments_lexer": "ipython2",
283 | "version": "2.7.12"
284 | }
285 | },
286 | "nbformat": 4,
287 | "nbformat_minor": 0
288 | }
289 |
--------------------------------------------------------------------------------
/notebooks/OD_weights.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import pysal as ps\n",
12 | "from pysal import weights as w\n",
13 | "import numpy as np\n",
14 | "import scipy.sparse as sp"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "metadata": {
21 | "collapsed": false
22 | },
23 | "outputs": [],
24 | "source": [
25 | "\n",
26 | "def OD(Wo, Wd):\n",
27 | " Wo = Wo.sparse\n",
28 | " Wd = Wd.sparse\n",
29 | " Ww = sp.kron(Wo, Wd)\n",
30 | " return w.WSP2W(w.WSP(Ww))"
31 | ]
32 | },
33 | {
34 | "cell_type": "code",
35 | "execution_count": 7,
36 | "metadata": {
37 | "collapsed": false
38 | },
39 | "outputs": [
40 | {
41 | "name": "stdout",
42 | "output_type": "stream",
43 | "text": [
44 | "(256, 256)\n"
45 | ]
46 | }
47 | ],
48 | "source": [
49 | "origins = ps.weights.lat2W(4,4)\n",
50 | "dests = ps.weights.lat2W(4,4)\n",
51 | "Ww = OD(origins, dests)\n",
52 | "Ww.transform = 'r'\n",
53 | "print Ww.full()[0].shape"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 4,
59 | "metadata": {
60 | "collapsed": false
61 | },
62 | "outputs": [
63 | {
64 | "name": "stdout",
65 | "output_type": "stream",
66 | "text": [
67 | "[[ 0]\n",
68 | " [38]\n",
69 | " [36]\n",
70 | " [86]\n",
71 | " [30]\n",
72 | " [ 0]\n",
73 | " [69]\n",
74 | " [19]\n",
75 | " [84]\n",
76 | " [43]\n",
77 | " [ 0]\n",
78 | " [80]\n",
79 | " [58]\n",
80 | " [ 3]\n",
81 | " [35]\n",
82 | " [ 0]]\n",
83 | "[[ 28. ]\n",
84 | " [ 53.25]\n",
85 | " [ 53.25]\n",
86 | " [ 28. ]\n",
87 | " [ 28. ]\n",
88 | " [ 36. ]\n",
89 | " [ 36. ]\n",
90 | " [ 28. ]\n",
91 | " [ 28. ]\n",
92 | " [ 36. ]\n",
93 | " [ 36. ]\n",
94 | " [ 28. ]\n",
95 | " [ 28. ]\n",
96 | " [ 53.25]\n",
97 | " [ 53.25]\n",
98 | " [ 28. ]]\n"
99 | ]
100 | }
101 | ],
102 | "source": [
103 | "flows = np.random.randint(0,100, (4,4))\n",
104 | "np.fill_diagonal(flows, 0)\n",
105 | "flows = flows.reshape((16,1))\n",
106 | "print flows\n",
107 | "slag = ps.lag_spatial(Ww, flows)\n",
108 | "print slag"
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": 5,
114 | "metadata": {
115 | "collapsed": false
116 | },
117 | "outputs": [
118 | {
119 | "data": {
120 | "text/plain": [
121 | "{0: [1.0, 1.0], 1: [1.0, 1.0], 2: [1.0, 1.0], 3: [1.0, 1.0]}"
122 | ]
123 | },
124 | "execution_count": 5,
125 | "metadata": {},
126 | "output_type": "execute_result"
127 | }
128 | ],
129 | "source": [
130 | "origins.weights"
131 | ]
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": 6,
136 | "metadata": {
137 | "collapsed": false
138 | },
139 | "outputs": [],
140 | "source": [
141 | "import os\n",
142 | "os.chdir('/Users/toshan/dev/pysal/pysal/weights')\n",
143 | "from spintW import ODW"
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": 16,
149 | "metadata": {
150 | "collapsed": false,
151 | "scrolled": true
152 | },
153 | "outputs": [],
154 | "source": [
155 | "origins = ps.weights.lat2W(2,2)\n",
156 | "dests = ps.weights.lat2W(2,2)\n",
157 | "Ww = ODW(origins, dests)"
158 | ]
159 | },
160 | {
161 | "cell_type": "code",
162 | "execution_count": 17,
163 | "metadata": {
164 | "collapsed": false
165 | },
166 | "outputs": [
167 | {
168 | "data": {
169 | "text/plain": [
170 | "array([[ 0. , 0. , 0. , 0. , 0. , 0.25, 0.25, 0. , 0. ,\n",
171 | " 0.25, 0.25, 0. , 0. , 0. , 0. , 0. ],\n",
172 | " [ 0. , 0. , 0. , 0. , 0.25, 0. , 0. , 0.25, 0.25,\n",
173 | " 0. , 0. , 0.25, 0. , 0. , 0. , 0. ],\n",
174 | " [ 0. , 0. , 0. , 0. , 0.25, 0. , 0. , 0.25, 0.25,\n",
175 | " 0. , 0. , 0.25, 0. , 0. , 0. , 0. ],\n",
176 | " [ 0. , 0. , 0. , 0. , 0. , 0.25, 0.25, 0. , 0. ,\n",
177 | " 0.25, 0.25, 0. , 0. , 0. , 0. , 0. ],\n",
178 | " [ 0. , 0.25, 0.25, 0. , 0. , 0. , 0. , 0. , 0. ,\n",
179 | " 0. , 0. , 0. , 0. , 0.25, 0.25, 0. ],\n",
180 | " [ 0.25, 0. , 0. , 0.25, 0. , 0. , 0. , 0. , 0. ,\n",
181 | " 0. , 0. , 0. , 0.25, 0. , 0. , 0.25],\n",
182 | " [ 0.25, 0. , 0. , 0.25, 0. , 0. , 0. , 0. , 0. ,\n",
183 | " 0. , 0. , 0. , 0.25, 0. , 0. , 0.25],\n",
184 | " [ 0. , 0.25, 0.25, 0. , 0. , 0. , 0. , 0. , 0. ,\n",
185 | " 0. , 0. , 0. , 0. , 0.25, 0.25, 0. ],\n",
186 | " [ 0. , 0.25, 0.25, 0. , 0. , 0. , 0. , 0. , 0. ,\n",
187 | " 0. , 0. , 0. , 0. , 0.25, 0.25, 0. ],\n",
188 | " [ 0.25, 0. , 0. , 0.25, 0. , 0. , 0. , 0. , 0. ,\n",
189 | " 0. , 0. , 0. , 0.25, 0. , 0. , 0.25],\n",
190 | " [ 0.25, 0. , 0. , 0.25, 0. , 0. , 0. , 0. , 0. ,\n",
191 | " 0. , 0. , 0. , 0.25, 0. , 0. , 0.25],\n",
192 | " [ 0. , 0.25, 0.25, 0. , 0. , 0. , 0. , 0. , 0. ,\n",
193 | " 0. , 0. , 0. , 0. , 0.25, 0.25, 0. ],\n",
194 | " [ 0. , 0. , 0. , 0. , 0. , 0.25, 0.25, 0. , 0. ,\n",
195 | " 0.25, 0.25, 0. , 0. , 0. , 0. , 0. ],\n",
196 | " [ 0. , 0. , 0. , 0. , 0.25, 0. , 0. , 0.25, 0.25,\n",
197 | " 0. , 0. , 0.25, 0. , 0. , 0. , 0. ],\n",
198 | " [ 0. , 0. , 0. , 0. , 0.25, 0. , 0. , 0.25, 0.25,\n",
199 | " 0. , 0. , 0.25, 0. , 0. , 0. , 0. ],\n",
200 | " [ 0. , 0. , 0. , 0. , 0. , 0.25, 0.25, 0. , 0. ,\n",
201 | " 0.25, 0.25, 0. , 0. , 0. , 0. , 0. ]])"
202 | ]
203 | },
204 | "execution_count": 17,
205 | "metadata": {},
206 | "output_type": "execute_result"
207 | }
208 | ],
209 | "source": [
210 | "Ww.full()[0]"
211 | ]
212 | },
213 | {
214 | "cell_type": "code",
215 | "execution_count": null,
216 | "metadata": {
217 | "collapsed": true
218 | },
219 | "outputs": [],
220 | "source": []
221 | },
222 | {
223 | "cell_type": "code",
224 | "execution_count": null,
225 | "metadata": {
226 | "collapsed": true
227 | },
228 | "outputs": [],
229 | "source": []
230 | }
231 | ],
232 | "metadata": {
233 | "anaconda-cloud": {},
234 | "kernelspec": {
235 | "display_name": "Python [Root]",
236 | "language": "python",
237 | "name": "Python [Root]"
238 | },
239 | "language_info": {
240 | "codemirror_mode": {
241 | "name": "ipython",
242 | "version": 2
243 | },
244 | "file_extension": ".py",
245 | "mimetype": "text/x-python",
246 | "name": "python",
247 | "nbconvert_exporter": "python",
248 | "pygments_lexer": "ipython2",
249 | "version": "2.7.12"
250 | }
251 | },
252 | "nbformat": 4,
253 | "nbformat_minor": 0
254 | }
255 |
--------------------------------------------------------------------------------
/notebooks/autograd_test.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 11,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import pandas as pd\n",
12 | "import scipy.optimize as sc\n",
13 | "import autograd.numpy as np\n",
14 | "import autograd\n",
15 | "from autograd.convenience_wrappers import multigrad\n",
16 | "import scipy.sparse"
17 | ]
18 | },
19 | {
20 | "cell_type": "code",
21 | "execution_count": 12,
22 | "metadata": {
23 | "collapsed": true
24 | },
25 | "outputs": [],
26 | "source": [
27 | "austria = pd.read_csv('http://dl.dropbox.com/u/8649795/AT_Austria.csv')\n",
28 | "austria = austria[austria['Origin'] != austria['Destination']]\n",
29 | "f = np.reshape(austria['Data'].values, (-1,1))\n",
30 | "o = austria['Origin'].values\n",
31 | "d = austria['Destination'].values\n",
32 | "dij = np.reshape(austria['Dij'].values, (-1,1))\n",
33 | "o_vars = np.reshape(austria['Oi2007'].values, (-1,1))\n",
34 | "d_vars = np.reshape(austria['Dj2007'].values, (-1,1))\n",
35 | "dij = np.reshape(austria['Dij'].values, (-1,1))\n",
36 | "o_vars = np.reshape(austria['Oi2007'].values, (-1,1))\n",
37 | "d_vars = np.reshape(austria['Dj2007'].values, (-1,1))"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": 13,
43 | "metadata": {
44 | "collapsed": true
45 | },
46 | "outputs": [],
47 | "source": [
48 | "def newton(f, x0):\n",
49 | " # wrap scipy.optimize.newton with our automatic derivatives\n",
50 | " params = sc.fsolve(f, x0)\n",
51 | " return params\n",
52 | "\n",
53 | "def poiss_loglike(mu, sig, ep, x, inputs):\n",
54 | " a,b,c = inputs[:,0], inputs[:,1], inputs[:,2]\n",
55 | " predict = sig*a + ep*b + mu*c\n",
56 | " predict = np.reshape(predict, (-1,1))\n",
57 | " return -np.sum(x*np.log(predict)-predict)\n",
58 | "\n",
59 | "#def loglike(mu, k, x, inputs):\n",
60 | " #return np.sum(poiss_loglike(mu, k, x, inputs))\n",
61 | "\n",
62 | "\n",
63 | "def fit_maxlike(x, inputs, mu_guess, o_guess, d_guess):\n",
64 | " prime = lambda p: multigrad(poiss_loglike, argnums=[0,1,2])(p[0], p[1], p[2], x, inputs)\n",
65 | " params = newton(prime, (mu_guess, o_guess, d_guess))\n",
66 | " return params"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": 15,
72 | "metadata": {
73 | "collapsed": false
74 | },
75 | "outputs": [
76 | {
77 | "name": "stdout",
78 | "output_type": "stream",
79 | "text": [
80 | "[-1.14993102 0.69084953 0.68523832]\n",
81 | "(-2.7430635540781623e-10, -2.5915536383536164e-10, -4.730811298259141e-10)\n"
82 | ]
83 | }
84 | ],
85 | "source": [
86 | "if __name__ == \"__main__\":\n",
87 | " \n",
88 | " x=np.log(f)\n",
89 | " inputs = np.hstack((np.log(o_vars), np.log(d_vars), np.log(dij)))\n",
90 | " params = fit_maxlike(x, inputs, mu_guess=0.0, o_guess=1.0, d_guess=1.0)\n",
91 | " print(params)\n",
92 | " \n",
93 | " prime = lambda p: multigrad(poiss_loglike, argnums=[0,1,2])(p[0], p[1], p[2], x, inputs)\n",
94 | " print(prime(params))"
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": null,
100 | "metadata": {
101 | "collapsed": true
102 | },
103 | "outputs": [],
104 | "source": []
105 | }
106 | ],
107 | "metadata": {
108 | "kernelspec": {
109 | "display_name": "Python 2",
110 | "language": "python",
111 | "name": "python2"
112 | },
113 | "language_info": {
114 | "codemirror_mode": {
115 | "name": "ipython",
116 | "version": 2
117 | },
118 | "file_extension": ".py",
119 | "mimetype": "text/x-python",
120 | "name": "python",
121 | "nbconvert_exporter": "python",
122 | "pygments_lexer": "ipython2",
123 | "version": "2.7.9"
124 | }
125 | },
126 | "nbformat": 4,
127 | "nbformat_minor": 0
128 | }
129 |
--------------------------------------------------------------------------------
/notebooks/dispersion_test.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 8,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import os\n",
12 | "os.chdir('/Users/toshan/dev/pysal/pysal/contrib/spint')\n",
13 | "from count_model import CountModel\n",
14 | "import numpy as np\n",
15 | "import pandas as pd\n",
16 | "from gravity import Gravity, Production, Attraction, Doubly, BaseGravity\n",
17 | "import statsmodels.formula.api as smf\n",
18 | "from statsmodels.api import families\n",
19 | "os.chdir('/Users/toshan/dev/pysal/pysal/contrib/glm')\n",
20 | "from glm import GLM\n",
21 | "from family import Poisson, QuasiPoisson\n",
22 | "\n",
23 | "import pysal\n",
24 | "import os\n",
25 | "os.chdir('/Users/toshan/dev/pysal/pysal/contrib/spint')\n",
26 | "from dispersion import alpha_disp, phi_disp\n",
27 | "\n"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": 2,
33 | "metadata": {
34 | "collapsed": false
35 | },
36 | "outputs": [],
37 | "source": [
38 | "rec = pd.read_csv('/Users/toshan/Documents/RecreationDemand.csv')"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 3,
44 | "metadata": {
45 | "collapsed": false
46 | },
47 | "outputs": [
48 | {
49 | "data": {
50 | "text/html": [
51 | "\n",
52 | "
\n",
53 | " \n",
54 | " \n",
55 | " | \n",
56 | " Unnamed: 0 | \n",
57 | " trips | \n",
58 | " quality | \n",
59 | " ski | \n",
60 | " income | \n",
61 | " userfee | \n",
62 | " costC | \n",
63 | " costS | \n",
64 | " costH | \n",
65 | "
\n",
66 | " \n",
67 | " \n",
68 | " \n",
69 | " 0 | \n",
70 | " 1 | \n",
71 | " 0 | \n",
72 | " 0 | \n",
73 | " yes | \n",
74 | " 4 | \n",
75 | " no | \n",
76 | " 67.59 | \n",
77 | " 68.620 | \n",
78 | " 76.800 | \n",
79 | "
\n",
80 | " \n",
81 | " 1 | \n",
82 | " 2 | \n",
83 | " 0 | \n",
84 | " 0 | \n",
85 | " no | \n",
86 | " 9 | \n",
87 | " no | \n",
88 | " 68.86 | \n",
89 | " 70.936 | \n",
90 | " 84.780 | \n",
91 | "
\n",
92 | " \n",
93 | " 2 | \n",
94 | " 3 | \n",
95 | " 0 | \n",
96 | " 0 | \n",
97 | " yes | \n",
98 | " 5 | \n",
99 | " no | \n",
100 | " 58.12 | \n",
101 | " 59.465 | \n",
102 | " 72.110 | \n",
103 | "
\n",
104 | " \n",
105 | " 3 | \n",
106 | " 4 | \n",
107 | " 0 | \n",
108 | " 0 | \n",
109 | " no | \n",
110 | " 2 | \n",
111 | " no | \n",
112 | " 15.79 | \n",
113 | " 13.750 | \n",
114 | " 23.680 | \n",
115 | "
\n",
116 | " \n",
117 | " 4 | \n",
118 | " 5 | \n",
119 | " 0 | \n",
120 | " 0 | \n",
121 | " yes | \n",
122 | " 3 | \n",
123 | " no | \n",
124 | " 24.02 | \n",
125 | " 34.033 | \n",
126 | " 34.547 | \n",
127 | "
\n",
128 | " \n",
129 | "
\n",
130 | "
"
131 | ],
132 | "text/plain": [
133 | " Unnamed: 0 trips quality ski income userfee costC costS costH\n",
134 | "0 1 0 0 yes 4 no 67.59 68.620 76.800\n",
135 | "1 2 0 0 no 9 no 68.86 70.936 84.780\n",
136 | "2 3 0 0 yes 5 no 58.12 59.465 72.110\n",
137 | "3 4 0 0 no 2 no 15.79 13.750 23.680\n",
138 | "4 5 0 0 yes 3 no 24.02 34.033 34.547"
139 | ]
140 | },
141 | "execution_count": 3,
142 | "metadata": {},
143 | "output_type": "execute_result"
144 | }
145 | ],
146 | "source": [
147 | "rec.head()"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": 4,
153 | "metadata": {
154 | "collapsed": true
155 | },
156 | "outputs": [],
157 | "source": [
158 | "y = rec['trips'].values.reshape((-1,1))"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 5,
164 | "metadata": {
165 | "collapsed": false
166 | },
167 | "outputs": [],
168 | "source": [
169 | "X = rec[['quality', 'income', 'costC', 'costS', 'costH']].values"
170 | ]
171 | },
172 | {
173 | "cell_type": "code",
174 | "execution_count": 22,
175 | "metadata": {
176 | "collapsed": false
177 | },
178 | "outputs": [],
179 | "source": [
180 | "test = CountModel(y, X, constant=False)"
181 | ]
182 | },
183 | {
184 | "cell_type": "code",
185 | "execution_count": 23,
186 | "metadata": {
187 | "collapsed": false
188 | },
189 | "outputs": [],
190 | "source": [
191 | "glm_results = test.fit(framework='glm')"
192 | ]
193 | },
194 | {
195 | "cell_type": "code",
196 | "execution_count": 24,
197 | "metadata": {
198 | "collapsed": false
199 | },
200 | "outputs": [
201 | {
202 | "data": {
203 | "text/plain": [
204 | "array([ 7.30811593e+00, 2.71035909e+00, 3.36051997e-03])"
205 | ]
206 | },
207 | "execution_count": 24,
208 | "metadata": {},
209 | "output_type": "execute_result"
210 | }
211 | ],
212 | "source": [
213 | "phi_disp(glm_results)"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": 26,
219 | "metadata": {
220 | "collapsed": false
221 | },
222 | "outputs": [
223 | {
224 | "data": {
225 | "text/plain": [
226 | "array([ 6.30811593e+00, 2.71035909e+00, 3.36051997e-03])"
227 | ]
228 | },
229 | "execution_count": 26,
230 | "metadata": {},
231 | "output_type": "execute_result"
232 | }
233 | ],
234 | "source": [
235 | "alpha_disp(glm_results)"
236 | ]
237 | },
238 | {
239 | "cell_type": "code",
240 | "execution_count": 27,
241 | "metadata": {
242 | "collapsed": false
243 | },
244 | "outputs": [
245 | {
246 | "data": {
247 | "text/plain": [
248 | "array([ 1.55402055e+00, 3.38253708e+00, 3.59097912e-04])"
249 | ]
250 | },
251 | "execution_count": 27,
252 | "metadata": {},
253 | "output_type": "execute_result"
254 | }
255 | ],
256 | "source": [
257 | "alpha_disp(glm_results, lambda x: x**2)"
258 | ]
259 | },
260 | {
261 | "cell_type": "code",
262 | "execution_count": 28,
263 | "metadata": {
264 | "collapsed": false
265 | },
266 | "outputs": [],
267 | "source": [
268 | "#Prepare some test data - columbus example\n",
269 | "db = pysal.open(pysal.examples.get_path('columbus.dbf'),'r')\n",
270 | "y = np.array(db.by_col(\"HOVAL\"))\n",
271 | "y = np.reshape(y, (49,1))\n",
272 | "X = []\n",
273 | "#X.append(np.ones(len(y)))\n",
274 | "X.append(db.by_col(\"INC\"))\n",
275 | "X.append(db.by_col(\"CRIME\"))\n",
276 | "X = np.array(X).T\n",
277 | "\n",
278 | "poisson_y = np.round(y).astype(int)"
279 | ]
280 | },
281 | {
282 | "cell_type": "code",
283 | "execution_count": 29,
284 | "metadata": {
285 | "collapsed": false
286 | },
287 | "outputs": [],
288 | "source": [
289 | "test = CountModel(poisson_y, X)"
290 | ]
291 | },
292 | {
293 | "cell_type": "code",
294 | "execution_count": 30,
295 | "metadata": {
296 | "collapsed": true
297 | },
298 | "outputs": [],
299 | "source": [
300 | "glm_results = test.fit(framework='glm')"
301 | ]
302 | },
303 | {
304 | "cell_type": "code",
305 | "execution_count": 31,
306 | "metadata": {
307 | "collapsed": false
308 | },
309 | "outputs": [
310 | {
311 | "data": {
312 | "text/plain": [
313 | "array([ 5.39968689, 2.3230411 , 0.01008847])"
314 | ]
315 | },
316 | "execution_count": 31,
317 | "metadata": {},
318 | "output_type": "execute_result"
319 | }
320 | ],
321 | "source": [
322 | "phi_disp(glm_results)"
323 | ]
324 | },
325 | {
326 | "cell_type": "code",
327 | "execution_count": 32,
328 | "metadata": {
329 | "collapsed": false
330 | },
331 | "outputs": [
332 | {
333 | "data": {
334 | "text/plain": [
335 | "array([ 4.39968689, 2.3230411 , 0.01008847])"
336 | ]
337 | },
338 | "execution_count": 32,
339 | "metadata": {},
340 | "output_type": "execute_result"
341 | }
342 | ],
343 | "source": [
344 | "alpha_disp(glm_results)"
345 | ]
346 | },
347 | {
348 | "cell_type": "code",
349 | "execution_count": 33,
350 | "metadata": {
351 | "collapsed": false
352 | },
353 | "outputs": [
354 | {
355 | "data": {
356 | "text/plain": [
357 | "array([ 0.10690133, 2.24709978, 0.01231683])"
358 | ]
359 | },
360 | "execution_count": 33,
361 | "metadata": {},
362 | "output_type": "execute_result"
363 | }
364 | ],
365 | "source": [
366 | "alpha_disp(glm_results, lambda x:x**2)"
367 | ]
368 | },
369 | {
370 | "cell_type": "code",
371 | "execution_count": 10,
372 | "metadata": {
373 | "collapsed": false
374 | },
375 | "outputs": [
376 | {
377 | "name": "stdout",
378 | "output_type": "stream",
379 | "text": [
380 | "\n",
381 | "\n",
382 | "\n"
383 | ]
384 | }
385 | ],
386 | "source": [
387 | "model1 = GLM(y, X, constant=False, family=Poisson()).fit()"
388 | ]
389 | },
390 | {
391 | "cell_type": "code",
392 | "execution_count": 11,
393 | "metadata": {
394 | "collapsed": false
395 | },
396 | "outputs": [
397 | {
398 | "name": "stdout",
399 | "output_type": "stream",
400 | "text": [
401 | "\n",
402 | "\n",
403 | "\n"
404 | ]
405 | }
406 | ],
407 | "source": [
408 | "model2 = GLM(y, X, constant=False, family=QuasiPoisson()).fit()"
409 | ]
410 | },
411 | {
412 | "cell_type": "code",
413 | "execution_count": 13,
414 | "metadata": {
415 | "collapsed": false
416 | },
417 | "outputs": [
418 | {
419 | "name": "stdout",
420 | "output_type": "stream",
421 | "text": [
422 | "1.0\n",
423 | "\n",
424 | "7.02573401193\n"
425 | ]
426 | }
427 | ],
428 | "source": [
429 | "print model1.scale\n",
430 | "print model2.scale"
431 | ]
432 | }
433 | ],
434 | "metadata": {
435 | "kernelspec": {
436 | "display_name": "Python 2",
437 | "language": "python",
438 | "name": "python2"
439 | },
440 | "language_info": {
441 | "codemirror_mode": {
442 | "name": "ipython",
443 | "version": 2
444 | },
445 | "file_extension": ".py",
446 | "mimetype": "text/x-python",
447 | "name": "python",
448 | "nbconvert_exporter": "python",
449 | "pygments_lexer": "ipython2",
450 | "version": "2.7.9"
451 | }
452 | },
453 | "nbformat": 4,
454 | "nbformat_minor": 0
455 | }
456 |
--------------------------------------------------------------------------------
/notebooks/glm_speed.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {
7 | "ExecuteTime": {
8 | "end_time": "2019-01-05T17:49:08.791636Z",
9 | "start_time": "2019-01-05T17:49:07.648966Z"
10 | }
11 | },
12 | "outputs": [],
13 | "source": [
14 | "import numpy as np\n",
15 | "import pandas as pd\n",
16 | "from spint.gravity import Gravity, Production, Attraction, Doubly, BaseGravity\n",
17 | "#from entropy import Unconstrained, ProductionConstrained, AttractionConstrained, DoublyConstrained\n",
18 | "import statsmodels.formula.api as smf\n",
19 | "from statsmodels.api import families\n",
20 | "import matplotlib.pyplot as plt\n",
21 | "%pylab inline\n",
22 | "\n",
23 | "import time \n",
24 | "\n",
25 | "def timeit(method):\n",
26 | "\n",
27 | " def timed(*args, **kw):\n",
28 | " ts = time.time()\n",
29 | " result = method(*args, **kw)\n",
30 | " te = time.time()\n",
31 | " elapsed = te-ts\n",
32 | " \n",
33 | " return result, elapsed\n",
34 | "\n",
35 | " return timed"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": null,
41 | "metadata": {
42 | "ExecuteTime": {
43 | "end_time": "2019-01-05T17:49:11.621267Z",
44 | "start_time": "2019-01-05T17:49:11.612565Z"
45 | }
46 | },
47 | "outputs": [],
48 | "source": [
49 | "@timeit\n",
50 | "def gravity(f ,o, d, o_vars, d_vars, dij, cost='exp', framework='glm'):\n",
51 | " results = Gravity(f, o_vars, d_vars, dij, cost, framework=framework)\n",
52 | " return results\n",
53 | " \n",
54 | "@timeit \n",
55 | "def production(f ,o, d, o_vars, d_vars, dij, cost='exp', framework='glm'):\n",
56 | " results = Production(f, o, d_vars, dij, 'exp', framework=framework)\n",
57 | " return results\n",
58 | "\n",
59 | "@timeit \n",
60 | "def attraction(f ,o, d, o_vars, d_vars, dij, cost='exp', framework='glm'):\n",
61 | " results = Attraction(f, d, o_vars, dij, 'exp', framework=framework)\n",
62 | " return results\n",
63 | "\n",
64 | "@timeit \n",
65 | "def doubly(f ,o, d, o_vars, d_vars, dij, cost='exp', framework='glm'):\n",
66 | " results = Doubly(f, o, d, dij, 'exp', framework=framework)\n",
67 | " return results\n",
68 | "\n"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "execution_count": null,
74 | "metadata": {
75 | "ExecuteTime": {
76 | "end_time": "2019-01-05T17:49:13.051717Z",
77 | "start_time": "2019-01-05T17:49:13.043400Z"
78 | }
79 | },
80 | "outputs": [],
81 | "source": [
82 | "def sim_data(n):\n",
83 | " o = np.tile(np.arange(n),n)\n",
84 | " d = np.repeat(np.arange(n),n)\n",
85 | " loc_size = np.random.randint(25000,500000, n)\n",
86 | " o_vars = np.tile(loc_size, n)\n",
87 | " d_vars = np.repeat(loc_size, n)\n",
88 | " dij = np.random.exponential(2500, n**2)\n",
89 | " f = o_vars**.3*d_vars**.4*np.exp(dij*-.00005)\n",
90 | " o = np.reshape(o, (-1,1))\n",
91 | " d = np.reshape(d, (-1,1))\n",
92 | " o_vars = np.reshape(o_vars, (-1,1))\n",
93 | " d_vars = np.reshape(d_vars, (-1,1))\n",
94 | " dij = np.reshape(dij, (-1,1))\n",
95 | " f = np.reshape(f, (-1,1))\n",
96 | " f = f.astype(np.int64)\n",
97 | " return f, o, d, o_vars, d_vars, dij\n"
98 | ]
99 | },
100 | {
101 | "cell_type": "code",
102 | "execution_count": null,
103 | "metadata": {
104 | "ExecuteTime": {
105 | "end_time": "2019-01-05T17:49:28.057547Z",
106 | "start_time": "2019-01-05T17:49:28.052351Z"
107 | }
108 | },
109 | "outputs": [],
110 | "source": [
111 | "def loop(func, start, stop, step, framework='glm'):\n",
112 | " results = []\n",
113 | " for n in np.arange(start, stop, step):\n",
114 | " f, o, d, o_vars, d_vars, dij = sim_data(n)\n",
115 | " out, elapsed = func(f, o, d, o_vars, d_vars, dij, 'exp', framework=framework)\n",
116 | " print(out.params[-2:])\n",
117 | " results.append(elapsed)\n",
118 | " return results"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": null,
124 | "metadata": {
125 | "ExecuteTime": {
126 | "end_time": "2019-01-05T17:49:33.184949Z",
127 | "start_time": "2019-01-05T17:49:30.182637Z"
128 | }
129 | },
130 | "outputs": [],
131 | "source": [
132 | "glm_grav = loop(gravity, 50, 250, 50)\n",
133 | "glm_prod = loop(production, 50, 250, 50)\n",
134 | "glm_att = loop(attraction, 50, 250, 50)\n",
135 | "glm_doub = loop(doubly, 50, 250, 50)"
136 | ]
137 | },
138 | {
139 | "cell_type": "code",
140 | "execution_count": null,
141 | "metadata": {
142 | "ExecuteTime": {
143 | "end_time": "2019-01-05T17:49:36.298895Z",
144 | "start_time": "2019-01-05T17:49:36.193100Z"
145 | }
146 | },
147 | "outputs": [],
148 | "source": [
149 | "smglm_grav = loop(gravity, 50, 250, 50, framework='sm_glm')\n",
150 | "smglm_prod = loop(production, 50, 250, 50, framework='sm_glm')\n",
151 | "smglm_att = loop(attraction, 50, 250, 50, framework='sm_glm')\n",
152 | "smglm_doub = loop(doubly, 50, 250, 50, framework='sm_glm')"
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": null,
158 | "metadata": {
159 | "ExecuteTime": {
160 | "end_time": "2019-01-05T17:49:51.262028Z",
161 | "start_time": "2019-01-05T17:49:51.258592Z"
162 | }
163 | },
164 | "outputs": [],
165 | "source": [
166 | "x = np.arange(50, 250, 50)"
167 | ]
168 | },
169 | {
170 | "cell_type": "code",
171 | "execution_count": null,
172 | "metadata": {
173 | "ExecuteTime": {
174 | "end_time": "2019-01-05T17:49:51.934219Z",
175 | "start_time": "2019-01-05T17:49:51.642595Z"
176 | },
177 | "scrolled": true
178 | },
179 | "outputs": [],
180 | "source": [
181 | "plt.plot(x, glm_grav, x, glm_prod, x, glm_att, x, glm_doub)\n",
182 | "plt.legend(('unconstrained', 'production', 'attraction', 'doubly'))\n",
183 | "plt.title('Custom GLM Framework')\n",
184 | "plt.xlabel('Sample Size')\n",
185 | "plt.ylabel('Seconds')"
186 | ]
187 | },
188 | {
189 | "cell_type": "code",
190 | "execution_count": null,
191 | "metadata": {
192 | "ExecuteTime": {
193 | "end_time": "2019-01-05T17:49:53.767784Z",
194 | "start_time": "2019-01-05T17:49:53.751473Z"
195 | }
196 | },
197 | "outputs": [],
198 | "source": [
199 | "plt.plot(x, smglm_grav, x, smglm_prod, x, smglm_att, x, smglm_doub)\n",
200 | "plt.legend(('unconstrained', 'production', 'attraction', 'doubly'))\n",
201 | "plt.legend(('unconstrained', 'production', 'attraction', 'doubly'))\n",
202 | "plt.title('Statsmodels GLM Framework')\n",
203 | "plt.xlabel('Sample Size')\n",
204 | "plt.ylabel('Seconds')"
205 | ]
206 | },
207 | {
208 | "cell_type": "code",
209 | "execution_count": null,
210 | "metadata": {},
211 | "outputs": [],
212 | "source": []
213 | },
214 | {
215 | "cell_type": "code",
216 | "execution_count": null,
217 | "metadata": {
218 | "ExecuteTime": {
219 | "end_time": "2019-01-05T17:50:02.265965Z",
220 | "start_time": "2019-01-05T17:50:02.181539Z"
221 | }
222 | },
223 | "outputs": [],
224 | "source": [
225 | "f, o, d, o_vars, d_vars, dij = sim_data(100)\n",
226 | "test = Production(f, o, d_vars, dij, 'exp')"
227 | ]
228 | },
229 | {
230 | "cell_type": "code",
231 | "execution_count": null,
232 | "metadata": {
233 | "ExecuteTime": {
234 | "end_time": "2019-01-05T17:50:03.122726Z",
235 | "start_time": "2019-01-05T17:50:03.117604Z"
236 | }
237 | },
238 | "outputs": [],
239 | "source": [
240 | "test."
241 | ]
242 | }
243 | ],
244 | "metadata": {
245 | "kernelspec": {
246 | "display_name": "Python [conda env:py3_spgh_dev]",
247 | "language": "python",
248 | "name": "conda-env-py3_spgh_dev-py"
249 | },
250 | "language_info": {
251 | "codemirror_mode": {
252 | "name": "ipython",
253 | "version": 3
254 | },
255 | "file_extension": ".py",
256 | "mimetype": "text/x-python",
257 | "name": "python",
258 | "nbconvert_exporter": "python",
259 | "pygments_lexer": "ipython3",
260 | "version": "3.6.6"
261 | }
262 | },
263 | "nbformat": 4,
264 | "nbformat_minor": 1
265 | }
266 |
--------------------------------------------------------------------------------
/notebooks/local_SI.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [
10 | {
11 | "name": "stdout",
12 | "output_type": "stream",
13 | "text": [
14 | "Populating the interactive namespace from numpy and matplotlib\n"
15 | ]
16 | }
17 | ],
18 | "source": [
19 | "import numpy as np\n",
20 | "import pandas as pd\n",
21 | "import os\n",
22 | "os.chdir('../')\n",
23 | "from gravity import Gravity, Production, Attraction, Doubly, BaseGravity\n",
24 | "import statsmodels.formula.api as smf\n",
25 | "from statsmodels.api import families\n",
26 | "import matplotlib.pyplot as plt\n",
27 | "%pylab inline"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": 2,
33 | "metadata": {
34 | "collapsed": true
35 | },
36 | "outputs": [],
37 | "source": [
38 | "austria = pd.read_csv('http://dl.dropbox.com/u/8649795/AT_Austria.csv')\n",
39 | "austria = austria[austria['Origin'] != austria['Destination']]\n",
40 | "f = austria['Data'].values\n",
41 | "o = austria['Origin'].values\n",
42 | "d = austria['Destination'].values\n",
43 | "dij = austria['Dij'].values\n",
44 | "o_vars = austria['Oi2007'].values\n",
45 | "d_vars = austria['Dj2007'].values"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": 37,
51 | "metadata": {
52 | "collapsed": false
53 | },
54 | "outputs": [
55 | {
56 | "name": "stdout",
57 | "output_type": "stream",
58 | "text": [
59 | "-0.00976746026969\n"
60 | ]
61 | }
62 | ],
63 | "source": [
64 | "model = Gravity(f, o_vars, d_vars, dij, 'exp')\n",
65 | "print model.params[-1]"
66 | ]
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": 39,
71 | "metadata": {
72 | "collapsed": false
73 | },
74 | "outputs": [
75 | {
76 | "data": {
77 | "text/plain": [
78 | "[-0.01699776161094757,\n",
79 | " -0.0053210259160796358,\n",
80 | " -0.0028594272276957211,\n",
81 | " -0.006533037784217155,\n",
82 | " -0.0024666647861060209,\n",
83 | " -0.0058258251130860472,\n",
84 | " -0.010739622617965516,\n",
85 | " -0.0046867791898773659,\n",
86 | " -0.0065940756391066335]"
87 | ]
88 | },
89 | "execution_count": 39,
90 | "metadata": {},
91 | "output_type": "execute_result"
92 | }
93 | ],
94 | "source": [
95 | "local = model.local(loc_index=o, locs=np.unique(o))\n",
96 | "local['param2']"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 41,
102 | "metadata": {
103 | "collapsed": false
104 | },
105 | "outputs": [
106 | {
107 | "name": "stdout",
108 | "output_type": "stream",
109 | "text": [
110 | "-0.00727113391179\n"
111 | ]
112 | }
113 | ],
114 | "source": [
115 | "model = Production(f, o, d_vars, dij, 'exp')\n",
116 | "print model.params[-1]"
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": 42,
122 | "metadata": {
123 | "collapsed": false
124 | },
125 | "outputs": [
126 | {
127 | "data": {
128 | "text/plain": [
129 | "[-0.016997761610949791,\n",
130 | " -0.005321025916080413,\n",
131 | " -0.0028594272276953325,\n",
132 | " -0.0065330377842177101,\n",
133 | " -0.0024666647861060209,\n",
134 | " -0.0058258251130863803,\n",
135 | " -0.010739622617965183,\n",
136 | " -0.0046867791898770328,\n",
137 | " -0.0065940756391070776]"
138 | ]
139 | },
140 | "execution_count": 42,
141 | "metadata": {},
142 | "output_type": "execute_result"
143 | }
144 | ],
145 | "source": [
146 | "local = model.local()\n",
147 | "local['param2']"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": 43,
153 | "metadata": {
154 | "collapsed": false
155 | },
156 | "outputs": [
157 | {
158 | "name": "stdout",
159 | "output_type": "stream",
160 | "text": [
161 | "-0.00693754909526\n"
162 | ]
163 | }
164 | ],
165 | "source": [
166 | "model = Attraction(f, d, o_vars, dij, 'exp')\n",
167 | "print model.params[-1]"
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "execution_count": 44,
173 | "metadata": {
174 | "collapsed": false
175 | },
176 | "outputs": [
177 | {
178 | "data": {
179 | "text/plain": [
180 | "[-0.010872636479707154,\n",
181 | " -0.0054690202130680543,\n",
182 | " -0.0025567421332022833,\n",
183 | " -0.0051439340488994012,\n",
184 | " -0.0036020461535491433,\n",
185 | " -0.010088935906795271,\n",
186 | " -0.012926843651020203,\n",
187 | " -0.0075750287063747201,\n",
188 | " -0.0081576735088411123]"
189 | ]
190 | },
191 | "execution_count": 44,
192 | "metadata": {},
193 | "output_type": "execute_result"
194 | }
195 | ],
196 | "source": [
197 | "local = model.local()\n",
198 | "local['param2']"
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "execution_count": null,
204 | "metadata": {
205 | "collapsed": true
206 | },
207 | "outputs": [],
208 | "source": []
209 | }
210 | ],
211 | "metadata": {
212 | "kernelspec": {
213 | "display_name": "Python 2",
214 | "language": "python",
215 | "name": "python2"
216 | },
217 | "language_info": {
218 | "codemirror_mode": {
219 | "name": "ipython",
220 | "version": 2
221 | },
222 | "file_extension": ".py",
223 | "mimetype": "text/x-python",
224 | "name": "python",
225 | "nbconvert_exporter": "python",
226 | "pygments_lexer": "ipython2",
227 | "version": "2.7.9"
228 | }
229 | },
230 | "nbformat": 4,
231 | "nbformat_minor": 0
232 | }
233 |
--------------------------------------------------------------------------------
/notebooks/netW.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import numpy as np\n",
12 | "import os\n",
13 | "os.chdir('/Users/toshan/dev/pysal/pysal/weights')\n",
14 | "from spintW import netW, mat2L"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "metadata": {
21 | "collapsed": true
22 | },
23 | "outputs": [],
24 | "source": [
25 | "link_list = [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'a'), ('b', 'c'), ('b', 'd'), ('c', 'a'), ('c', 'b'), ('c', 'd'), ('d', 'a'), ('d', 'b'), ('d', 'c')]"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 3,
31 | "metadata": {
32 | "collapsed": false
33 | },
34 | "outputs": [
35 | {
36 | "data": {
37 | "text/plain": [
38 | "array([[ 0., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1., 0.],\n",
39 | " [ 1., 0., 1., 1., 1., 0., 1., 1., 1., 1., 0., 1.],\n",
40 | " [ 1., 1., 0., 1., 0., 1., 1., 0., 1., 1., 1., 1.],\n",
41 | " [ 1., 1., 1., 0., 1., 1., 1., 1., 0., 1., 1., 0.],\n",
42 | " [ 1., 1., 0., 1., 0., 1., 1., 1., 1., 0., 1., 1.],\n",
43 | " [ 1., 0., 1., 1., 1., 0., 0., 1., 1., 1., 1., 1.],\n",
44 | " [ 1., 1., 1., 1., 1., 0., 0., 1., 1., 1., 0., 1.],\n",
45 | " [ 1., 1., 0., 1., 1., 1., 1., 0., 1., 0., 1., 1.],\n",
46 | " [ 0., 1., 1., 0., 1., 1., 1., 1., 0., 1., 1., 1.],\n",
47 | " [ 1., 1., 1., 1., 0., 1., 1., 0., 1., 0., 1., 1.],\n",
48 | " [ 1., 0., 1., 1., 1., 1., 0., 1., 1., 1., 0., 1.],\n",
49 | " [ 0., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 0.]])"
50 | ]
51 | },
52 | "execution_count": 3,
53 | "metadata": {},
54 | "output_type": "execute_result"
55 | }
56 | ],
57 | "source": [
58 | "w = netW(link_list)\n",
59 | "w.full()[0]"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": 4,
65 | "metadata": {
66 | "collapsed": false
67 | },
68 | "outputs": [
69 | {
70 | "data": {
71 | "text/plain": [
72 | "array([[ 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
73 | " [ 1., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
74 | " [ 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
75 | " [ 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0.],\n",
76 | " [ 0., 0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
77 | " [ 0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
78 | " [ 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0.],\n",
79 | " [ 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 0.],\n",
80 | " [ 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.],\n",
81 | " [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.],\n",
82 | " [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 1.],\n",
83 | " [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0.]])"
84 | ]
85 | },
86 | "execution_count": 4,
87 | "metadata": {},
88 | "output_type": "execute_result"
89 | }
90 | ],
91 | "source": [
92 | "w = netW(link_list, share='O')\n",
93 | "w.full()[0]"
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": 5,
99 | "metadata": {
100 | "collapsed": false
101 | },
102 | "outputs": [
103 | {
104 | "data": {
105 | "text/plain": [
106 | "array([[ 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0.],\n",
107 | " [ 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1.],\n",
108 | " [ 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0.],\n",
109 | " [ 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0.],\n",
110 | " [ 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
111 | " [ 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
112 | " [ 0., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
113 | " [ 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
114 | " [ 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
115 | " [ 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
116 | " [ 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
117 | " [ 0., 1., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.]])"
118 | ]
119 | },
120 | "execution_count": 5,
121 | "metadata": {},
122 | "output_type": "execute_result"
123 | }
124 | ],
125 | "source": [
126 | "w = netW(link_list, share='D')\n",
127 | "w.full()[0]"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": 6,
133 | "metadata": {
134 | "collapsed": false
135 | },
136 | "outputs": [
137 | {
138 | "data": {
139 | "text/plain": [
140 | "array([[ 0., 1., 1., 0., 0., 0., 0., 1., 0., 0., 1., 0.],\n",
141 | " [ 1., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 1.],\n",
142 | " [ 1., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0.],\n",
143 | " [ 0., 0., 0., 0., 1., 1., 1., 0., 0., 1., 0., 0.],\n",
144 | " [ 0., 1., 0., 1., 0., 1., 0., 0., 0., 0., 0., 1.],\n",
145 | " [ 0., 0., 1., 1., 1., 0., 0., 0., 1., 0., 0., 0.],\n",
146 | " [ 0., 0., 0., 1., 0., 0., 0., 1., 1., 1., 0., 0.],\n",
147 | " [ 1., 0., 0., 0., 0., 0., 1., 0., 1., 0., 1., 0.],\n",
148 | " [ 0., 0., 1., 0., 0., 1., 1., 1., 0., 0., 0., 0.],\n",
149 | " [ 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 1.],\n",
150 | " [ 1., 0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 1.],\n",
151 | " [ 0., 1., 0., 0., 1., 0., 0., 0., 0., 1., 1., 0.]])"
152 | ]
153 | },
154 | "execution_count": 6,
155 | "metadata": {},
156 | "output_type": "execute_result"
157 | }
158 | ],
159 | "source": [
160 | "w = netW(link_list, share='OD')\n",
161 | "w.full()[0]"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": 7,
167 | "metadata": {
168 | "collapsed": false
169 | },
170 | "outputs": [
171 | {
172 | "data": {
173 | "text/plain": [
174 | "array([[ 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0.],\n",
175 | " [ 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],\n",
176 | " [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.],\n",
177 | " [ 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
178 | " [ 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],\n",
179 | " [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.],\n",
180 | " [ 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
181 | " [ 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0.],\n",
182 | " [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.],\n",
183 | " [ 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
184 | " [ 0., 0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0.],\n",
185 | " [ 0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.]])"
186 | ]
187 | },
188 | "execution_count": 7,
189 | "metadata": {},
190 | "output_type": "execute_result"
191 | }
192 | ],
193 | "source": [
194 | "w = netW(link_list, share='C')\n",
195 | "w.full()[0]"
196 | ]
197 | },
198 | {
199 | "cell_type": "code",
200 | "execution_count": 8,
201 | "metadata": {
202 | "collapsed": false
203 | },
204 | "outputs": [
205 | {
206 | "data": {
207 | "text/plain": [
208 | "array([[0, 1, 1],\n",
209 | " [1, 0, 1],\n",
210 | " [1, 1, 0]])"
211 | ]
212 | },
213 | "execution_count": 8,
214 | "metadata": {},
215 | "output_type": "execute_result"
216 | }
217 | ],
218 | "source": [
219 | "mat = np.array([[0,1,1],[1,0,1],[1,1,0]])\n",
220 | "mat"
221 | ]
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": 11,
226 | "metadata": {
227 | "collapsed": false
228 | },
229 | "outputs": [
230 | {
231 | "data": {
232 | "text/plain": [
233 | "[(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]"
234 | ]
235 | },
236 | "execution_count": 11,
237 | "metadata": {},
238 | "output_type": "execute_result"
239 | }
240 | ],
241 | "source": [
242 | "adjL = mat2L(mat)\n",
243 | "adjL"
244 | ]
245 | },
246 | {
247 | "cell_type": "code",
248 | "execution_count": 10,
249 | "metadata": {
250 | "collapsed": false
251 | },
252 | "outputs": [
253 | {
254 | "data": {
255 | "text/plain": [
256 | "array([[ 0., 0., 1., 1., 0., 0.],\n",
257 | " [ 0., 0., 0., 0., 1., 1.],\n",
258 | " [ 1., 1., 0., 0., 0., 0.],\n",
259 | " [ 0., 0., 0., 0., 1., 1.],\n",
260 | " [ 1., 1., 0., 0., 0., 0.],\n",
261 | " [ 0., 0., 1., 1., 0., 0.]])"
262 | ]
263 | },
264 | "execution_count": 10,
265 | "metadata": {},
266 | "output_type": "execute_result"
267 | }
268 | ],
269 | "source": [
270 | "w = netW(adjL, share='C')\n",
271 | "w.full()[0]"
272 | ]
273 | },
274 | {
275 | "cell_type": "code",
276 | "execution_count": null,
277 | "metadata": {
278 | "collapsed": true
279 | },
280 | "outputs": [],
281 | "source": []
282 | }
283 | ],
284 | "metadata": {
285 | "kernelspec": {
286 | "display_name": "Python 2",
287 | "language": "python",
288 | "name": "python2"
289 | },
290 | "language_info": {
291 | "codemirror_mode": {
292 | "name": "ipython",
293 | "version": 2
294 | },
295 | "file_extension": ".py",
296 | "mimetype": "text/x-python",
297 | "name": "python",
298 | "nbconvert_exporter": "python",
299 | "pygments_lexer": "ipython2",
300 | "version": "2.7.9"
301 | }
302 | },
303 | "nbformat": 4,
304 | "nbformat_minor": 0
305 | }
306 |
--------------------------------------------------------------------------------
/notebooks/sparse_categorical.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import numpy as np\n",
12 | "from scipy import sparse as sp\n",
13 | "from statsmodels.tools.tools import categorical\n",
14 | "from datetime import datetime as dt\n"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "metadata": {
21 | "collapsed": true
22 | },
23 | "outputs": [],
24 | "source": [
25 | "def spcategorical(data):\n",
26 | " '''\n",
27 | " Returns a dummy matrix given an array of categorical variables.\n",
28 | " Parameters\n",
29 | " ----------\n",
30 | " data : array\n",
31 | " A 1d vector of the categorical variable.\n",
32 | "\n",
33 | " Returns\n",
34 | " --------\n",
35 | " dummy_matrix\n",
36 | " A sparse matrix of dummy (indicator/binary) float variables for the\n",
37 | " categorical data. \n",
38 | "\n",
39 | " '''\n",
40 | " if np.squeeze(data).ndim == 1:\n",
41 | " tmp_arr = np.unique(data)\n",
42 | " tmp_dummy = sp.csr_matrix((0, len(data)))\n",
43 | " for each in tmp_arr[:, None]:\n",
44 | " row = sp.csr_matrix((each == data).astype(float))\n",
45 | " tmp_dummy = sp.vstack([tmp_dummy, row])\n",
46 | " tmp_dummy = tmp_dummy.T\n",
47 | " return tmp_dummy\n",
48 | " else:\n",
49 | " raise IndexError(\"The index %s is not understood\" % col)\n"
50 | ]
51 | },
52 | {
53 | "cell_type": "code",
54 | "execution_count": 3,
55 | "metadata": {
56 | "collapsed": false
57 | },
58 | "outputs": [
59 | {
60 | "data": {
61 | "text/plain": [
62 | "True"
63 | ]
64 | },
65 | "execution_count": 3,
66 | "metadata": {},
67 | "output_type": "execute_result"
68 | }
69 | ],
70 | "source": [
71 | "data = np.random.randint(1,100, 10000)\n",
72 | "np.allclose(spcategorical(np.array(data)).toarray(), categorical(np.array(data), drop=True))"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "execution_count": 4,
78 | "metadata": {
79 | "collapsed": false
80 | },
81 | "outputs": [
82 | {
83 | "ename": "KeyboardInterrupt",
84 | "evalue": "",
85 | "output_type": "error",
86 | "traceback": [
87 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
88 | "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
89 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m3000\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mo\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtile\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mo_dums\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mspcategorical\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m3000\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0md\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
90 | "\u001b[0;32m\u001b[0m in \u001b[0;36mspcategorical\u001b[0;34m(data)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mtmp_dummy\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcsr_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0meach\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtmp_arr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mNone\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0mrow\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcsr_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0meach\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfloat\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0mtmp_dummy\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvstack\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mtmp_dummy\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrow\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0mtmp_dummy\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtmp_dummy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mT\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
91 | "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/sparse/compressed.pyc\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, arg1, shape, dtype, copy)\u001b[0m\n\u001b[1;32m 67\u001b[0m self.format)\n\u001b[1;32m 68\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mcoo\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mcoo_matrix\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 69\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_set_self\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoo_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 70\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 71\u001b[0m \u001b[0;31m# Read matrix dimensions given, if any\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
92 | "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/sparse/coo.pyc\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, arg1, shape, dtype, copy)\u001b[0m\n\u001b[1;32m 197\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 198\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 199\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrow\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcol\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnonzero\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 200\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mM\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrow\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcol\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 201\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhas_canonical_format\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
93 | "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
94 | ]
95 | }
96 | ],
97 | "source": [
98 | "s = dt.now()\n",
99 | "n = 3000\n",
100 | "o = np.tile(np.arange(n),n)\n",
101 | "o_dums = spcategorical(np.array(o))\n",
102 | "n = 3000\n",
103 | "d = np.repeat(np.arange(n),n)\n",
104 | "d_dums = spcategorical(np.array(d))\n",
105 | "sp.hstack((o_dums, d_dums))\n",
106 | "e = dt.now()\n",
107 | "print e-s"
108 | ]
109 | },
110 | {
111 | "cell_type": "code",
112 | "execution_count": 59,
113 | "metadata": {
114 | "collapsed": false
115 | },
116 | "outputs": [
117 | {
118 | "data": {
119 | "text/plain": [
120 | "<9000000x6000 sparse matrix of type ''\n",
121 | "\twith 18000000 stored elements in Compressed Sparse Column format>"
122 | ]
123 | },
124 | "execution_count": 59,
125 | "metadata": {},
126 | "output_type": "execute_result"
127 | }
128 | ],
129 | "source": [
130 | "all_dums = sp.hstack((o_dums, d_dums))\n",
131 | "all_dums"
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": 7,
137 | "metadata": {
138 | "collapsed": false
139 | },
140 | "outputs": [
141 | {
142 | "name": "stdout",
143 | "output_type": "stream",
144 | "text": [
145 | "(10000, 99)\n"
146 | ]
147 | }
148 | ],
149 | "source": [
150 | "print spcategorical(np.array(data)).toarray().shape"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "execution_count": null,
156 | "metadata": {
157 | "collapsed": true
158 | },
159 | "outputs": [],
160 | "source": []
161 | }
162 | ],
163 | "metadata": {
164 | "kernelspec": {
165 | "display_name": "Python 2",
166 | "language": "python",
167 | "name": "python2"
168 | },
169 | "language_info": {
170 | "codemirror_mode": {
171 | "name": "ipython",
172 | "version": 2
173 | },
174 | "file_extension": ".py",
175 | "mimetype": "text/x-python",
176 | "name": "python",
177 | "nbconvert_exporter": "python",
178 | "pygments_lexer": "ipython2",
179 | "version": "2.7.9"
180 | }
181 | },
182 | "nbformat": 4,
183 | "nbformat_minor": 0
184 | }
185 |
--------------------------------------------------------------------------------
/notebooks/sparse_categorical_bottleneck.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 2,
6 | "metadata": {
7 | "collapsed": true
8 | },
9 | "outputs": [],
10 | "source": [
11 | "from scipy import sparse as sp\n",
12 | "import numpy as np\n",
13 | "\n",
14 | "def spcategorical(n_cat_ids):\n",
15 | " '''\n",
16 | " Returns a dummy matrix given an array of categorical variables.\n",
17 | " Parameters\n",
18 | " ----------\n",
19 | " n_cat_ids : array\n",
20 | " A 1d vector of the categorical labels for n observations.\n",
21 | "\n",
22 | " Returns\n",
23 | " --------\n",
24 | " dummy : array\n",
25 | " A sparse matrix of dummy (indicator/binary) variables for the\n",
26 | " categorical data. \n",
27 | "\n",
28 | " '''\n",
29 | " if np.squeeze(n_cat_ids).ndim == 1:\n",
30 | " cat_set = np.unique(n_cat_ids)\n",
31 | " n = len(n_cat_ids)\n",
32 | " index = [np.where(cat_set == id)[0].tolist()[0] for id in n_cat_ids] #This list comprehension is likely \n",
33 | " print index #the most intense part of the algorithm\n",
34 | " indptr = np.arange(n+1, dtype=int) \n",
35 | " return sp.csr_matrix((np.ones(n), index, indptr))\n",
36 | " else:\n",
37 | " raise IndexError(\"The index %s is not understood\" % col)\n",
38 | "\n",
39 | "#If the variable, n_cat_ids, is already composed of integers and the integers are the n x 1 vector of\n",
40 | "#origins or destinations in OD pairs for which w ewant to build fixed effects then there is no need to \n",
41 | "#create the index variable, which probably takes the most time within this function. Instead n_cat_ids can\n",
42 | "#passed directly to the csr matrix constructor and some speed-ups can be achieved. In the case where the\n",
43 | "#origin/destination ids are not integers but are strings a speed-up may be possible by alterign the algorithm\n",
44 | "#so that the index is build in chunks (say each origin/destination) rather than for each row of of the n x 1\n",
45 | "#n_cat_ids array as is done in creating the index variable."
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "metadata": {
52 | "collapsed": true
53 | },
54 | "outputs": [],
55 | "source": []
56 | }
57 | ],
58 | "metadata": {
59 | "kernelspec": {
60 | "display_name": "Python 2",
61 | "language": "python",
62 | "name": "python2"
63 | },
64 | "language_info": {
65 | "codemirror_mode": {
66 | "name": "ipython",
67 | "version": 2
68 | },
69 | "file_extension": ".py",
70 | "mimetype": "text/x-python",
71 | "name": "python",
72 | "nbconvert_exporter": "python",
73 | "pygments_lexer": "ipython2",
74 | "version": "2.7.9"
75 | }
76 | },
77 | "nbformat": 4,
78 | "nbformat_minor": 0
79 | }
80 |
--------------------------------------------------------------------------------
/notebooks/sparse_scipy_optim.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 114,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "import pandas as pd\n",
12 | "import scipy.optimize as sc\n",
13 | "import scipy.sparse as sp"
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": 115,
19 | "metadata": {
20 | "collapsed": true
21 | },
22 | "outputs": [],
23 | "source": [
24 | "data = np.random.poisson(100, (10000,1))"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": 116,
30 | "metadata": {
31 | "collapsed": true
32 | },
33 | "outputs": [],
34 | "source": [
35 | "data = sp.csr_matrix(data)"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": 117,
41 | "metadata": {
42 | "collapsed": false
43 | },
44 | "outputs": [
45 | {
46 | "name": "stdout",
47 | "output_type": "stream",
48 | "text": [
49 | "[ 0.]\n",
50 | "[ 0.00025]\n",
51 | "[ 0.0005]\n",
52 | "[ 0.00075]\n",
53 | "[ 0.00125]\n",
54 | "[ 0.00175]\n",
55 | "[ 0.00275]\n",
56 | "[ 0.00375]\n",
57 | "[ 0.00575]\n",
58 | "[ 0.00775]\n",
59 | "[ 0.01175]\n",
60 | "[ 0.01575]\n",
61 | "[ 0.02375]\n",
62 | "[ 0.03175]\n",
63 | "[ 0.04775]\n",
64 | "[ 0.06375]\n",
65 | "[ 0.09575]\n",
66 | "[ 0.12775]\n",
67 | "[ 0.19175]\n",
68 | "[ 0.25575]\n",
69 | "[ 0.38375]\n",
70 | "[ 0.51175]\n",
71 | "[ 0.76775]\n",
72 | "[ 1.02375]\n",
73 | "[ 1.53575]\n",
74 | "[ 2.04775]\n",
75 | "[ 3.07175]\n",
76 | "[ 4.09575]\n",
77 | "[ 6.14375]\n",
78 | "[ 8.19175]\n",
79 | "[ 12.28775]\n",
80 | "[ 16.38375]\n",
81 | "[ 24.57575]\n",
82 | "[ 32.76775]\n",
83 | "[ 49.15175]\n",
84 | "[ 65.53575]\n",
85 | "[ 98.30375]\n",
86 | "[ 131.07175]\n",
87 | "[ 131.07175]\n",
88 | "[ 114.68775]\n",
89 | "[ 81.91975]\n",
90 | "[ 106.49575]\n",
91 | "[ 90.11175]\n",
92 | "[ 102.39975]\n",
93 | "[ 94.20775]\n",
94 | "[ 100.35175]\n",
95 | "[ 102.39975]\n",
96 | "[ 99.32775]\n",
97 | "[ 98.30375]\n",
98 | "[ 99.83975]\n",
99 | "[ 100.35175]\n",
100 | "[ 99.58375]\n",
101 | "[ 100.09575]\n",
102 | "[ 99.71175]\n",
103 | "[ 99.58375]\n",
104 | "[ 99.77575]\n",
105 | "[ 99.83975]\n",
106 | "[ 99.74375]\n",
107 | "[ 99.80775]\n",
108 | "[ 99.75975]\n",
109 | "[ 99.74375]\n",
110 | "[ 99.76775]\n",
111 | "[ 99.77575]\n",
112 | "[ 99.76375]\n",
113 | "[ 99.77175]\n",
114 | "[ 99.76575]\n",
115 | "[ 99.76975]\n",
116 | "[ 99.76675]\n",
117 | "[ 99.76875]\n",
118 | "[ 99.76725]\n",
119 | "[ 99.76825]\n",
120 | "[ 99.7675]\n",
121 | "[ 99.76725]\n",
122 | "[ 99.767625]\n",
123 | "[ 99.76775]\n",
124 | "[ 99.7675625]\n",
125 | "Optimization terminated successfully.\n",
126 | " Current function value: -3594470.473058\n",
127 | " Iterations: 38\n",
128 | " Function evaluations: 76\n",
129 | "[ 99.767625]\n"
130 | ]
131 | }
132 | ],
133 | "source": [
134 | "def poiss_loglike(x, data, a):\n",
135 | " print x\n",
136 | " return -np.sum(data*np.log(x)-x)*a\n",
137 | "\n",
138 | "\n",
139 | "params = sc.fmin(poiss_loglike, 0, args=(data ,1))\n",
140 | "print params"
141 | ]
142 | }
143 | ],
144 | "metadata": {
145 | "kernelspec": {
146 | "display_name": "Python 2",
147 | "language": "python",
148 | "name": "python2"
149 | },
150 | "language_info": {
151 | "codemirror_mode": {
152 | "name": "ipython",
153 | "version": 2
154 | },
155 | "file_extension": ".py",
156 | "mimetype": "text/x-python",
157 | "name": "python",
158 | "nbconvert_exporter": "python",
159 | "pygments_lexer": "ipython2",
160 | "version": "2.7.9"
161 | }
162 | },
163 | "nbformat": 4,
164 | "nbformat_minor": 0
165 | }
166 |
--------------------------------------------------------------------------------
/notebooks/test_grav.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [
10 | {
11 | "name": "stderr",
12 | "output_type": "stream",
13 | "text": [
14 | "//anaconda/lib/python2.7/site-packages/matplotlib/font_manager.py:273: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.\n",
15 | " warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.')\n"
16 | ]
17 | },
18 | {
19 | "name": "stdout",
20 | "output_type": "stream",
21 | "text": [
22 | "Populating the interactive namespace from numpy and matplotlib\n"
23 | ]
24 | }
25 | ],
26 | "source": [
27 | "import numpy as np\n",
28 | "import pandas as pd\n",
29 | "import os\n",
30 | "os.chdir('../')\n",
31 | "from gravity import Gravity, Production, Attraction, Doubly, BaseGravity\n",
32 | "import statsmodels.formula.api as smf\n",
33 | "from statsmodels.api import families\n",
34 | "import matplotlib.pyplot as plt\n",
35 | "%pylab inline"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": 2,
41 | "metadata": {
42 | "collapsed": false
43 | },
44 | "outputs": [],
45 | "source": [
46 | "\n",
47 | "n = 3000\n",
48 | "o = np.tile(np.arange(n),n)\n",
49 | "d = np.repeat(np.arange(n),n)\n",
50 | "loc_size = np.random.randint(25000,500000, n)\n",
51 | "o_vars = np.tile(loc_size, n)\n",
52 | "d_vars = np.repeat(loc_size, n)\n",
53 | "dij = np.random.exponential(2500, n**2)\n",
54 | "f = o_vars**.3*d_vars**.4*np.exp(dij*-.00005)\n",
55 | "o = np.reshape(o, (-1,1))\n",
56 | "d = np.reshape(d, (-1,1))\n",
57 | "o_vars = np.reshape(o_vars, (-1,1))\n",
58 | "d_vars = np.reshape(d_vars, (-1,1))\n",
59 | "dij = np.reshape(dij, (-1,1))\n",
60 | "f = np.reshape(f, (-1,1))\n",
61 | "f = f.astype(np.int64)"
62 | ]
63 | },
64 | {
65 | "cell_type": "code",
66 | "execution_count": 3,
67 | "metadata": {
68 | "collapsed": false
69 | },
70 | "outputs": [
71 | {
72 | "name": "stdout",
73 | "output_type": "stream",
74 | "text": [
75 | "CPU times: user 14.3 s, sys: 1.46 s, total: 15.8 s\n",
76 | "Wall time: 7.41 s\n"
77 | ]
78 | },
79 | {
80 | "data": {
81 | "text/plain": [
82 | ""
83 | ]
84 | },
85 | "execution_count": 3,
86 | "metadata": {},
87 | "output_type": "execute_result"
88 | }
89 | ],
90 | "source": [
91 | "%time Gravity(f, o_vars, d_vars, dij, 'exp')"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": 4,
97 | "metadata": {
98 | "collapsed": false
99 | },
100 | "outputs": [
101 | {
102 | "name": "stdout",
103 | "output_type": "stream",
104 | "text": [
105 | "CPU times: user 38.3 s, sys: 4 s, total: 42.3 s\n",
106 | "Wall time: 24.6 s\n"
107 | ]
108 | },
109 | {
110 | "data": {
111 | "text/plain": [
112 | ""
113 | ]
114 | },
115 | "execution_count": 4,
116 | "metadata": {},
117 | "output_type": "execute_result"
118 | }
119 | ],
120 | "source": [
121 | "%time Production(f, o, d_vars, dij, 'exp')"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": 5,
127 | "metadata": {
128 | "collapsed": false
129 | },
130 | "outputs": [
131 | {
132 | "name": "stdout",
133 | "output_type": "stream",
134 | "text": [
135 | "CPU times: user 36 s, sys: 4.25 s, total: 40.2 s\n",
136 | "Wall time: 21.4 s\n"
137 | ]
138 | },
139 | {
140 | "data": {
141 | "text/plain": [
142 | ""
143 | ]
144 | },
145 | "execution_count": 5,
146 | "metadata": {},
147 | "output_type": "execute_result"
148 | }
149 | ],
150 | "source": [
151 | "%time Attraction(f, d, o_vars, dij, 'exp')"
152 | ]
153 | },
154 | {
155 | "cell_type": "code",
156 | "execution_count": 6,
157 | "metadata": {
158 | "collapsed": false
159 | },
160 | "outputs": [
161 | {
162 | "name": "stdout",
163 | "output_type": "stream",
164 | "text": [
165 | "CPU times: user 1min 19s, sys: 6.3 s, total: 1min 25s\n",
166 | "Wall time: 37.4 s\n"
167 | ]
168 | },
169 | {
170 | "data": {
171 | "text/plain": [
172 | ""
173 | ]
174 | },
175 | "execution_count": 6,
176 | "metadata": {},
177 | "output_type": "execute_result"
178 | }
179 | ],
180 | "source": [
181 | "%time Doubly(f, o, d, dij, 'exp')"
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": null,
187 | "metadata": {
188 | "collapsed": true
189 | },
190 | "outputs": [],
191 | "source": []
192 | },
193 | {
194 | "cell_type": "code",
195 | "execution_count": null,
196 | "metadata": {
197 | "collapsed": true
198 | },
199 | "outputs": [],
200 | "source": []
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 3,
205 | "metadata": {
206 | "collapsed": false
207 | },
208 | "outputs": [],
209 | "source": [
210 | "from glm import GLM\n",
211 | "from iwls import iwls\n",
212 | "import line_profiler\n",
213 | "import IPython\n",
214 | "ip = IPython.get_ipython()\n",
215 | "ip.define_magic('lprun', line_profiler.magic_lprun)\n",
216 | "instance = Production(f, o, d_vars, dij, 'exp')\n"
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": 9,
222 | "metadata": {
223 | "collapsed": false
224 | },
225 | "outputs": [
226 | {
227 | "name": "stdout",
228 | "output_type": "stream",
229 | "text": [
230 | "correct sparse\n"
231 | ]
232 | }
233 | ],
234 | "source": [
235 | "%lprun -f BaseGravity.__init__ instance.__init__(f, o, d_vars, dij, 'exp')"
236 | ]
237 | },
238 | {
239 | "cell_type": "code",
240 | "execution_count": 8,
241 | "metadata": {
242 | "collapsed": true
243 | },
244 | "outputs": [],
245 | "source": [
246 | "glm_inst = GLM(instance.y, instance.X, family=families.Poisson())\n",
247 | "%lprun -f GLM.__init__ glm_inst.__init__(instance.y, instance.X, family=families.Poisson())"
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "execution_count": 7,
253 | "metadata": {
254 | "collapsed": true
255 | },
256 | "outputs": [],
257 | "source": [
258 | "%lprun -f iwls iwls(instance.y, instance.X, family=families.Poisson(), offset=None, y_fix=None)"
259 | ]
260 | },
261 | {
262 | "cell_type": "code",
263 | "execution_count": null,
264 | "metadata": {
265 | "collapsed": true
266 | },
267 | "outputs": [],
268 | "source": []
269 | }
270 | ],
271 | "metadata": {
272 | "anaconda-cloud": {},
273 | "kernelspec": {
274 | "display_name": "Python [Root]",
275 | "language": "python",
276 | "name": "Python [Root]"
277 | },
278 | "language_info": {
279 | "codemirror_mode": {
280 | "name": "ipython",
281 | "version": 2
282 | },
283 | "file_extension": ".py",
284 | "mimetype": "text/x-python",
285 | "name": "python",
286 | "nbconvert_exporter": "python",
287 | "pygments_lexer": "ipython2",
288 | "version": "2.7.12"
289 | }
290 | },
291 | "nbformat": 4,
292 | "nbformat_minor": 0
293 | }
294 |
--------------------------------------------------------------------------------
/notebooks/validate_gravity.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 75,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "#import sys\n",
12 | "#sys.path.append('/Users/toshan/dev/pysal/pysal/contrib/glm')\n",
13 | "#from utils import \n",
14 | "import numpy as np\n",
15 | "import pandas as pd\n",
16 | "import sys\n",
17 | "sys.path.append('/Users/toshan/dev/pysal/pysal/contrib/spint')\n",
18 | "from gravity import Gravity, Production, Attraction, Doubly, BaseGravity\n",
19 | "import gravity\n",
20 | "from utils import sorensen\n",
21 | "import statsmodels.formula.api as smf\n",
22 | "from statsmodels.api import families as families"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": 32,
28 | "metadata": {
29 | "collapsed": false
30 | },
31 | "outputs": [],
32 | "source": [
33 | "austria = pd.read_csv('http://dl.dropbox.com/u/8649795/AT_Austria.csv')\n",
34 | "austria = austria[austria['Origin'] != austria['Destination']]\n",
35 | "f = austria['Data'].values\n",
36 | "o = austria['Origin'].values\n",
37 | "d = austria['Destination'].values\n",
38 | "dij = austria['Dij'].values\n",
39 | "o_vars = austria['Oi2007'].values\n",
40 | "d_vars = austria['Dj2007'].values\n"
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 33,
46 | "metadata": {
47 | "collapsed": false
48 | },
49 | "outputs": [
50 | {
51 | "name": "stdout",
52 | "output_type": "stream",
53 | "text": [
54 | "[ -7.95447436e+00 8.63867812e-01 8.80474585e-01 -6.20544765e-03]\n",
55 | "[ -7.95447436e+00 8.63867812e-01 8.80474585e-01 -6.20544766e-03]\n"
56 | ]
57 | }
58 | ],
59 | "source": [
60 | "grav = Gravity(f, o_vars, d_vars, dij, 'exp', framework='glm', constant=True)\n",
61 | "print grav.params\n",
62 | "\n",
63 | "gravity = smf.glm('Data~np.log(Oi2007)+np.log(Dj2007)+Dij', family=families.Poisson(), data=austria).fit()\n",
64 | "print gravity.params.values"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": 35,
70 | "metadata": {
71 | "collapsed": false,
72 | "scrolled": false
73 | },
74 | "outputs": [
75 | {
76 | "name": "stdout",
77 | "output_type": "stream",
78 | "text": [
79 | "[-1.11700938 1.68662317 2.15188689 0.60300297 0.88380784 1.20926104\n",
80 | " 0.68938983 1.15472804 1.02479968 0.89278717 -0.00727113]\n",
81 | "[-1.11700938 1.68662317 2.15188689 0.60300297 0.88380784 1.20926105\n",
82 | " 0.68938983 1.15472805 1.02479968 0.89278717 -0.00727113]\n"
83 | ]
84 | }
85 | ],
86 | "source": [
87 | "production = Production(f, o, d_vars, dij, 'exp', framework='glm')\n",
88 | "print production.params\n",
89 | "\n",
90 | "gravity = smf.glm('Data~Origin+np.log(Dj2007)+Dij', family=families.Poisson(), data=austria).fit()\n",
91 | "print gravity.params.values"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": 5,
97 | "metadata": {
98 | "collapsed": false
99 | },
100 | "outputs": [
101 | {
102 | "name": "stdout",
103 | "output_type": "stream",
104 | "text": [
105 | "[-0.88439723 1.62180605 1.92772078 0.12462001 0.62378812 0.69646073\n",
106 | " 0.20909411 0.6856777 0.48539625 0.89235874 -0.00693755]\n",
107 | "[-0.88439723 1.62180605 1.92772078 0.12462002 0.62378812 0.69646073\n",
108 | " 0.20909411 0.6856777 0.48539625 0.89235874 -0.00693755]\n"
109 | ]
110 | }
111 | ],
112 | "source": [
113 | "attraction = Attraction(f, d, o_vars, dij, 'exp', framework='glm', constant=True)\n",
114 | "print attraction.params\n",
115 | "\n",
116 | "gravity = smf.glm('Data~np.log(Oi2007)+Destination + Dij', family=families.Poisson(), data=austria).fit()\n",
117 | "print gravity.params.values"
118 | ]
119 | },
120 | {
121 | "cell_type": "code",
122 | "execution_count": 6,
123 | "metadata": {
124 | "collapsed": false,
125 | "scrolled": true
126 | },
127 | "outputs": [
128 | {
129 | "name": "stdout",
130 | "output_type": "stream",
131 | "text": [
132 | "[ 6.20471518 1.5449095 2.4414292 0.69924374 0.94869185 1.28967637\n",
133 | " 0.74270015 1.19468573 0.98874193 1.49709841 2.18492741 0.18784818\n",
134 | " 0.66434515 0.74264938 0.21334535 0.66765781 0.39986094 -0.00791533]\n",
135 | "[ 6.20471518 1.5449095 2.4414292 0.69924374 0.94869185 1.28967637\n",
136 | " 0.74270016 1.19468574 0.98874192 1.49709841 2.18492741 0.18784818\n",
137 | " 0.66434515 0.74264938 0.21334535 0.66765782 0.39986087 -0.00791533]\n"
138 | ]
139 | }
140 | ],
141 | "source": [
142 | "doubly = Doubly(f, o, d, dij, 'exp', framework='glm', constant=True)\n",
143 | "print doubly.params\n",
144 | "\n",
145 | "gravity = smf.glm('Data~Origin+Destination+Dij', family=families.Poisson(), data=austria).fit()\n",
146 | "print gravity.params.values"
147 | ]
148 | }
149 | ],
150 | "metadata": {
151 | "anaconda-cloud": {},
152 | "kernelspec": {
153 | "display_name": "Python [Root]",
154 | "language": "python",
155 | "name": "Python [Root]"
156 | },
157 | "language_info": {
158 | "codemirror_mode": {
159 | "name": "ipython",
160 | "version": 2
161 | },
162 | "file_extension": ".py",
163 | "mimetype": "text/x-python",
164 | "name": "python",
165 | "nbconvert_exporter": "python",
166 | "pygments_lexer": "ipython2",
167 | "version": "2.7.12"
168 | }
169 | },
170 | "nbformat": 4,
171 | "nbformat_minor": 0
172 | }
173 |
--------------------------------------------------------------------------------
/readthedocs.yml:
--------------------------------------------------------------------------------
1 | # Required
2 | version: 2
3 |
4 | # Build documentation in the docs/ directory with Sphinx
5 | sphinx:
6 | configuration: doc/conf.py
7 |
8 | # Optionally build your docs in additional formats such as PDF and ePub
9 | formats: all
10 |
11 | python:
12 | version: 3.7
13 | install:
14 | - requirements: requirements.txt
15 | - method: pip
16 | path: .
17 | extra_requirements:
18 | - tests
19 | - docs
20 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | scipy>=0.11
2 | numpy>=1.3
3 | libpysal>=4.0.0
4 | spglm>=1.0.6
5 | spreg
6 |
--------------------------------------------------------------------------------
/requirements_docs.txt:
--------------------------------------------------------------------------------
1 | sphinx>=1.4.3
2 | sphinxcontrib-napoleon
3 | sphinx_gallery
4 | sphinxcontrib-bibtex
5 | sphinx_bootstrap_theme
6 | numpydoc
7 |
--------------------------------------------------------------------------------
/requirements_tests.txt:
--------------------------------------------------------------------------------
1 | nose
2 | nose-progressive
3 | nose-exclude
4 | coverage
5 | coveralls
6 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | description-file = README.md
3 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 | from distutils.command.build_py import build_py
3 |
4 | # Get __version__ from PACKAGE_NAME/__init__.py without importing the package
5 | # __version__ has to be defined in the first line
6 | with open('spint/__init__.py', 'r') as f:
7 | exec(f.readline())
8 |
9 |
10 | def _get_requirements_from_files(groups_files):
11 | groups_reqlist = {}
12 |
13 | for k, v in groups_files.items():
14 | with open(v, 'r') as f:
15 | pkg_list = f.read().splitlines()
16 | groups_reqlist[k] = pkg_list
17 |
18 | return groups_reqlist
19 |
20 |
21 | def setup_package():
22 | _groups_files = {
23 | 'base': 'requirements.txt',
24 | 'tests': 'requirements_tests.txt',
25 | 'docs': 'requirements_docs.txt'
26 | }
27 |
28 | reqs = _get_requirements_from_files(_groups_files)
29 | install_reqs = reqs.pop('base')
30 | extras_reqs = reqs
31 |
32 | setup(name='spint', # name of package
33 | version=__version__,
34 | description='SPatial INTeraction models', # short <80chr description
35 | url='https://github.com/pysal/spint', # github repo
36 | maintainer='Taylor M. Oshan',
37 | maintainer_email='tayoshan@gmail.com',
38 | python_requires='>3.5',
39 | test_suite='nose.collector',
40 | tests_require=['nose'],
41 | keywords='spatial statistics',
42 | classifiers=[
43 | 'Development Status :: 5 - Production/Stable',
44 | 'Intended Audience :: Science/Research',
45 | 'Intended Audience :: Developers',
46 | 'Intended Audience :: Education',
47 | 'Topic :: Scientific/Engineering',
48 | 'Topic :: Scientific/Engineering :: GIS',
49 | 'License :: OSI Approved :: BSD License',
50 | 'Programming Language :: Python',
51 | 'Programming Language :: Python :: 3.6',
52 | 'Programming Language :: Python :: 3.7'
53 | ],
54 | license='3-Clause BSD',
55 | packages=find_packages(),
56 | install_requires=install_reqs,
57 | extras_require=extras_reqs,
58 | zip_safe=False,
59 | cmdclass={'build.py': build_py})
60 |
61 |
62 | if __name__ == '__main__':
63 | setup_package()
64 |
--------------------------------------------------------------------------------
/spint/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.0.7'
2 |
3 | from .gravity import Gravity, Production, Attraction, Doubly
4 | from .utils import CPC, sorensen, srmse
5 | from .vec_SA import VecMoran as Moran_Vector
6 | from .dispersion import phi_disp, alpha_disp
7 | from .flow_accessibility import Accessibility
8 |
--------------------------------------------------------------------------------
/spint/count_model.py:
--------------------------------------------------------------------------------
1 | """
2 | CountModel class for dispatching different types of count models and different
3 | types of estimation technqiues.
4 | """
5 |
6 | __author__ = "Taylor Oshan tayoshan@gmail.com"
7 |
8 | import numpy as np
9 | from spglm.glm import GLM
10 | from spglm.family import Poisson, QuasiPoisson
11 |
12 |
13 | class CountModel(object):
14 | """
15 | Base class for variety of count-based models such as Poisson, negative binomial,
16 | etc. of the exponetial family.
17 |
18 | Parameters
19 | ----------
20 | y : array
21 | n x 1; n observations of the depedent variable
22 | X : array
23 | n x k; design matrix of k explanatory variables
24 | family : instance of class 'family'
25 | default is Poisson()
26 | constant : boolean
27 | True if intercept should be estimated and false otherwise.
28 | Default is True.
29 |
30 |
31 | Attributes
32 | ----------
33 | y : array
34 | n x 1; n observations of the depedent variable
35 | X : array
36 | n x k; design matrix of k explanatory variables
37 | fitted : boolean
38 | False is model has not been fitted and True if it has been
39 | successfully fitted. Deault is False.
40 | constant : boolean
41 | True if intercept should be estimated and false otherwise.
42 | Default is True.
43 |
44 | Example
45 | -------
46 | >>> from spint.count_model import CountModel
47 | >>> import libpysal
48 | >>> db = libpysal.io.open(libpysal.examples.get_path('columbus.dbf'),'r')
49 | >>> y = np.array(db.by_col("HOVAL"))
50 | >>> y = np.reshape(y, (49,1))
51 | >>> y = np.round(y).astype(int)
52 | >>> X = []
53 | >>> X.append(db.by_col("INC"))
54 | >>> X.append(db.by_col("CRIME"))
55 | >>> X = np.array(X).T
56 | >>> model = CountModel(y, X, family=Poisson())
57 | >>> results = model.fit('GLM')
58 | >>> results.params
59 | array([ 3.92159085, 0.01183491, -0.01371397])
60 |
61 | """
62 |
63 | def __init__(self, y, X, family=Poisson(), constant=True):
64 | self.y = self._check_counts(y)
65 | self.X = X
66 | self.constant = constant
67 |
68 | def _check_counts(self, y):
69 | if (y.dtype == 'int64') | (y.dtype == 'int32'):
70 | return y
71 | else:
72 | raise TypeError(
73 | 'Dependent variable (y) must be composed of integers')
74 |
75 | def fit(self, framework='GLM', Quasi=False):
76 | """
77 | Method that fits a particular count model usign the appropriate
78 | estimation technique. Models include Poisson GLM, Negative Binomial GLM,
79 | Quasi-Poisson - at the moment Poisson GLM is the only option.
80 |
81 | TODO: add zero inflated variants and hurdle variants.
82 |
83 | Parameters
84 | ----------
85 | framework : string
86 | estimation framework; default is GLM
87 | "GLM" | "QUASI" |
88 | """
89 | if (framework.lower() == 'glm'):
90 | if not Quasi:
91 | results = GLM(
92 | self.y,
93 | self.X,
94 | family=Poisson(),
95 | constant=self.constant).fit()
96 | else:
97 | results = GLM(
98 | self.y,
99 | self.X,
100 | family=QuasiPoisson(),
101 | constant=self.constant).fit()
102 | return CountModelResults(results)
103 |
104 | else:
105 | raise NotImplemented(
106 | 'Poisson GLM is the only count model currently implemented')
107 |
108 |
109 | class CountModelResults(object):
110 | """
111 | Results of estimated GLM and diagnostics.
112 |
113 | Parameters
114 | ----------
115 | results : GLM object
116 | Pointer to GLMResults object with estimated parameters
117 | and diagnostics.
118 |
119 | Attributes
120 | ----------
121 | model : GLM Object
122 | Points to model object for which parameters have been
123 | estimated. May contain additional diagnostics.
124 | y : array
125 | n*1, dependent variable.
126 | X : array
127 | n*k, independent variable, including constant.
128 | family : string
129 | Model type: 'Gaussian', 'Poisson', 'Logistic'
130 | n : integer
131 | Number of observations
132 | k : integer
133 | Number of independent variables
134 | df_model : float
135 | k-1, where k is the number of variables (including
136 | intercept)
137 | df_residual : float
138 | observations minus variables (n-k)
139 | routine.
140 | params : array
141 | n*k, estimared beta coefficients
142 | yhat : array
143 | n*1, predicted value of y (i.e., fittedvalues)
144 | cov_params : array
145 | Variance covariance matrix (kxk) of betas
146 | std_err : array
147 | k*1, standard errors of betas
148 | pvalues : array
149 | k*1, two-tailed pvalues of parameters
150 | tvalues : array
151 | k*1, the tvalues of the standard errors
152 | deviance : float
153 | value of the deviance function evalued at params;
154 | see family.py for distribution-specific deviance
155 | llf : float
156 | value of the loglikelihood function evalued at params;
157 | see family.py for distribution-specific loglikelihoods
158 | llnull : float
159 | value of the loglikelihood function evaluated with only an
160 | intercept; see family.py for distribution-specific
161 | loglikelihoods
162 | AIC : float
163 | Akaike information criterion
164 | resid : array
165 | response residuals; defined as y-mu
166 |
167 | resid_dev : array
168 | k x 1, residual deviance of model
169 | D2 : float
170 | percentage of explained deviance
171 | adj_D2 : float
172 |
173 | pseudo_R2 : float
174 | McFadden's pseudo R2 (coefficient of determination)
175 | adj_pseudoR2 : float
176 | adjusted McFadden's pseudo R2
177 |
178 | """
179 |
180 | def __init__(self, results):
181 | self.y = results.y
182 | self.X = results.X
183 | self.family = results.family
184 | self.params = results.params
185 | self.AIC = results.aic
186 | self.df_model = results.df_model
187 | self.df_resid = results.df_resid
188 | self.llf = results.llf
189 | self.llnull = results.llnull
190 | self.yhat = results.mu
191 | self.deviance = results.deviance
192 | self.n = results.n
193 | self.k = results.k
194 | self.resid = results.resid_response
195 | self.resid_dev = results.resid_deviance
196 | self.cov_params = results.cov_params()
197 | self.std_err = results.bse
198 | self.pvalues = results.pvalues
199 | self.tvalues = results.tvalues
200 | self.D2 = results.D2
201 | self.adj_D2 = results.adj_D2
202 | self.pseudoR2 = results.pseudoR2
203 | self.adj_pseudoR2 = results.adj_pseudoR2
204 | self.model = results
205 |
--------------------------------------------------------------------------------
/spint/dispersion.py:
--------------------------------------------------------------------------------
1 | """
2 | Various functions to test hypotheses regarding the dispersion of the variance of
3 | a variable.
4 |
5 | """
6 |
7 | __author__ = "Taylor Oshan tayoshan@gmail.com"
8 |
9 | from spglm.glm import GLM
10 | from spglm.family import Poisson
11 | import numpy as np
12 | import scipy.stats as stats
13 | from types import FunctionType
14 |
15 |
16 | def phi_disp(model):
17 | """
18 | Test the hypothesis that var[y] = mu (equidispersion) against the
19 | alternative hypothesis (quasi-Poisson) that var[y] = phi * mu where mu
20 | is the expected value of y and phi is an estimated overdispersion
21 | coefficient which is equivalent to 1+alpha in the alternative alpha
22 | dispersion test.
23 |
24 | phi > 0: overdispersion
25 | phi = 1: equidispersion
26 | phi < 0: underdispersion
27 |
28 | Parameters
29 | ----------
30 | model : Model results class
31 | function can only be called on a sucessfully fitted model
32 | which has a valid response variable, y, and a valid
33 | predicted response variable, yhat.
34 | alt_var : function
35 | specifies an alternative varaince as a function of mu.
36 | Function must take a single scalar as input and return a
37 | single scalar as output
38 | Returns
39 | -------
40 | array : [alpha coefficient, tvalue of alpha, pvalue of alpha]
41 |
42 | """
43 | try:
44 | y = model.y.reshape((-1, 1))
45 | yhat = model.yhat.reshape((-1, 1))
46 | ytest = (((y - yhat)**2 - y) / yhat).reshape((-1, 1))
47 | except BaseException:
48 | raise AttributeError(
49 | "Check that fitted model has valid 'y' and 'yhat' attributes")
50 |
51 | phi = 1 + np.mean(ytest)
52 | zval = np.sqrt(len(ytest)) * np.mean(ytest) / np.std(ytest, ddof=1)
53 | pval = stats.norm.sf(zval)
54 |
55 | return np.array([phi, zval, pval])
56 |
57 |
58 | def alpha_disp(model, alt_var=lambda x: x):
59 | """
60 | Test the hypothesis that var[y] = mu (equidispersion) against the
61 | alternative hypothesis that var[y] = mu + alpha * alt_var(mu) where mu
62 | is the expected value of y, alpha is an estimated coefficient, and
63 | alt_var() specifies an alternative variance as a function of mu.
64 | alt_var=lambda x:x corresponds to an alternative hypothesis of a negative
65 | binomimal model with a linear variance function and alt_var=lambda
66 | x:x**2 correspinds to an alternative hypothesis of a negative binomial
67 | model with a quadratic varaince function.
68 |
69 | alpha > 0: overdispersion
70 | alpha = 1: equidispersion
71 | alpha < 0: underdispersion
72 |
73 | Parameters
74 | ----------
75 | model : Model results class
76 | function can only be called on a sucessfully fitted model
77 | which has a valid response variable, y, and a valid
78 | predicted response variable, yhat.
79 | alt_var : function
80 | specifies an alternative varaince as a function of mu.
81 | Function must take a single scalar as input and return a
82 | single scalar as output
83 | Returns
84 | -------
85 | array : [alpha coefficient, tvalue of alpha, pvalue of alpha]
86 |
87 | """
88 | try:
89 | y = model.y.reshape((-1, 1))
90 | yhat = model.yhat.reshape((-1, 1))
91 | ytest = (((y - yhat)**2 - y) / yhat).reshape((-1, 1))
92 | except BaseException:
93 | raise AttributeError(
94 | "Make sure model passed has been estimated and has a valid 'y' and 'yhat' attribute")
95 |
96 | if isinstance(alt_var, FunctionType):
97 | X = (alt_var(yhat) / yhat).reshape((-1, 1))
98 | test_results = GLM(ytest, X, constant=False).fit()
99 | alpha = test_results.params[0]
100 | zval = test_results.tvalues[0]
101 | pval = stats.norm.sf(zval)
102 | else:
103 | raise TypeError(
104 | "The alternative variance function, 'alt_var', must be a valid function'")
105 |
106 | return np.array([alpha, zval, pval])
107 |
--------------------------------------------------------------------------------
/spint/flow_accessibility.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # 3. FlowAccessibility = Accessibility of flow taking existing destinations
3 | import numpy as np
4 | import pandas as pd
5 | import itertools
6 |
7 | #-------------------------------------------------------------------------------------------------------------
8 |
9 | def _generate_dummy_flows():
10 | nodes = ['A','B','C','D','E']
11 | destination_masses = [60,10,10,30,50]
12 |
13 | all_flow = pd.DataFrame( list(itertools.product(nodes,nodes
14 | )
15 | )
16 | ).rename(columns = {0:'origin_ID', 1:'destination_ID'
17 | }
18 | )
19 |
20 | masses = {'nodes': nodes,'dest_masses': destination_masses
21 | }
22 |
23 | masses = pd.DataFrame({'nodes': nodes,'dest_masses': destination_masses
24 | }, columns = ['nodes','dest_masses'
25 | ]
26 | )
27 |
28 | all_flow['volume_in_unipartite'] = [10,10,10,10,10,
29 | 10,0,0,10,10,
30 | 10,0,0,10,0,
31 | 10,10,10,0,10,
32 | 10,10,0,10,10]
33 |
34 | all_flow['volume_in_bipartite'] = [0,0,10,10,10,
35 | 0,0,0,10,10,
36 | 0,0,0,0,0,
37 | 0,0,0,0,0,
38 | 0,0,0,0,0]
39 |
40 | all_flow['distances'] = [0,8,2,5,5,
41 | 8,0,10,7,4,
42 | 2,10,0,6,9,
43 | 5,7,6,0,2,
44 | 5,4,9,2,0]
45 |
46 | all_flow = all_flow.merge(masses, how = 'left', left_on = 'destination_ID', right_on = 'nodes')
47 |
48 | all_flow['results_all=False'] = [500, 510, 730, 230, 190,
49 | 400, 890, 750, 400, 360,
50 | 150, 690, 300, 300, 360,
51 | 350, 780, 670, 530, 430,
52 | 230, 690, 400, 370, 400]
53 |
54 | return all_flow
55 |
56 |
57 | #-------------------------------------------------------------------------------------------------------------
58 |
59 |
60 |
61 | def Accessibility(dest_nodes, distances, weights, masses, all_destinations=False, is_bipartite = False):
62 |
63 | """
64 | Function to calculate Accessibility for Competing Destination model, given a COMPLETE origin-destination edgelist.
65 | See an example notebook to see how to construct the COMPLETE origin-destination edgelist from your data.
66 |
67 | Parameters
68 | ----------
69 | dest_nodes : array of strings or numeric codes
70 | n x 1; the DESTINATION column in the origin-destination edgelist
71 |
72 | distances : array of numbers
73 | n x 1; the distance column in the origin-destination edgelist
74 |
75 | weights : array of numbers
76 | n x 1; the flow volume column in the origin-destination edgelist
77 |
78 | masses : array of numbers
79 | n x 1; the DESTINATION masses column in the origin-destination edgelist
80 |
81 | all_destinations: bolean, Deafult is False
82 | True to consider all the existing destinations as a competing destinations,
83 | even those where flows does not exist in the data.
84 | False to consider only those destinations as a competing destinations, which exists in the data.
85 | This option is only available for flow data that can be represented as unipartite graph.
86 | is_bipartite : bolean, Deafult is False
87 | True to predefine the flow graph as bipartite: one where origins and destinations are separate
88 | entities and where interaction can happen only in one direction, from origin to destination.
89 | False to keep assumption for regular unipartite graph.
90 | """
91 |
92 | # convert numbers to integers
93 | distances = np.array(distances.astype(int))
94 | weights = np.array(weights.astype(int))
95 | masses = np.array(masses.astype(int))
96 | dest_nodes = np.array(dest_nodes.astype(str))
97 |
98 | # define error
99 | if len(distances) != len(weights) != len(masses) != len(dest_nodes):
100 | raise ValueError("One of the input array is different length then the others, but they should all be the same length. See notebook example if you are unsure what the input should look like ")
101 | if all_destinations & is_bipartite:
102 | raise ValueError("This option has not been implemented yet")
103 |
104 | # define number of rows
105 | nrows= len(dest_nodes)
106 | uniques = len(np.unique(np.array(dest_nodes)))
107 |
108 | # create binary for weight
109 | v_bin = np.ones(nrows)
110 | weights[np.isnan(weights)] = 0
111 | v_bin[weights <= 0] = 0
112 |
113 | # define the base matrices
114 | distance = distances.reshape(uniques,uniques)
115 | mass =masses.reshape(uniques,uniques).T
116 |
117 | # define the identity array
118 | idn = np.identity(uniques)
119 | idn = np.where((idn==1), 0, 1)
120 | idn = np.concatenate(uniques * [idn.ravel()], axis = 0
121 | ).reshape(uniques,uniques,uniques
122 | ).T
123 |
124 | # multiply the distance by mass
125 | dm = distance * mass
126 |
127 | # combine all matrices for either all or existing destinations
128 | if is_bipartite:
129 | exists = v_bin.reshape(uniques,uniques).T
130 | output = (np.concatenate(uniques * [exists], axis = 0
131 | ).reshape(uniques,uniques,uniques
132 | ).T
133 | ) * idn * (uniques * [dm]
134 | )
135 | elif all_destinations:
136 | exists = v_bin.reshape(uniques,uniques)
137 | output = idn * (nrows * [dm])
138 | else:
139 | exists = v_bin.reshape(uniques,uniques)
140 | output = (np.concatenate(uniques * [exists], axis = 0
141 | ).reshape(uniques,uniques,uniques
142 | ).T
143 | ) * idn * (uniques * [dm]
144 | )
145 |
146 | # get the sum and covert to series
147 | output = (np.sum(output,axis = 1
148 | )
149 | ).reshape(nrows
150 | ).T
151 |
152 |
153 | return output
154 |
--------------------------------------------------------------------------------
/spint/primer/SpIntPrimer.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spint/050865acae4054b8ac30b12e6d38ca884e7a43cc/spint/primer/SpIntPrimer.pdf
--------------------------------------------------------------------------------
/spint/primer/austria.csv:
--------------------------------------------------------------------------------
1 | ,Origin,Destination,Data,Oi,Dj,Dij
2 | 0,AT11,AT11,0,4016,5146,1e-300
3 | 1,AT11,AT12,1131,4016,25741,103.001845
4 | 2,AT11,AT13,1887,4016,26980,84.204666
5 | 3,AT11,AT21,69,4016,4117,220.811933
6 | 4,AT11,AT22,738,4016,8634,132.00748
7 | 5,AT11,AT31,98,4016,8193,214.511814
8 | 6,AT11,AT32,31,4016,4902,246.933305
9 | 7,AT11,AT33,43,4016,3952,390.85611
10 | 8,AT11,AT34,19,4016,1910,505.089539
11 | 9,AT12,AT11,1633,20080,5146,103.001845
12 | 10,AT12,AT12,0,20080,25741,1e-300
13 | 11,AT12,AT13,14055,20080,26980,45.796272
14 | 12,AT12,AT21,416,20080,4117,216.994739
15 | 13,AT12,AT22,1276,20080,8634,129.878172
16 | 14,AT12,AT31,1850,20080,8193,140.706671
17 | 15,AT12,AT32,388,20080,4902,201.232355
18 | 16,AT12,AT33,303,20080,3952,343.50075
19 | 17,AT12,AT34,159,20080,1910,453.515594
20 | 18,AT13,AT11,2301,29142,5146,84.204666
21 | 19,AT13,AT12,20164,29142,25741,45.796272
22 | 20,AT13,AT13,0,29142,26980,1e-300
23 | 21,AT13,AT21,1080,29142,4117,249.932874
24 | 22,AT13,AT22,1831,29142,8634,158.630661
25 | 23,AT13,AT31,1943,29142,8193,186.420738
26 | 24,AT13,AT32,742,29142,4902,244.108305
27 | 25,AT13,AT33,674,29142,3952,387.61776
28 | 26,AT13,AT34,407,29142,1910,498.407152
29 | 27,AT21,AT11,85,4897,5146,220.811933
30 | 28,AT21,AT12,379,4897,25741,216.994739
31 | 29,AT21,AT13,1597,4897,26980,249.932874
32 | 30,AT21,AT21,0,4897,4117,1e-300
33 | 31,AT21,AT22,1608,4897,8634,92.407958
34 | 32,AT21,AT31,328,4897,8193,151.777157
35 | 33,AT21,AT32,317,4897,4902,92.894408
36 | 34,AT21,AT33,469,4897,3952,194.851669
37 | 35,AT21,AT34,114,4897,1910,306.105825
38 | 36,AT22,AT11,762,8487,5146,132.00748
39 | 37,AT22,AT12,1110,8487,25741,129.878172
40 | 38,AT22,AT13,2973,8487,26980,158.630661
41 | 39,AT22,AT21,1252,8487,4117,92.407958
42 | 40,AT22,AT22,0,8487,8634,1e-300
43 | 41,AT22,AT31,1081,8487,8193,124.563096
44 | 42,AT22,AT32,622,8487,4902,122.433524
45 | 43,AT22,AT33,425,8487,3952,261.893783
46 | 44,AT22,AT34,262,8487,1910,376.34667
47 | 45,AT31,AT11,196,10638,5146,214.511814
48 | 46,AT31,AT12,2027,10638,25741,140.706671
49 | 47,AT31,AT13,3498,10638,26980,186.420738
50 | 48,AT31,AT21,346,10638,4117,151.777157
51 | 49,AT31,AT22,1332,10638,8634,124.563096
52 | 50,AT31,AT31,0,10638,8193,1e-300
53 | 51,AT31,AT32,2144,10638,4902,81.753652
54 | 52,AT31,AT33,821,10638,3952,208.456383
55 | 53,AT31,AT34,274,10638,1910,314.793199
56 | 54,AT32,AT11,49,5790,5146,246.933305
57 | 55,AT32,AT12,378,5790,25741,201.232355
58 | 56,AT32,AT13,1349,5790,26980,244.108305
59 | 57,AT32,AT21,310,5790,4117,92.894408
60 | 58,AT32,AT22,851,5790,8634,122.433524
61 | 59,AT32,AT31,2117,5790,8193,81.753652
62 | 60,AT32,AT32,0,5790,4902,1e-300
63 | 61,AT32,AT33,630,5790,3952,145.076472
64 | 62,AT32,AT34,106,5790,1910,258.591197
65 | 63,AT33,AT11,87,4341,5146,390.85611
66 | 64,AT33,AT12,424,4341,25741,343.50075
67 | 65,AT33,AT13,978,4341,26980,387.61776
68 | 66,AT33,AT21,490,4341,4117,194.851669
69 | 67,AT33,AT22,670,4341,8634,261.893783
70 | 68,AT33,AT31,577,4341,8193,208.456383
71 | 69,AT33,AT32,546,4341,4902,145.076472
72 | 70,AT33,AT33,0,4341,3952,1e-300
73 | 71,AT33,AT34,569,4341,1910,114.46325
74 | 72,AT34,AT11,33,2184,5146,505.089539
75 | 73,AT34,AT12,128,2184,25741,453.515594
76 | 74,AT34,AT13,643,2184,26980,498.407152
77 | 75,AT34,AT21,154,2184,4117,306.105825
78 | 76,AT34,AT22,328,2184,8634,376.34667
79 | 77,AT34,AT31,199,2184,8193,314.793199
80 | 78,AT34,AT32,112,2184,4902,258.591197
81 | 79,AT34,AT33,587,2184,3952,114.46325
82 | 80,AT34,AT34,0,2184,1910,1e-300
83 |
--------------------------------------------------------------------------------
/spint/primer/austria.dbf:
--------------------------------------------------------------------------------
1 | _ f OBJECTID N NUTS_ID C STAT_LEVL_ N AREA N LEN N Shape_Leng N Shape_Area N
299AT33 2 0.00000000000 0.00000000000 11.11589824150 1.50022172697 312AT34 2 0.00000000000 0.00000000000 3.43932445938 0.30882099234 316AT11 2 0.00000000000 0.00000000000 7.25018235459 0.47491040095 326AT13 2 0.00000000000 0.00000000000 1.42907805863 0.05005857427 333AT31 2 0.00000000000 0.00000000000 9.13947499030 1.44833936577 334AT21 2 0.00000000000 0.00000000000 7.26685835453 1.12271501139 336AT32 2 0.00000000000 0.00000000000 8.17138727933 0.85287668505 337AT12 2 0.00000000000 0.00000000000 12.10618028170 2.32668356970 350AT22 2 0.00000000000 0.00000000000 9.32843862672 1.95118722812
--------------------------------------------------------------------------------
/spint/primer/austria.prj:
--------------------------------------------------------------------------------
1 | GEOGCS["ETRS89",DATUM["D_ETRS_1989",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
--------------------------------------------------------------------------------
/spint/primer/austria.qpj:
--------------------------------------------------------------------------------
1 | GEOGCS["ETRS89",DATUM["European_Terrestrial_Reference_System_1989",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6258"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4258"]]
2 |
--------------------------------------------------------------------------------
/spint/primer/austria.shp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spint/050865acae4054b8ac30b12e6d38ca884e7a43cc/spint/primer/austria.shp
--------------------------------------------------------------------------------
/spint/primer/austria.shx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spint/050865acae4054b8ac30b12e6d38ca884e7a43cc/spint/primer/austria.shx
--------------------------------------------------------------------------------
/spint/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spint/050865acae4054b8ac30b12e6d38ca884e7a43cc/spint/tests/__init__.py
--------------------------------------------------------------------------------
/spint/tests/test_accessibility.py:
--------------------------------------------------------------------------------
1 | """
2 | Tests for Accessibility function.
3 |
4 | The correctness of the function is veryfied by matching the output to manually calculated values, using very simple dummy dataset.
5 |
6 | """
7 |
8 | __author__ = 'Lenka Hasova haska.lenka@gmail.com'
9 |
10 | import unittest
11 | import numpy as np
12 | from ..flow_accessibility import _generate_dummy_flows
13 | from ..flow_accessibility import Accessibility
14 |
15 |
16 |
17 | class AccessibilityTest(unittest.TestCase):
18 |
19 | def test_accessibility(self):
20 | flow = _generate_dummy_flows()
21 | flow = flow.loc[:,['origin_ID', 'destination_ID','distances', 'volume_in_unipartite','dest_masses','results_all=False']]
22 | flow['acc_uni'] = Accessibility(nodes = flow['origin_ID'], distances = flow['distances'], weights = flow['volume_in_unipartite'], masses = flow['dest_masses'], all_destinations=False)
23 |
24 | np.testing.testing.assert_array_equal(flow['results_all=False'], flow['acc_uni'])
25 |
26 | if __name__ == '__main__':
27 | unittest.main()
--------------------------------------------------------------------------------
/spint/tests/test_count_model.py:
--------------------------------------------------------------------------------
1 | """
2 | Tests for CountModel class, which includes various linear models designed for
3 | count data
4 |
5 | Test data is the Columbus dataset after it has been rounded to integers to act
6 | as count data. Results are verified using corresponding functions in R.
7 |
8 | """
9 |
10 | __author__ = 'Taylor Oshan tayoshan@gmail.com'
11 |
12 | import unittest
13 | import numpy as np
14 | import libpysal
15 | from spglm.family import Poisson
16 | from ..count_model import CountModel
17 |
18 |
19 | class TestCountModel(unittest.TestCase):
20 | """Tests CountModel class"""
21 |
22 | def setUp(self):
23 | db = libpysal.io.open(libpysal.examples.get_path('columbus.dbf'), 'r')
24 | y = np.array(db.by_col("HOVAL"))
25 | y = np.reshape(y, (49, 1))
26 | self.y = np.round(y).astype(int)
27 | X = []
28 | X.append(db.by_col("INC"))
29 | X.append(db.by_col("CRIME"))
30 | self.X = np.array(X).T
31 |
32 | def test_PoissonGLM(self):
33 | model = CountModel(self.y, self.X, family=Poisson())
34 | results = model.fit('GLM')
35 | np.testing.assert_allclose(results.params, [3.92159085, 0.01183491,
36 | -0.01371397], atol=1.0e-8)
37 | self.assertIsInstance(results.family, Poisson)
38 | self.assertEqual(results.n, 49)
39 | self.assertEqual(results.k, 3)
40 | self.assertEqual(results.df_model, 2)
41 | self.assertEqual(results.df_resid, 46)
42 | np.testing.assert_allclose(results.yhat,
43 | [51.26831574,
44 | 50.15022766,
45 | 40.06142973,
46 | 34.13799739,
47 | 28.76119226,
48 | 42.6836241,
49 | 55.64593703,
50 | 34.08277997,
51 | 40.90389582,
52 | 37.19727958,
53 | 23.47459217,
54 | 26.12384057,
55 | 29.78303507,
56 | 25.96888223,
57 | 29.14073823,
58 | 26.04369592,
59 | 34.18996367,
60 | 32.28924005,
61 | 27.42284396,
62 | 72.69207879,
63 | 33.05316347,
64 | 36.52276972,
65 | 49.2551479,
66 | 35.33439632,
67 | 24.07252457,
68 | 31.67153709,
69 | 27.81699478,
70 | 25.38021219,
71 | 24.31759259,
72 | 23.13586161,
73 | 48.40724678,
74 | 48.57969818,
75 | 31.92596006,
76 | 43.3679231,
77 | 34.32925819,
78 | 51.78908089,
79 | 34.49778584,
80 | 27.56236198,
81 | 48.34273194,
82 | 57.50829097,
83 | 50.66038226,
84 | 54.68701352,
85 | 35.77103116,
86 | 43.21886784,
87 | 40.07615759,
88 | 49.98658004,
89 | 43.13352883,
90 | 40.28520774,
91 | 46.28910294])
92 | np.testing.assert_allclose(results.cov_params,
93 | [[1.70280610e-02, -6.18628383e-04, -2.21386966e-04],
94 | [-6.18628383e-04, 2.61733917e-05, 6.77496445e-06],
95 | [-2.21386966e-04, 6.77496445e-06, 3.75463502e-06]])
96 | np.testing.assert_allclose(results.std_err, [0.13049161, 0.00511599,
97 | 0.00193769], atol=1.0e-8)
98 | np.testing.assert_allclose(
99 | results.pvalues, [
100 | 2.02901657e-198, 2.07052532e-002, 1.46788805e-012])
101 | np.testing.assert_allclose(results.tvalues, [30.0524361, 2.31331634,
102 | -7.07748998])
103 | np.testing.assert_allclose(results.resid, [28.73168426, -
104 | 5.15022766, -
105 | 14.06142973, -
106 | 1.13799739, -
107 | 5.76119226, -
108 | 13.6836241, 19.35406297, 2.91722003, 12.09610418, 58.80272042, -
109 | 3.47459217, -
110 | 6.12384057, 12.21696493, 17.03111777, -
111 | 11.14073823, -
112 | 7.04369592, 7.81003633, 27.71075995, 3.57715604, 8.30792121, -
113 | 13.05316347, -
114 | 6.52276972, -
115 | 1.2551479, 17.66560368, -
116 | 6.07252457, -
117 | 11.67153709, 6.18300522, -
118 | 2.38021219, 7.68240741, -
119 | 1.13586161, -
120 | 16.40724678, -
121 | 8.57969818, -
122 | 7.92596006, -
123 | 15.3679231, -
124 | 7.32925819, -
125 | 15.78908089, 8.50221416, -
126 | 4.56236198, -
127 | 8.34273194, 4.49170903, -
128 | 8.66038226, -
129 | 10.68701352, -
130 | 9.77103116, -
131 | 9.21886784, -
132 | 12.07615759, 26.01341996, -
133 | 1.13352883, -
134 | 13.28520774, -
135 | 10.28910294])
136 | self.assertAlmostEqual(results.deviance, 230.46013824817649)
137 | self.assertAlmostEqual(results.llf, -247.42592089969378)
138 | self.assertAlmostEqual(results.AIC, 500.85184179938756)
139 | self.assertAlmostEqual(results.D2, 0.388656011675)
140 | self.assertAlmostEqual(results.adj_D2, 0.36207583826952761)
141 |
142 |
143 | if __name__ == '__main__':
144 | unittest.main()
145 |
--------------------------------------------------------------------------------
/spint/tests/test_dispersion.py:
--------------------------------------------------------------------------------
1 |
2 | """
3 | Tests for regressiom based dispersion tests (Cameron & Trivedi, 2013)
4 |
5 | Cameron, Colin A. & Trivedi, Pravin K. (2013) Regression Analysis of Count Data.
6 | Camridge University Press: New York, New York.
7 |
8 | """
9 |
10 | __author__ = 'Taylor Oshan tayoshan@gmail.com'
11 |
12 | import unittest
13 | import numpy as np
14 | import libpysal
15 | from spglm.family import Poisson
16 | from ..count_model import CountModel
17 | from ..dispersion import phi_disp, alpha_disp
18 |
19 |
20 | class TestDispersion(unittest.TestCase):
21 |
22 | def setUp(self):
23 | db = libpysal.io.open(libpysal.examples.get_path('columbus.dbf'), 'r')
24 | y = np.array(db.by_col("HOVAL"))
25 | y = np.reshape(y, (49, 1))
26 | self.y = np.round(y).astype(int)
27 | X = []
28 | X.append(db.by_col("INC"))
29 | X.append(db.by_col("CRIME"))
30 | self.X = np.array(X).T
31 |
32 | def test_Dispersion(self):
33 | model = CountModel(self.y, self.X, family=Poisson())
34 | results = model.fit('GLM')
35 | phi = phi_disp(results)
36 | alpha1 = alpha_disp(results)
37 | alpha2 = alpha_disp(results, lambda x: x**2)
38 | np.testing.assert_allclose(phi, [5.39968689, 2.3230411, 0.01008847],
39 | atol=1.0e-8)
40 | np.testing.assert_allclose(alpha1, [4.39968689, 2.3230411,
41 | 0.01008847], atol=1.0e-8)
42 | np.testing.assert_allclose(alpha2, [0.10690133, 2.24709978,
43 | 0.01231683], atol=1.0e-8)
44 |
45 |
46 | if __name__ == '__main__':
47 | unittest.main()
48 |
--------------------------------------------------------------------------------
/spint/tests/test_universal.py:
--------------------------------------------------------------------------------
1 | """
2 | Tests for universal spatial interaction models.
3 |
4 | Test data is the Austria migration dataset used in Dennet's (2012) practical
5 | primer on spatial interaction modeling. The data was made avialable through the
6 | following dropbox link: http://dl.dropbox.com/u/8649795/AT_Austria.csv.
7 | The data has been pre-filtered so that there are no intra-zonal flows.
8 |
9 | Dennett, A. (2012). Estimating flows between geographical locations: get me
10 | started in spatial interaction modelling (Working Paper No. 184).
11 | UCL: Citeseer.
12 | """
13 |
14 | __author__ = 'Tyler Hoffman tylerhoff1@gmail.com'
15 |
16 | import unittest
17 | import numpy as np
18 | from scipy.stats import pearsonr
19 | from ..universal import Lenormand, Radiation, PWO
20 | np.random.seed(123456)
21 |
22 |
23 | class TestUniversal(unittest.TestCase):
24 | """ Tests for universal models """
25 |
26 | def setUp(self):
27 | self.f = np.array([0, 1131, 1887, 69, 738, 98,
28 | 31, 43, 19, 1633, 0, 14055, 416,
29 | 1276, 1850, 388, 303, 159, 2301, 20164,
30 | 0, 1080, 1831, 1943, 742, 674, 407,
31 | 85, 379, 1597, 0, 1608, 328, 317,
32 | 469, 114, 762, 1110, 2973, 1252, 0,
33 | 1081, 622, 425, 262, 196, 2027, 3498, 346,
34 | 1332, 0, 2144, 821, 274, 49, 378, 1349,
35 | 310, 851, 2117, 0, 630, 106, 87, 424,
36 | 978, 490, 670, 577, 546, 0, 569,
37 | 33, 128, 643, 154, 328, 199, 112, 587, 0])
38 |
39 | self.o = np.array(['AT11', 'AT11', 'AT11', 'AT11', 'AT11', 'AT11',
40 | 'AT11', 'AT11', 'AT11', 'AT12', 'AT12', 'AT12',
41 | 'AT12', 'AT12', 'AT12', 'AT12', 'AT12', 'AT12',
42 | 'AT13', 'AT13', 'AT13', 'AT13', 'AT13', 'AT13',
43 | 'AT13', 'AT13', 'AT13', 'AT21', 'AT21', 'AT21',
44 | 'AT21', 'AT21', 'AT21', 'AT21', 'AT21', 'AT21',
45 | 'AT22', 'AT22', 'AT22', 'AT22', 'AT22', 'AT22',
46 | 'AT22', 'AT22', 'AT22', 'AT31', 'AT31', 'AT31',
47 | 'AT31', 'AT31', 'AT31', 'AT31', 'AT31', 'AT31',
48 | 'AT32', 'AT32', 'AT32', 'AT32', 'AT32', 'AT32',
49 | 'AT32', 'AT32', 'AT32', 'AT33', 'AT33', 'AT33',
50 | 'AT33', 'AT33', 'AT33', 'AT33', 'AT33', 'AT33',
51 | 'AT34', 'AT34', 'AT34', 'AT34', 'AT34', 'AT34',
52 | 'AT34', 'AT34', 'AT34'])
53 |
54 | self.d = np.array(['AT11', 'AT12', 'AT13', 'AT21', 'AT22', 'AT31',
55 | 'AT32', 'AT33', 'AT34', 'AT11', 'AT12', 'AT13',
56 | 'AT21', 'AT22', 'AT31', 'AT32', 'AT33', 'AT34',
57 | 'AT11', 'AT12', 'AT13', 'AT21', 'AT22', 'AT31',
58 | 'AT32', 'AT33', 'AT34', 'AT11', 'AT12', 'AT13',
59 | 'AT21', 'AT22', 'AT31', 'AT32', 'AT33', 'AT34',
60 | 'AT11', 'AT12', 'AT13', 'AT21', 'AT22', 'AT31',
61 | 'AT32', 'AT33', 'AT34', 'AT11', 'AT12', 'AT13',
62 | 'AT21', 'AT22', 'AT31', 'AT32', 'AT33', 'AT34',
63 | 'AT11', 'AT12', 'AT13', 'AT21', 'AT22', 'AT31',
64 | 'AT32', 'AT33', 'AT34', 'AT11', 'AT12', 'AT13',
65 | 'AT21', 'AT22', 'AT31', 'AT32', 'AT33', 'AT34',
66 | 'AT11', 'AT12', 'AT13', 'AT21', 'AT22', 'AT31',
67 | 'AT32', 'AT33', 'AT34'])
68 |
69 | self.dij = np.array([0, 103, 84, 221, 132, 215, 247, 391, 505,
70 | 103, 0, 46, 217, 130, 141, 201, 344, 454,
71 | 84, 46, 0, 250, 159, 186, 244, 288, 498,
72 | 221, 217, 250, 0, 92, 152, 93, 195, 306,
73 | 132, 130, 159, 92, 0, 125, 122, 262, 376,
74 | 215, 141, 186, 152, 125, 0, 82, 208, 315,
75 | 247, 201, 244, 93, 122, 82, 0, 145, 259,
76 | 391, 344, 388, 195, 262, 208, 145, 0, 114,
77 | 505, 454, 498, 306, 376, 315, 259, 114, 0])
78 |
79 | self.o_var = np.array([4016, 4016, 4016, 4016, 4016, 4016,
80 | 4016, 4016, 4016, 20080, 20080, 20080,
81 | 20080, 20080, 20080, 20080, 20080, 20080,
82 | 29142, 29142, 29142, 29142, 29142, 29142,
83 | 29142, 29142, 29142, 4897, 4897, 4897,
84 | 4897, 4897, 4897, 4897, 4897, 4897,
85 | 8487, 8487, 8487, 8487, 8487, 8487,
86 | 8487, 8487, 8487, 10638, 10638, 10638,
87 | 10638, 10638, 10638, 10638, 10638, 10638,
88 | 5790, 5790, 5790, 5790, 5790, 5790,
89 | 5790, 5790, 5790, 4341, 4341, 4341,
90 | 4341, 4341, 4341, 4341, 4341, 4341,
91 | 2184, 2184, 2184, 2184, 2184, 2184,
92 | 2184, 2184, 2184])
93 |
94 | self.d_var = np.array([5146, 25741, 26980, 4117, 8634, 8193,
95 | 4902, 3952, 1910, 5146, 25741, 26980, 4117,
96 | 8634, 8193, 4902, 3952, 1910, 5146, 25741,
97 | 26980, 4117, 8634, 8193, 4902, 3952, 1910,
98 | 5146, 25741, 26980, 4117, 8634, 8193, 4902,
99 | 3952, 1910, 5146, 25741, 26980, 4117, 8634,
100 | 8193, 4902, 3952, 1910, 5146, 25741, 26980,
101 | 4117, 8634, 8193, 4902, 3952, 1910,
102 | 5146, 25741, 26980, 4117, 8634, 8193,
103 | 4902, 3952, 1910, 5146, 25741, 26980, 4117,
104 | 8634, 8193, 4902, 3952, 1910, 5146, 25741,
105 | 26980, 4117, 8634, 8193, 4902, 3952, 1910])
106 |
107 | self.xlocs = np.array([47.1537, 48.1081, 48.2082, 46.7222, 47.3593,
108 | 48.0259, 47.8095, 47.2537, 47.2497])
109 |
110 | self.ylocs = np.array([16.2689, 15.805, 16.3738, 14.1806, 14.47,
111 | 13.9724, 13.055, 11.6015, 9.9797])
112 |
113 | def ready(self):
114 | N = 9
115 | outflows = self.o_var[0::N]
116 | inflows = self.d_var[0:N]
117 | locs = np.zeros((N, 2))
118 | locs[:, 0] = self.xlocs
119 | locs[:, 1] = self.ylocs
120 | dists = np.reshape(self.dij, (N, N), order='C')
121 | T_obs = np.reshape(self.f, (N, N), order='C')
122 |
123 | return outflows, inflows, locs, dists, T_obs
124 |
125 | def test_Lenormand(self):
126 | outflows, inflows, locs, dists, T_obs = self.ready()
127 |
128 | # Lenormand paper's model
129 | model = Lenormand(inflows, outflows, dists)
130 | T_L = model.flowmat()
131 | np.testing.assert_almost_equal(
132 | pearsonr(T_L.flatten(), T_obs.flatten()),
133 | (-0.0728415, 0.5181216)
134 | )
135 |
136 | def test_Radiation(self):
137 | outflows, inflows, locs, dists, T_obs = self.ready()
138 |
139 | # Radiation model -- requires locations of each node
140 | model = Radiation(inflows, outflows, dists, locs, locs)
141 | T_R = model.flowmat()
142 | np.testing.assert_almost_equal(
143 | pearsonr(T_R.flatten(), T_obs.flatten()),
144 | (0.05384603805950201, 0.6330568989373918)
145 | )
146 |
147 | def test_PWO(self):
148 | outflows, inflows, locs, dists, T_obs = self.ready()
149 |
150 | # PWO model
151 | model = PWO(inflows, outflows, dists, locs, locs)
152 | T_P = model.flowmat()
153 | np.testing.assert_almost_equal(
154 | pearsonr(T_P.flatten(), T_obs.flatten()),
155 | (0.23623562773229048, 0.033734908271368574)
156 | )
157 |
158 |
159 | if __name__ == '__main__':
160 | unittest.main()
161 |
--------------------------------------------------------------------------------
/spint/tests/test_vec_SA.py:
--------------------------------------------------------------------------------
1 | """
2 | Tests for analysis of spatial autocorrelation within vectors
3 |
4 | """
5 |
6 | __author__ = 'Taylor Oshan tayoshan@gmail.com'
7 |
8 | import unittest
9 | import numpy as np
10 | from libpysal.weights.distance import DistanceBand
11 | from ..vec_SA import VecMoran
12 |
13 |
14 | class TestVecMoran(unittest.TestCase):
15 | """Tests VecMoran class"""
16 |
17 | def setUp(self):
18 | self.vecs = np.array([[1, 55, 60, 100, 500],
19 | [2, 60, 55, 105, 501],
20 | [3, 500, 55, 155, 500],
21 | [4, 505, 60, 160, 500],
22 | [5, 105, 950, 105, 500],
23 | [6, 155, 950, 155, 499]])
24 | self.origins = self.vecs[:, 1:3]
25 | self.dests = self.vecs[:, 3:5]
26 |
27 | def test_origin_focused_A(self):
28 | wo = DistanceBand(
29 | self.origins,
30 | threshold=9999,
31 | alpha=-1.5,
32 | binary=False)
33 | np.random.seed(1)
34 | vmo = VecMoran(self.vecs, wo, focus='origin', rand='A')
35 | self.assertAlmostEquals(vmo.I, 0.645944594367)
36 | self.assertAlmostEquals(vmo.p_z_sim, 0.03898650733809228)
37 |
38 | def test_dest_focused_A(self):
39 | wd = DistanceBand(self.dests, threshold=9999, alpha=-1.5, binary=False)
40 | np.random.seed(1)
41 | vmd = VecMoran(self.vecs, wd, focus='destination', rand='A')
42 | self.assertAlmostEquals(vmd.I, -0.764603695022)
43 | self.assertAlmostEquals(vmd.p_z_sim, 0.149472673677)
44 |
45 | def test_origin_focused_B(self):
46 | wo = DistanceBand(
47 | self.origins,
48 | threshold=9999,
49 | alpha=-1.5,
50 | binary=False)
51 | np.random.seed(1)
52 | vmo = VecMoran(self.vecs, wo, focus='origin', rand='B')
53 | self.assertAlmostEquals(vmo.I, 0.645944594367)
54 | self.assertAlmostEquals(vmo.p_z_sim, 0.02944612633233532)
55 |
56 | def test_dest_focused_B(self):
57 | wd = DistanceBand(self.dests, threshold=9999, alpha=-1.5, binary=False)
58 | np.random.seed(1)
59 | vmd = VecMoran(self.vecs, wd, focus='destination', rand='B')
60 | self.assertAlmostEquals(vmd.I, -0.764603695022)
61 | self.assertAlmostEquals(vmd.p_z_sim, 0.12411761124197379)
62 |
63 |
64 | if __name__ == '__main__':
65 | unittest.main()
66 |
--------------------------------------------------------------------------------
/spint/universal.py:
--------------------------------------------------------------------------------
1 | """
2 | Implementations of universal spatial interaction models: Lenormand's
3 | model, radiation model, and population-weighted opportunities.
4 |
5 | References
6 | ----------
7 | Lenormand, M., Huet, S., Gargiulo, F., and Deffuant, G. (2012). "A Universal
8 | Model of Commuting Networks." PLOS One, 7, 10.
9 |
10 | Simini, F., Gonzalez, M. C., Maritan, A., Barabasi, A.-L. (2012). "A universal
11 | model for mobility and migration patterns." Nature, 484, 96-100.
12 |
13 | Yan, X.-Y., Zhao, C., Fan, Y., Di, Z., and Wang, W.-X. (2014). "Universal
14 | predictability of mobility patterns in cities." Journal of the Royal
15 | Society Interface, 11, 100.
16 | """
17 |
18 | __author__ = 'Tyler Hoffman tylerhoff1@gmail.com'
19 |
20 | from abc import ABC, abstractmethod
21 | import numpy as np
22 | import pandas as pd
23 | from scipy.stats import pearsonr
24 |
25 |
26 | class Universal(ABC):
27 | """
28 | Base class for all the universal models as they all have similar
29 | underlying structures. For backend design purposes, not practical use.
30 |
31 | Parameters
32 | ----------
33 | inflows : array of reals
34 | N x 1, observed flows into each location
35 | outflows : array of reals
36 | M x 1, observed flows out of each location
37 | dists : matrix of reals
38 | N x M, pairwise distances between each location
39 |
40 | Attributes
41 | ----------
42 | N : integer
43 | number of origins
44 | M : integer
45 | number of destinations
46 | flowmat : abstract method
47 | estimates flows, implemented by children
48 | """
49 | def __init__(self, inflows, outflows, dists):
50 | self.N = len(outflows) # number of origins
51 | self.M = len(inflows) # number of destinations
52 | self.outflows = outflows.copy() # list of origin outflows
53 | self.inflows = inflows.copy() # list of destination inflows
54 | self.dists = dists.copy() # list of distances
55 |
56 | @abstractmethod
57 | def flowmat(self): pass
58 |
59 |
60 | class Lenormand(Universal):
61 | """
62 | Universal model based off of Lenormand et al. 2012,
63 | "A Universal Model of Commuting Networks".
64 |
65 | Parameters
66 | ----------
67 | inflows : array of reals
68 | N x 1, observed flows into each location
69 | outflows : array of reals
70 | M x 1, observed flows out of each location
71 | dists : matrix of reals
72 | N x M, pairwise distances between each location
73 | beta : scalar
74 | real, universal parameter for the model
75 | avg_sa : scalar
76 | real, average surface area of units
77 |
78 | Attributes
79 | ----------
80 | N : integer
81 | number of origins
82 | M : integer
83 | number of destinations
84 | calibrate : method
85 | calibrates beta using constants from the paper
86 | flowmat : method
87 | estimates flows via the Lenormand model
88 | """
89 |
90 | def __init__(self, inflows, outflows, dists, beta=1, avg_sa=None):
91 | super().__init__(inflows, outflows, dists)
92 | self.beta = self.calibrate(avg_sa) if avg_sa is not None else beta
93 |
94 | def calibrate(self, avg_sa):
95 | # Constants from the paper
96 | nu = 0.177
97 | alpha = 3.15 * 10**(-4)
98 | self.beta = alpha*avg_sa**(-nu)
99 |
100 | def flowmat(self):
101 | # Builds the matrix T from the parameter beta and a matrix of distances
102 | T = np.zeros((self.N, self.M))
103 |
104 | # Copy class variables so as not to modify
105 | sIN = self.inflows.copy()
106 | sOUT = self.outflows.copy()
107 |
108 | # Assembly loop
109 | while sum(sOUT) > 0:
110 | # Pick random nonzero sOUT
111 | idxs, = np.where(sOUT > 0)
112 | i = np.random.choice(idxs)
113 |
114 | # Compute Pij's (not memoized b/c it changes on iteration)
115 | Pi = np.multiply(sIN, np.exp(-self.beta*self.dists[i, :])) / \
116 | np.dot(sIN, np.exp(-self.beta*self.dists[i, :]))
117 |
118 | # Pick random j according to Pij
119 | j = np.random.choice(range(self.N), p=Pi)
120 |
121 | # Adjust values
122 | T[i, j] += 1
123 | sIN[j] -= 1
124 | sOUT[i] -= 1
125 |
126 | return T
127 |
128 |
129 | class Radiation(Universal):
130 | """
131 | Universal model based off of Simini et al. 2012,
132 | "A universal model for mobility and migration patterns".
133 | Requires slightly more data than Lenormand.
134 |
135 | Parameters
136 | ----------
137 | inflows : array of reals
138 | N x 1, observed flows into each location
139 | outflows : array of reals
140 | M x 1, observed flows out of each location
141 | dists : matrix of reals
142 | N x M, pairwise distances between each location
143 | ilocs : array of reals
144 | N x 2, inflow node locations
145 | olocs : array of reals
146 | M x 2, outflow node locations
147 |
148 | Attributes
149 | ----------
150 | N : integer
151 | number of origins
152 | M : integer
153 | number of destinations
154 | flowmat : method
155 | estimates flows via the Radiation model
156 | """
157 |
158 | def __init__(self, inflows, outflows, dists, ilocs, olocs):
159 | super().__init__(inflows, outflows, dists)
160 | self.ilocs = ilocs.copy()
161 | self.olocs = olocs.copy()
162 |
163 | def _from_origin(self, idx, total_origins):
164 | # Sort destinations by distance from origin
165 | didxs = np.argsort(self.dists[idx, :])
166 | inflows = self.inflows[didxs]
167 |
168 | # Normalization
169 | F = 1.0/(1.0 - self.outflows[idx]/total_origins)
170 |
171 | pop_in_radius = 0
172 | flows = np.zeros((self.M,))
173 | for j in range(self.M):
174 | # Use formula from the paper
175 | flows[j] = F*(self.outflows[idx]*inflows[j]) / \
176 | ((self.outflows[idx] + pop_in_radius) *
177 | (self.outflows[idx] + inflows[j] + pop_in_radius))
178 |
179 | pop_in_radius += inflows[j]
180 |
181 | # Unsort list
182 | return flows[didxs.argsort()]
183 |
184 | def flowmat(self):
185 | # Builds the OD matrix T from the inputted data
186 | T = np.zeros((self.N, self.M))
187 | total_origins = sum(self.outflows)
188 |
189 | for i in range(self.N):
190 | T[i, :] = self._from_origin(i, total_origins)
191 |
192 | return T
193 |
194 |
195 | class PWO(Universal):
196 | """
197 | Population-weighted opportunies (PWO) implements a
198 | universal model based off of Yan et al. 2014,
199 | "Universal predictability of mobility patterns in cities".
200 | Requires slightly more data than Lenormand.
201 |
202 | Parameters
203 | ----------
204 | inflows : array of reals
205 | N x 1, observed flows into each location
206 | outflows : array of reals
207 | M x 1, observed flows out of each location
208 | dists : matrix of reals
209 | N x M, pairwise distances between each location
210 | ilocs : array of reals
211 | N x 2, inflow node locations
212 | olocs : array of reals
213 | M x 2, outflow node locations
214 |
215 | Attributes
216 | ----------
217 | N : integer
218 | number of origins
219 | M : integer
220 | number of destinations
221 | flowmat : method
222 | estimates flows via the Radiation model
223 | """
224 |
225 | def __init__(self, inflows, outflows, dists, ilocs, olocs):
226 | super().__init__(inflows, outflows, dists)
227 | self.ilocs = ilocs.copy()
228 | self.olocs = olocs.copy()
229 | self.total = sum(inflows) # total population of the system
230 |
231 | def _from_destination(self, jdx):
232 | # Sort origins by distance from destination
233 | didxs = np.argsort(self.dists[jdx, :])
234 | outflows = self.outflows[didxs]
235 | pop_in_radius = self.inflows[jdx] # here pop_in_radius includes endpts
236 | flows = np.zeros((self.N,))
237 |
238 | # Loop over origins
239 | for i in range(self.N):
240 | pop_in_radius += outflows[i] # add other endpt
241 |
242 | # Compute denominator
243 | denom = 0
244 | denom_pop_in_radius = outflows[i]
245 | for k in range(self.M): # loop over destinations
246 | denom_pop_in_radius += self.inflows[k]
247 | if k != i:
248 | denom += self.inflows[k] * (1/denom_pop_in_radius -
249 | 1/self.total)
250 |
251 | # Use formula from the paper
252 | flows[i] = self.inflows[jdx]*(1/pop_in_radius - 1/self.total)/denom
253 |
254 | # Unsort list
255 | return flows[didxs.argsort()]
256 |
257 | def flowmat(self):
258 | # Builds the OD matrix T from the inputted data
259 | T = np.zeros((self.N, self.M))
260 |
261 | for j in range(self.M):
262 | T[:, j] = self._from_destination(j)
263 |
264 | return T
265 |
266 |
267 | def test():
268 | # Read data from Austria file
269 | N = 9
270 | austria = pd.read_csv('austria.csv')
271 | modN = austria[austria.index % N == 0]
272 | outflows = modN['Oi'].values
273 | inflows = austria['Dj'].head(n=N).values
274 | locs = np.zeros((N, 2))
275 | locs[:, 0] = modN['X'].values
276 | locs[:, 1] = modN['Y'].values
277 | dists = np.reshape(austria['Dij'].values, (N, N), order='C')
278 | T_obs = np.reshape(austria['Data'].values, (N, N), order='C')
279 |
280 | # Lenormand paper's model
281 | model = Lenormand(inflows, outflows, dists)
282 | T_L = model.flowmat()
283 | print(pearsonr(T_L.flatten(), T_obs.flatten()))
284 |
285 | # Radiation model -- requires locations of each node
286 | model = Radiation(inflows, outflows, dists, locs, locs)
287 | T_R = model.flowmat()
288 | print(pearsonr(T_R.flatten(), T_obs.flatten()))
289 |
290 | # PWO model
291 | model = PWO(inflows, outflows, dists, locs, locs)
292 | T_P = model.flowmat()
293 | print(pearsonr(T_P.flatten(), T_obs.flatten()))
294 |
295 |
296 | if __name__ == '__main__':
297 | test()
298 |
--------------------------------------------------------------------------------
/spint/utils.py:
--------------------------------------------------------------------------------
1 | """
2 | Useful functions for analyzing spatial interaction data.
3 | """
4 |
5 | __author__ = "Taylor Oshan tayoshan@gmail.com"
6 |
7 | from scipy import sparse as sp
8 | import numpy as np
9 | from collections import defaultdict
10 | from functools import partial
11 | from itertools import count
12 |
13 |
14 | def CPC(model):
15 | """
16 | Common part of commuters based on Sorensen index
17 | Lenormand et al. 2012
18 | """
19 | y = model.y
20 | try:
21 | yhat = model.yhat.resahpe((-1, 1))
22 | except BaseException:
23 | yhat = model.mu((-1, 1))
24 | N = model.n
25 | YYhat = np.hstack([y, yhat])
26 | NCC = np.sum(np.min(YYhat, axis=1))
27 | NCY = np.sum(Y)
28 | NCYhat = np.sum(yhat)
29 | return (N * NCC) / (NCY + NCYhat)
30 |
31 |
32 | def sorensen(model):
33 | """
34 | Sorensen similarity index
35 |
36 | For use on spatial interaction models; N = sample size
37 | rather than N = number of locations and normalized by N instead of N**2
38 | """
39 | try:
40 | y = model.y.reshape((-1, 1))
41 | except BaseException:
42 | y = model.f.reshape((-1, 1))
43 | try:
44 | yhat = model.yhat.reshape((-1, 1))
45 | except BaseException:
46 | yhat = model.mu.reshape((-1, 1))
47 | N = model.n
48 | YYhat = np.hstack([y, yhat])
49 | num = 2.0 * np.min(YYhat, axis=1)
50 | den = yhat + y
51 | return (1.0 / N) * (np.sum(num.reshape((-1, 1)) / den.reshape((-1, 1))))
52 |
53 |
54 | def srmse(model):
55 | """
56 | Standardized root mean square error
57 | """
58 | n = float(model.n)
59 | try:
60 | y = model.y.reshape((-1, 1)).astype(float)
61 | except BaseException:
62 | y = model.f.reshape((-1, 1)).astype(float)
63 | try:
64 | yhat = model.yhat.reshape((-1, 1)).astype(float)
65 | except BaseException:
66 | yhat = model.mu.reshape((-1, 1)).astype(float)
67 | srmse = ((np.sum((y - yhat)**2) / n)**.5) / (np.sum(y) / n)
68 | return srmse
69 |
70 |
71 | def spcategorical(index):
72 | '''
73 | Returns a dummy matrix given an array of categorical variables.
74 | Parameters
75 | ----------
76 | n_cat_ids : array
77 | A 1d vector of the categorical labels for n observations.
78 |
79 | Returns
80 | --------
81 | dummy : array
82 | A sparse matrix of dummy (indicator/binary) variables for the
83 | categorical data.
84 |
85 | '''
86 | if np.squeeze(index).ndim == 1:
87 | id_set = np.unique(index)
88 | n = len(index)
89 | # if index.dtype.type is not np.int_:
90 | mapper = defaultdict(partial(next, count()))
91 | [mapper[each] for each in id_set]
92 | index = [mapper[each] for each in index]
93 | indptr = np.arange(n + 1, dtype=int)
94 | return sp.csr_matrix((np.ones(n), index, indptr))
95 | else:
96 | raise IndexError("The index %s is not understood" % index)
97 |
98 |
99 | #old and slow
100 | """
101 | def spcategorical(n_cat_ids):
102 | '''
103 | Returns a dummy matrix given an array of categorical variables.
104 | Parameters
105 | ----------
106 | n_cat_ids : array
107 | A 1d vector of the categorical labels for n observations.
108 |
109 | Returns
110 | --------
111 | dummy : array
112 | A sparse matrix of dummy (indicator/binary) variables for the
113 | categorical data.
114 |
115 | '''
116 | if np.squeeze(n_cat_ids).ndim == 1:
117 | cat_set = np.unique(n_cat_ids)
118 | n = len(n_cat_ids)
119 | index = [np.where(cat_set == id)[0].tolist()[0] for id in n_cat_ids]
120 | indptr = np.arange(n+1, dtype=int)
121 | return sp.csr_matrix((np.ones(n), index, indptr))
122 | else:
123 | raise IndexError("The index %s is not understood" % col)
124 | """
125 |
--------------------------------------------------------------------------------
/spint/vec_SA.py:
--------------------------------------------------------------------------------
1 | """
2 | Classes for statistics for testing hypotheses of spatial autocorrelation amongst
3 | vectors.
4 | """
5 |
6 | _author_ = "Taylor Oshan tayoshan@gmail.com, Levi Wolf levi.john.wolf@gmail.com"
7 |
8 | import numpy as np
9 | import scipy.stats as stats
10 | from libpysal.weights.distance import DistanceBand
11 |
12 | PERMUTATIONS = 99
13 |
14 |
15 | class VecMoran:
16 | """Moran's I Global Autocorrelation Statistic For Vectors
17 |
18 | Parameters
19 | ----------
20 | y : array
21 | variable measured across n origin-destination vectors
22 | w : W
23 | spatial weights instance
24 | focus : string
25 | denotes whether to calculate the statistic with a focus on
26 | spatial proximity between origins or destinations; default
27 | is 'origin' but option include:
28 |
29 | 'origin' | 'destination'
30 |
31 | rand : string
32 | denote which randomization technqiue to use for
33 | significance testing; default is 'A' but options are:
34 |
35 | 'A': transate entire vector
36 | 'B': shuffle points and redraw vectors
37 |
38 | permutations : int
39 | number of random permutations for calculation of
40 | pseudo-p_values
41 | two_tailed : boolean
42 | If True (default) analytical p-values for Moran are two
43 | tailed, otherwise if False, they are one-tailed.
44 | Attributes
45 | ----------
46 | y : array
47 | original variable
48 | w : W obejct
49 | original w object
50 | n : integer
51 | number of vectors
52 | o : array
53 | n x 2; 2D coordinates of vector origins
54 | d : array
55 | n x 2: 2D coordinates of vector destinations
56 | alpha : scalar
57 | distance decay parameter harvested from W object
58 | binary : boolean
59 | True is all entries in W > 0 are set to 1; False if if they
60 | are inverse distance weighted; default is False; attribute is
61 | harvested from W object
62 | build_sp : boolean
63 | True if W object is build using sparse distance matrix and
64 | False if it is built using a dense distance matrix; attribute
65 | is harvested from W object
66 | threshold : scalar
67 | all values larger than threshold are set 0 in W object;
68 | attribute is harvested from W object
69 | silent : boolean
70 | True if island warnings are silent and False if they are not;
71 | default is False; attribute is harvested from W object
72 | focus : string
73 | denotes whether to calculate the statistic with a focus on
74 | spatial proximity between origins or destinations; default
75 | is 'origin' but option include:
76 |
77 | 'origin' | 'destination'
78 |
79 | rand : string
80 | denote which randomization technqiue to use for
81 | significance testing; default is 'A' but options are:
82 |
83 | 'A': transate entire vector
84 | 'B': shuffle points and redraw vectors
85 |
86 | permutations : int
87 | number of permutations
88 | I : float
89 | value of vector-based Moran's I
90 | EI : float
91 | expected value under randomization assumption
92 | VI_rand : float
93 | variance of I under randomization assumption
94 | seI_rand : float
95 | standard deviation of I under randomization assumption
96 | z_rand : float
97 | z-value of I under randomization assumption
98 | p_rand : float
99 | p-value of I under randomization assumption
100 | two_tailed : boolean
101 | If True p_norm and p_rand are two-tailed, otherwise they
102 | are one-tailed.
103 | sim : array
104 | (if permutations>0)
105 | vector of I values for permuted samples
106 | p_sim : array
107 | (if permutations>0)
108 | p-value based on permutations (one-tailed)
109 | null: spatial randomness
110 | alternative: the observed I is extreme if
111 | it is either extremely greater or extremely lower
112 | than the values obtained based on permutations
113 | EI_sim : float
114 | (if permutations>0)
115 | average value of I from permutations
116 | VI_sim : float
117 | (if permutations>0)
118 | variance of I from permutations
119 | seI_sim : float
120 | (if permutations>0)
121 | standard deviation of I under permutations.
122 | z_sim : float
123 | (if permutations>0)
124 | standardized I based on permutations
125 | p_z_sim : float
126 | (if permutations>0)
127 | p-value based on standard normal approximation from
128 | permutations
129 |
130 | Examples
131 | --------
132 | >>> import numpy as np
133 | >>> np.random.seed(1)
134 | >>> from libpysal.weights import DistanceBand
135 | >>> from spint.vec_SA import VecMoran
136 | >>> vecs = np.array([[1, 55, 60, 100, 500],
137 | ... [2, 60, 55, 105, 501],
138 | ... [3, 500, 55, 155, 500],
139 | ... [4, 505, 60, 160, 500],
140 | ... [5, 105, 950, 105, 500],
141 | ... [6, 155, 950, 155, 499]])
142 | >>> origins = vecs[:, 1:3]
143 | >>> dests = vecs[:, 3:5]
144 | >>> wo = DistanceBand(origins, threshold=9999, alpha=-1.5, binary=False)
145 | >>> wd = DistanceBand(dests, threshold=9999, alpha=-1.5, binary=False)
146 |
147 | #randomization technique A
148 | >>> vmo = VecMoran(vecs, wo, focus='origin', rand='A')
149 | >>> vmd = VecMoran(vecs, wd, focus='destination', rand='A')
150 | >>> vmo.I
151 | 0.6459445943670211
152 | >>> vmo.p_z_sim
153 | 0.03898650733809228
154 | >>> vmd.I
155 | -0.7646036950223406
156 | >>> vmd.p_z_sim
157 | 0.11275129553163704
158 |
159 | #randomization technique B
160 | >>> vmo = VecMoran(vecs, wo, focus='origin', rand='B')
161 | >>> vmd = VecMoran(vecs, wd, focus='destination', rand='B')
162 | >>> vmo.I
163 | 0.6459445943670211
164 | >>> vmo.p_z_sim
165 | 0.05087923006558356
166 | >>> vmd.I
167 | -0.7646036950223406
168 | >>> vmd.p_z_sim
169 | 0.1468368983650693
170 |
171 | """
172 |
173 | def __init__(
174 | self,
175 | y,
176 | w,
177 | focus='origin',
178 | rand='A',
179 | permutations=PERMUTATIONS,
180 | two_tailed=True):
181 | self.y = y
182 | self.o = y[:, 1:3]
183 | self.d = y[:, 3:5]
184 | self.focus = focus
185 | self.rand = rand
186 | self.permutations = permutations
187 | self.two_tailed = two_tailed
188 | if isinstance(w, DistanceBand):
189 | self.w = w
190 | else:
191 | raise TypeError('Spatial weight, W, must be of type DistanceBand')
192 | try:
193 | self.threshold = w.threshold
194 | self.alpha = w.alpha
195 | self.build_sp = w.build_sp
196 | self.binary = w.binary
197 | self.silence_warnings = w.silence_warnings
198 | except BaseException:
199 | raise AttributeError('W object missing necessary attributes: '
200 | 'threshold, alpha, binary, build_sp, silent')
201 |
202 | self.__moments()
203 | self.I = self.__calc(self.z)
204 | self.z_rand = (self.I - self.EI) / self.seI_rand
205 |
206 | if self.z_rand > 0:
207 | self.p_rand = 1 - stats.norm.cdf(self.z_rand)
208 | else:
209 | self.p_rand = stats.norm.cdf(self.z_rand)
210 |
211 | if self.two_tailed:
212 | self.p_rand *= 2.
213 |
214 | if permutations:
215 | if self.rand.upper() == 'A':
216 | sim = self.__rand_vecs_A(self.focus)
217 | elif self.rand.upper() == 'B':
218 | sim = self.__rand_vecs_B(self.focus)
219 | else:
220 | raise ValueError(
221 | "Parameter 'rand' must take a value of either 'A' or 'B'")
222 |
223 | self.sim = sim = np.array(sim)
224 | above = sim >= self.I
225 | larger = above.sum()
226 | if (self.permutations - larger) < larger:
227 | larger = self.permutations - larger
228 | self.p_sim = (larger + 1.) / (permutations + 1.)
229 | self.EI_sim = sim.sum() / permutations
230 | self.seI_sim = np.array(sim).std()
231 | self.VI_sim = self.seI_sim ** 2
232 | self.z_sim = (self.I - self.EI_sim) / self.seI_sim
233 | if self.z_sim > 0:
234 | self.p_z_sim = 1 - stats.norm.cdf(self.z_sim)
235 | else:
236 | self.p_z_sim = stats.norm.cdf(self.z_sim)
237 |
238 | def __moments(self):
239 | self.n = len(self.y)
240 | xObar = self.o[:, 0].mean()
241 | yObar = self.o[:, 1].mean()
242 | xDbar = self.d[:, 0].mean()
243 | yDbar = self.d[:, 1].mean()
244 | u = (self.y[:, 3] - self.y[:, 1]) - (xDbar - xObar)
245 | v = (self.y[:, 4] - self.y[:, 2]) - (yDbar - yObar)
246 | z = np.outer(u, u) + np.outer(v, v)
247 | self.z = z
248 | self.uv2ss = np.sum(np.dot(u, u) + np.dot(v, v))
249 | self.EI = -1. / (self.n - 1)
250 | n = self.n
251 | s1 = self.w.s1
252 | W = self.w.s0
253 | s2 = self.w.s2
254 |
255 | v_num = n * n * s1 - n * s2 + 3 * W * W
256 | v_den = (n - 1) * (n + 1) * W * W
257 |
258 | a2 = np.sum(np.dot(u, u)) / n
259 | b2 = np.sum(np.dot(v, v)) / n
260 | m2 = a2 + b2
261 | a4 = np.sum(np.dot(np.dot(u, u), np.dot(u, u))) / n
262 | b4 = np.sum(np.dot(np.dot(v, u), np.dot(v, v))) / n
263 | n1 = a2**2 * ((n**2 - 3 * n + 3) * s1 - n * s2 + 3 * W**2)
264 | n2 = a4 * ((n**2 - n) * s1 - 2 * n * s2 + 6 * W**2)
265 | n3 = b2**2 * ((n**2 - 3 * n + 3) * s1 - n * s2 + 3 * W**2)
266 | n4 = b4 * ((n**2 - n) * s1 - 2 * n * s2 + 6 * W**2)
267 | d = (n - 1) * (n - 2) * (n - 3)
268 | self.VI_rand = 1 / (W**2 * m2**2) * \
269 | ((n1 - n2) / d + (n3 - n4) / d) + \
270 | ((a2 * b2) - m2**2) / (m2**2 * (n - 1)**2)
271 | self.seI_rand = self.VI_rand ** (1 / 2.)
272 |
273 | def __calc(self, z):
274 | zl = self._slag(self.w, z)
275 | inum = np.sum(zl)
276 | return self.n / self.w.s0 * inum / self.uv2ss
277 |
278 | def _newD(self, oldO, oldD, newO):
279 | oldOX, oldOY = oldO[:, 0], oldO[:, 1]
280 | oldDX, oldDY = oldD[:, 0], oldD[:, 1]
281 | newOX, newOY = newO[:, 0], newO[:, 1]
282 | deltaX = newOX - oldOX
283 | deltaY = newOY - oldOY
284 | newDX = oldDX + deltaX
285 | newDY = oldDY + deltaY
286 | return np.hstack([newDX.reshape((-1, 1)), newDY.reshape((-1, 1))])
287 |
288 | def _newO(self, oldO, oldD, newD):
289 | oldOX, oldOY = oldO[:, 0], oldO[:, 1]
290 | oldDX, oldDY = oldD[:, 0], oldD[:, 1]
291 | newDX, newDY = newD[:, 0], newD[:, 1]
292 | deltaX = newDX - oldDX
293 | deltaY = newDY - oldDY
294 | newOX = oldOX + deltaX
295 | newOY = oldOY + deltaY
296 | return np.hstack([newOX.reshape((-1, 1)), newOY.reshape((-1, 1))])
297 |
298 | def __rand_vecs_A(self, focus):
299 | if focus.lower() == 'origin':
300 | newOs = [
301 | np.random.permutation(
302 | self.o) for i in range(
303 | self.permutations)]
304 | sims = [np.hstack([np.arange(self.n).reshape((-1, 1)), newO,
305 | self._newD(self.o, self.d, newO)]) for newO in newOs]
306 | Ws = [
307 | DistanceBand(
308 | newO,
309 | threshold=self.threshold,
310 | alpha=self.alpha,
311 | binary=self.binary,
312 | build_sp=self.build_sp,
313 | silence_warnings=self.silence_warnings) for newO in newOs]
314 | elif focus.lower() == 'destination':
315 | newDs = [
316 | np.random.permutation(
317 | self.d) for i in range(
318 | self.permutations)]
319 | sims = [np.hstack([np.arange(self.n).reshape(
320 | (-1, 1)), self._newO(self.o, self.d, newD), newD]) for newD in newDs]
321 | Ws = [
322 | DistanceBand(
323 | newD,
324 | threshold=self.threshold,
325 | alpha=self.alpha,
326 | binary=self.binary,
327 | build_sp=self.build_sp,
328 | silence_warnings=self.silence_warnings) for newD in newDs]
329 | else:
330 | raise ValueError(
331 | "Parameter 'focus' must take value of either 'origin' or 'destination.'")
332 |
333 | VMs = [VecMoran(y, Ws[i], permutations=None)
334 | for i, y in enumerate(sims)]
335 | sim = [VM.__calc(VM.z) for VM in VMs]
336 | return sim
337 |
338 | def __rand_vecs_B(self, focus):
339 | if focus.lower() == 'origin':
340 | sims = [
341 | np.hstack(
342 | [
343 | np.arange(
344 | self.n).reshape(
345 | (-1,
346 | 1)),
347 | self.o,
348 | np.random.permutation(
349 | self.d)]) for i in range(
350 | self.permutations)]
351 | elif focus.lower() == 'destination':
352 | sims = [
353 | np.hstack(
354 | [
355 | np.arange(
356 | self.n).reshape(
357 | (-1,
358 | 1)),
359 | np.random.permutation(
360 | self.o),
361 | self.d]) for i in range(
362 | self.permutations)]
363 | else:
364 | raise ValueError(
365 | "Parameter 'focus' must take value of either 'origin' or 'destination.'")
366 | sims = [VecMoran(y, self.w, permutations=None) for y in sims]
367 | sim = [VM.__calc(VM.z) for VM in sims]
368 | return sim
369 |
370 | def _slag(self, w, y):
371 | """
372 | Dense spatial lag operator for.
373 | If w is row standardized, returns the average of each observation's neighbors;
374 | if not, returns the weighted sum of each observation's neighbors.
375 | Parameters
376 | ----------
377 | w : W
378 | object
379 | y : array
380 | numpy array with dimensionality conforming to w (see examples)
381 | Returns
382 | -------
383 | wy : array
384 | array of numeric values for the spatial lag
385 | """
386 | return np.array(w.sparse.todense()) * y
387 |
--------------------------------------------------------------------------------