Merge branch 'develop' into add-errors-on-null-only
This commit is contained in:
+20
-3
@@ -23,9 +23,15 @@ REPLACEMENTS = -e 's/@@VERSION@@/$(EXTVERSION)/g'
|
||||
|
||||
$(DATA): $(SOURCES_DATA)
|
||||
$(SED) $(REPLACEMENTS) $(SOURCES_DATA_DIR)/*.sql > $@
|
||||
ifeq ($(PG_PARALLEL), 0)
|
||||
$(eval TMPFILE := $(shell mktemp /tmp/$@.XXXXXXXXXX))
|
||||
$(SED) -e 's/PARALLEL \= [A-Z]*,/''/g' -e 's/PARALLEL [A-Z]*/''/g' $@ > $(TMPFILE);
|
||||
mv $(TMPFILE) $@
|
||||
endif
|
||||
|
||||
|
||||
TEST_DIR = test
|
||||
REGRESS = $(notdir $(basename $(wildcard $(TEST_DIR)/sql/*test.sql)))
|
||||
REGRESS = $(sort $(notdir $(basename $(wildcard $(TEST_DIR)/sql/*test.sql))))
|
||||
REGRESS_OPTS = --inputdir='$(TEST_DIR)' --outputdir='$(TEST_DIR)'
|
||||
|
||||
PG_CONFIG = pg_config
|
||||
@@ -50,7 +56,18 @@ test: installcheck
|
||||
release: ../../release/$(EXTENSION).control $(SOURCES_DATA)
|
||||
$(SED) $(REPLACEMENTS) $(SOURCES_DATA_DIR)/*.sql > ../../release/$(EXTENSION)--$(EXTVERSION).sql
|
||||
|
||||
# Install the current relese into the PostgreSQL extensions directory
|
||||
deploy:
|
||||
# If needed remove PARALLEL tags from the release files
|
||||
release_remove_parallel_deploy:
|
||||
ifeq ($(PG_PARALLEL), 0)
|
||||
for n in $(wildcard ../../release/*.sql); do \
|
||||
$(eval TMPFILE := $(shell mktemp /tmp/XXXXXXXXXX)) \
|
||||
$(SED) -e 's/PARALLEL \= [A-Z]*,/''/g' -e 's/PARALLEL [A-Z]*/''/g' $$n > $(TMPFILE); \
|
||||
mv $(TMPFILE) $$n; \
|
||||
done
|
||||
endif
|
||||
|
||||
# Install the current release into the PostgreSQL extensions directory
|
||||
deploy: release_remove_parallel_deploy
|
||||
$(INSTALL_DATA) ../../release/$(EXTENSION).control '$(DESTDIR)$(datadir)/extension/'
|
||||
$(INSTALL_DATA) ../../release/*.sql '$(DESTDIR)$(datadir)/extension/'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
comment = 'CartoDB Spatial Analysis extension'
|
||||
default_version = '0.5.1'
|
||||
default_version = '0.6.1'
|
||||
requires = 'plpythonu, postgis'
|
||||
superuser = true
|
||||
schema = cdb_crankshaft
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
CREATE OR REPLACE FUNCTION cdb_crankshaft_version()
|
||||
RETURNS text AS $$
|
||||
SELECT '@@VERSION@@'::text;
|
||||
$$ language 'sql' STABLE STRICT;
|
||||
$$ language 'sql' IMMUTABLE STRICT PARALLEL SAFE;
|
||||
|
||||
-- Internal identifier of the installed extension instence
|
||||
-- e.g. 'dev' for current development version
|
||||
CREATE OR REPLACE FUNCTION _cdb_crankshaft_internal_version()
|
||||
RETURNS text AS $$
|
||||
SELECT installed_version FROM pg_available_extensions where name='crankshaft' and pg_available_extensions IS NOT NULL;
|
||||
$$ language 'sql' STABLE STRICT;
|
||||
$$ language 'sql' STABLE STRICT PARALLEL SAFE;
|
||||
|
||||
@@ -6,4 +6,4 @@ _cdb_random_seeds (seed_value INTEGER) RETURNS VOID
|
||||
AS $$
|
||||
from crankshaft import random_seeds
|
||||
random_seeds.set_random_seeds(seed_value)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
@@ -8,7 +8,7 @@ CREATE OR REPLACE FUNCTION
|
||||
end if;
|
||||
return array_cat(current_state,current_row) ;
|
||||
END
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
-- Create aggregate if it did not exist
|
||||
DO $$
|
||||
@@ -24,6 +24,7 @@ BEGIN
|
||||
CREATE AGGREGATE CDB_PyAgg(NUMERIC[]) (
|
||||
SFUNC = CDB_PyAggS,
|
||||
STYPE = Numeric[],
|
||||
PARALLEL = SAFE,
|
||||
INITCOND = "{}"
|
||||
);
|
||||
END IF;
|
||||
|
||||
@@ -33,7 +33,7 @@ AS $$
|
||||
target_ids,
|
||||
model_params)
|
||||
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL RESTRICTED;
|
||||
|
||||
CREATE OR REPLACE FUNCTION
|
||||
CDB_CreateAndPredictSegment (
|
||||
@@ -50,4 +50,4 @@ AS $$
|
||||
from crankshaft.segmentation import create_and_predict_segment
|
||||
model_params = {'n_estimators': n_estimators, 'max_depth':max_depth, 'subsample' : subsample, 'learning_rate': learning_rate, 'min_samples_leaf' : min_samples_leaf}
|
||||
return create_and_predict_segment(query,variable_name,target_table, model_params)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
@@ -27,7 +27,7 @@ BEGIN
|
||||
RETURN QUERY
|
||||
SELECT g.* FROM t, s, CDB_Gravity(t_id, t_geom, t_weight, s_id, s_geom, s_pop, target, radius, minval) g;
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
$$ language plpgsql VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION CDB_Gravity(
|
||||
IN t_id bigint[],
|
||||
@@ -112,4 +112,4 @@ BEGIN
|
||||
p.targ_id = target AND
|
||||
p.sourc_id = d.sourc_id;
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
@@ -24,7 +24,7 @@ BEGIN
|
||||
RETURN output;
|
||||
END;
|
||||
$$
|
||||
language plpgsql IMMUTABLE;
|
||||
language plpgsql VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION CDB_SpatialInterpolation(
|
||||
IN geomin geometry[],
|
||||
@@ -141,4 +141,4 @@ BEGIN
|
||||
|
||||
END;
|
||||
$$
|
||||
language plpgsql IMMUTABLE;
|
||||
language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
@@ -167,7 +167,7 @@ BEGIN
|
||||
clipped_voro;
|
||||
RETURN geomout;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
/** ----------------------------------------------------------------------------------------
|
||||
* @function : FindCircle
|
||||
@@ -181,6 +181,7 @@ $$ language plpgsql IMMUTABLE;
|
||||
* or NULL if three points do not form a circle.
|
||||
* @history : Simon Greener - Feb 2012 - Original coding.
|
||||
* Rafa de la Torre - Aug 2016 - Small fix for type checking
|
||||
* Raul Marin - Sept 2017 - Remove unnecessary NULL checks and set function categories
|
||||
* @copyright : Simon Greener @ 2012
|
||||
* Licensed under a Creative Commons Attribution-Share Alike 2.5 Australia License. (http://creativecommons.org/licenses/by-sa/2.5/au/)
|
||||
**/
|
||||
@@ -203,10 +204,6 @@ DECLARE
|
||||
v_dF NUMERIC;
|
||||
v_dG NUMERIC;
|
||||
BEGIN
|
||||
IF ( p_pt1 IS NULL OR p_pt2 IS NULL OR p_pt3 IS NULL ) THEN
|
||||
RAISE EXCEPTION 'All supplied points must be not null.';
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
IF ( ST_GeometryType(p_pt1) <> 'ST_Point' OR
|
||||
ST_GeometryType(p_pt2) <> 'ST_Point' OR
|
||||
ST_GeometryType(p_pt3) <> 'ST_Point' ) THEN
|
||||
@@ -232,5 +229,5 @@ BEGIN
|
||||
RETURN ST_SetSRID(ST_MakePoint(v_CX, v_CY, v_radius),ST_Srid(p_pt1));
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql VOLATILE STRICT;
|
||||
LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
||||
|
||||
|
||||
+12
-12
@@ -15,7 +15,7 @@ AS $$
|
||||
moran = Moran()
|
||||
return moran.global_stat(subquery, column_name, w_type,
|
||||
num_ngbrs, permutations, geom_col, id_col)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I Local (internal function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -34,7 +34,7 @@ AS $$
|
||||
# TODO: use named parameters or a dictionary
|
||||
return moran.local_stat(subquery, column_name, w_type,
|
||||
num_ngbrs, permutations, geom_col, id_col)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I Local (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -52,7 +52,7 @@ AS $$
|
||||
SELECT moran, quads, significance, rowid, vals
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocal(subquery, column_name, w_type, num_ngbrs, permutations, geom_col, id_col);
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I only for HH and HL (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -71,7 +71,7 @@ AS $$
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocal(subquery, column_name, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
WHERE quads IN ('HH', 'HL');
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I only for LL and LH (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -90,7 +90,7 @@ AS $$
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocal(subquery, attr, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
WHERE quads IN ('LL', 'LH');
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I only for LH and HL (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -109,7 +109,7 @@ AS $$
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocal(subquery, attr, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
WHERE quads IN ('HL', 'LH');
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I Global Rate (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -129,7 +129,7 @@ AS $$
|
||||
# TODO: use named parameters or a dictionary
|
||||
return moran.global_rate_stat(subquery, numerator, denominator, w_type,
|
||||
num_ngbrs, permutations, geom_col, id_col)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
|
||||
-- Moran's I Local Rate (internal function)
|
||||
@@ -150,7 +150,7 @@ AS $$
|
||||
moran = Moran()
|
||||
# TODO: use named parameters or a dictionary
|
||||
return moran.local_rate_stat(subquery, numerator, denominator, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I Local Rate (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -170,7 +170,7 @@ AS $$
|
||||
SELECT moran, quads, significance, rowid, vals
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocalRate(subquery, numerator, denominator, w_type, num_ngbrs, permutations, geom_col, id_col);
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I Local Rate only for HH and HL (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -191,7 +191,7 @@ AS $$
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocalRate(subquery, numerator, denominator, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
WHERE quads IN ('HH', 'HL');
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I Local Rate only for LL and LH (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -212,7 +212,7 @@ AS $$
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocalRate(subquery, numerator, denominator, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
WHERE quads IN ('LL', 'LH');
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- Moran's I Local Rate only for LH and HL (public-facing function)
|
||||
CREATE OR REPLACE FUNCTION
|
||||
@@ -233,4 +233,4 @@ AS $$
|
||||
FROM cdb_crankshaft._CDB_AreasOfInterestLocalRate(subquery, numerator, denominator, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
WHERE quads IN ('HL', 'LH');
|
||||
|
||||
$$ LANGUAGE SQL;
|
||||
$$ LANGUAGE SQL VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
@@ -7,7 +7,7 @@ RETURNS table (cartodb_id integer, cluster_no integer) as $$
|
||||
kmeans = Kmeans()
|
||||
return kmeans.spatial(query, no_clusters, no_init)
|
||||
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION CDB_WeightedMeanS(state Numeric[],the_geom GEOMETRY(Point, 4326), weight NUMERIC)
|
||||
@@ -30,7 +30,7 @@ BEGIN
|
||||
RETURN Array[newX,newY,newW];
|
||||
|
||||
END
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION CDB_WeightedMeanF(state Numeric[])
|
||||
RETURNS GEOMETRY AS
|
||||
@@ -42,7 +42,7 @@ BEGIN
|
||||
RETURN ST_SETSRID(ST_MakePoint(state[1]/state[3], state[2]/state[3]),4326);
|
||||
END IF;
|
||||
END
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
-- Create aggregate if it did not exist
|
||||
DO $$
|
||||
@@ -59,6 +59,7 @@ BEGIN
|
||||
SFUNC = CDB_WeightedMeanS,
|
||||
FINALFUNC = CDB_WeightedMeanF,
|
||||
STYPE = Numeric[],
|
||||
PARALLEL = SAFE,
|
||||
INITCOND = "{0.0,0.0,0.0}"
|
||||
);
|
||||
END IF;
|
||||
|
||||
@@ -27,7 +27,7 @@ AS $$
|
||||
|
||||
## TODO: use named parameters or a dictionary
|
||||
return markov.spatial_trend(subquery, time_cols, num_classes, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- input table format: identical to above but in a predictable format
|
||||
-- Sample function call:
|
||||
|
||||
@@ -91,7 +91,7 @@ BEGIN
|
||||
RETURN ST_transform(ST_Centroid(best_c), 4326);
|
||||
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
|
||||
-- signed distance point to polygon with holes
|
||||
@@ -120,4 +120,4 @@ BEGIN
|
||||
dist := dist * within::numeric;
|
||||
RETURN dist;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
@@ -64,4 +64,4 @@ BEGIN
|
||||
END LOOP;
|
||||
RETURN QUERY SELECT unnest(geotemp ) as geomout, unnest(coltemp ) as colout;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
@@ -40,4 +40,4 @@ BEGIN
|
||||
END LOOP;
|
||||
RETURN QUERY SELECT unnest(gs) as geomout, unnest(coltemp ) as colout;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
@@ -14,6 +14,6 @@ AS $$
|
||||
from crankshaft.clustering import Getis
|
||||
getis = Getis()
|
||||
return getis.getis_ord(subquery, column_name, w_type, num_ngbrs, permutations, geom_col, id_col)
|
||||
$$ LANGUAGE plpythonu;
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
-- TODO: make a version that accepts the values as arrays
|
||||
|
||||
@@ -9,7 +9,7 @@ BEGIN
|
||||
RETURN column_value > threshold;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE ;
|
||||
|
||||
-- Find outliers by a percentage above the threshold
|
||||
-- TODO: add symmetric option? `is_symmetric boolean DEFAULT false`
|
||||
@@ -38,7 +38,7 @@ BEGIN
|
||||
unnest(ids) As rowid;
|
||||
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
-- Find outliers above a given number of standard deviations from the mean
|
||||
|
||||
@@ -72,4 +72,4 @@ BEGIN
|
||||
SELECT unnest(out_vals) As is_outlier,
|
||||
unnest(ids) As rowid;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
@@ -139,8 +139,7 @@ BEGIN
|
||||
where final.bin is not null
|
||||
;
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
|
||||
$$ language plpgsql VOLATILE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
-- =====================================================================
|
||||
@@ -205,4 +204,4 @@ BEGIN
|
||||
RETURN output;
|
||||
END;
|
||||
$$
|
||||
language plpgsql;
|
||||
language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
@@ -35,4 +35,4 @@ BEGIN
|
||||
INTO result;
|
||||
RETURN result;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
CREATE OR REPLACE FUNCTION
|
||||
CDB_GWR(subquery text, dep_var text, ind_vars text[],
|
||||
bw numeric default null, fixed boolean default False,
|
||||
kernel text default 'bisquare', geom_col text default 'the_geom',
|
||||
id_col text default 'cartodb_id')
|
||||
RETURNS table(coeffs JSON, stand_errs JSON, t_vals JSON,
|
||||
filtered_t_vals JSON, predicted numeric,
|
||||
residuals numeric, r_squared numeric, bandwidth numeric,
|
||||
rowid bigint)
|
||||
AS $$
|
||||
|
||||
from crankshaft.regression import GWR
|
||||
|
||||
gwr = GWR()
|
||||
|
||||
return gwr.gwr(subquery, dep_var, ind_vars, bw, fixed, kernel, geom_col, id_col)
|
||||
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION
|
||||
CDB_GWR_Predict(subquery text, dep_var text, ind_vars text[],
|
||||
bw numeric default null, fixed boolean default False,
|
||||
kernel text default 'bisquare',
|
||||
geom_col text default 'the_geom',
|
||||
id_col text default 'cartodb_id')
|
||||
RETURNS table(coeffs JSON, stand_errs JSON, t_vals JSON,
|
||||
r_squared numeric, predicted numeric, rowid bigint)
|
||||
AS $$
|
||||
|
||||
from crankshaft.regression import GWR
|
||||
gwr = GWR()
|
||||
|
||||
return gwr.gwr_predict(subquery, dep_var, ind_vars, bw, fixed, kernel, geom_col, id_col)
|
||||
|
||||
$$ LANGUAGE plpythonu VOLATILE PARALLEL UNSAFE;
|
||||
@@ -51,4 +51,4 @@ BEGIN
|
||||
RETURN ST_Collect(points);
|
||||
END;
|
||||
$$
|
||||
LANGUAGE plpgsql VOLATILE;
|
||||
LANGUAGE plpgsql VOLATILE PARALLEL RESTRICTED;
|
||||
|
||||
@@ -93,7 +93,7 @@ BEGIN
|
||||
|
||||
RETURN;
|
||||
END
|
||||
$$ LANGUAGE 'plpgsql' IMMUTABLE;
|
||||
$$ LANGUAGE 'plpgsql' IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
--
|
||||
-- Calculate the equal interval bins for a given column
|
||||
@@ -131,7 +131,7 @@ BEGIN
|
||||
END LOOP;
|
||||
RETURN reply;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
--
|
||||
-- Determine the Heads/Tails classifications from a numeric array
|
||||
@@ -178,7 +178,7 @@ BEGIN
|
||||
END LOOP;
|
||||
RETURN reply;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
--
|
||||
-- Determine the Jenks classifications from a numeric array
|
||||
@@ -299,7 +299,7 @@ BEGIN
|
||||
|
||||
RETURN (best_result)[2:array_upper(best_result, 1)];
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql VOLATILE PARALLEL RESTRICTED;
|
||||
|
||||
|
||||
|
||||
@@ -399,7 +399,7 @@ BEGIN
|
||||
RETURN array_prepend(gvf, reply);
|
||||
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE PARALLEL SAFE;
|
||||
|
||||
|
||||
--
|
||||
@@ -444,4 +444,4 @@ BEGIN
|
||||
END LOOP;
|
||||
RETURN reply;
|
||||
END;
|
||||
$$ language plpgsql IMMUTABLE;
|
||||
$$ language plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION plpythonu;
|
||||
CREATE EXTENSION postgis VERSION '2.2.2';
|
||||
CREATE EXTENSION postgis;
|
||||
-- Create role publicuser if it does not exist
|
||||
DO
|
||||
$$
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
-- test of Geographically Weighted Regression (GWR)
|
||||
SET client_min_messages TO WARNING;
|
||||
\set ECHO none
|
||||
rowid|coeff_pctrural|std_errs_pctrural|t_vals_pctrural|predicted|residuals|r_squared|bandwidth
|
||||
13001|-0.0852|0.0220|-3.8678|8.8071|-0.6071|0.5218|90.0
|
||||
13027|-0.0719|0.0221|-3.2506|9.9673|-0.8673|0.5443|90.0
|
||||
13027|-0.0719|0.0221|-3.2506|9.9673|-0.8673|0.5443|90.0
|
||||
13039|-0.0959|0.0241|-3.9755|13.4802|0.0198|0.6269|90.0
|
||||
13231|-0.1383|0.0181|-7.6634|8.5520|0.7480|0.6337|90.0
|
||||
13293|-0.1207|0.0184|-6.5553|12.9930|-3.9930|0.6446|90.0
|
||||
13321|-0.0720|0.0204|-3.5337|8.2738|-1.9738|0.5573|90.0
|
||||
(7 rows)
|
||||
Vendored
+199
@@ -0,0 +1,199 @@
|
||||
SET client_min_messages TO WARNING;
|
||||
\set ECHO none
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
-- Data from:
|
||||
-- https://github.com/TaylorOshan/pysal/blob/1d6af33bda46b1d623f70912c56155064463383f/pysal/examples/georgia/GData_utm.csv
|
||||
|
||||
CREATE TABLE g_utm_testing (
|
||||
cartodb_id bigint,
|
||||
the_geom geometry(Geometry, 2239),
|
||||
pctblack numeric,
|
||||
pctpov numeric,
|
||||
pctbach numeric,
|
||||
pctrural numeric,
|
||||
x numeric,
|
||||
y numeric,
|
||||
areakey int
|
||||
);
|
||||
|
||||
COPY g_utm_testing (cartodb_id, the_geom, pctblack, pctpov, pctbach, pctrural, x, y, areakey) FROM stdin;
|
||||
122 0101000020BF080000CDCCCCCC2AEB2A410000000043F74A41 34.4500000000000028 27.3000000000000007 8.59999999999999964 72.5999999999999943 882069.400000000023 3534470 13271
|
||||
9 0101000020BF0800009A999999786823410000000080684D41 0.349999999999999978 14.5999999999999996 8 96.5 635964.300000000047 3854592 13083
|
||||
30 0101000020BF0800009A9999990ACF294100000080E5174D41 9.89000000000000057 16.5 9.5 87.2000000000000028 845701.300000000047 3813323 13119
|
||||
121 0101000020BF08000000000000B67D2F4100000080AA6F4B41 14.0299999999999994 12.6999999999999993 7.59999999999999964 89.0999999999999943 1031899 3596117 13103
|
||||
139 0101000020BF080000CDCCCCCCFF4B2B410000008038A54A41 25.4600000000000009 22.5 11.0999999999999996 64.5999999999999943 894463.900000000023 3492465 13069
|
||||
78 0101000020BF08000066666666FB632741000000802BF44B41 34.0300000000000011 16.3000000000000007 10 63.6000000000000014 766461.699999999953 3663959 13171
|
||||
103 0101000020BF0800009A999999BEB62741000000809A594B41 58.7199999999999989 29.1999999999999993 10.0999999999999996 65.5999999999999943 777055.300000000047 3584821 13193
|
||||
104 0101000020BF0800009A999999E52C27410000008039874B41 43.2100000000000009 29.5 7.09999999999999964 100 759410.800000000047 3608179 13269
|
||||
160 0101000020BF0800009A999999A3DC2541000000004D544A41 27.4800000000000004 22.1000000000000014 8.19999999999999929 100 716369.800000000047 3451034 13201
|
||||
99 0101000020BF08000033333333DCC3294100000080D56E4B41 22.3599999999999994 18.3000000000000007 10.3000000000000007 57.8999999999999986 844270.099999999977 3595691 13023
|
||||
16 0101000020BF08000033333333C4532741000000004B164D41 0.28999999999999998 12.8000000000000007 8.59999999999999964 100 764386.099999999977 3812502 13085
|
||||
34 0101000020BF080000CDCCCCCCFE622441000000000FB94C41 14.3000000000000007 16.3000000000000007 6.79999999999999982 66.5 668031.400000000023 3764766 13233
|
||||
37 0101000020BF08000066666666423825410000008006AC4C41 3.93999999999999995 8.80000000000000071 7.59999999999999964 93.7000000000000028 695329.199999999953 3758093 13223
|
||||
47 0101000020BF08000066666666B195254100000080D0774C41 7.62999999999999989 6.59999999999999964 12 26.6999999999999993 707288.699999999953 3731361 13097
|
||||
108 0101000020BF080000333333339AFA264100000000173D4B41 34.0900000000000034 19.8999999999999986 8 100 752973.099999999977 3570222 13249
|
||||
75 0101000020BF0800009A9999992EEC29410000008048F74B41 42.3900000000000006 17.5 13.3000000000000007 42.7000000000000028 849431.300000000047 3665553 13009
|
||||
83 0101000020BF08000066666666C39D2D4100000080E3C54B41 41.509999999999998 27.8000000000000007 7.70000000000000018 53.7999999999999972 970465.699999999953 3640263 13165
|
||||
91 0101000020BF080000333333339939254100000000ABA74B41 25.4899999999999984 13.6999999999999993 13.5999999999999996 95.7999999999999972 695500.599999999977 3624790 13145
|
||||
131 0101000020BF080000CDCCCCCC2AEB2A410000000043F74A41 34.4500000000000028 27.3000000000000007 8.59999999999999964 72.5999999999999943 882069.400000000023 3534470 13271
|
||||
136 0101000020BF0800009A99999959562A4100000000D8DB4A41 31.3299999999999983 22 7.59999999999999964 47 863020.800000000047 3520432 13017
|
||||
140 0101000020BF080000CDCCCCCCFF4B2B410000008038A54A41 25.4600000000000009 22.5 11.0999999999999996 64.5999999999999943 894463.900000000023 3492465 13069
|
||||
45 0101000020BF080000333333338034294100000000B35D4C41 34.740000000000002 15 11 73 825920.099999999977 3717990 13211
|
||||
58 0101000020BF080000000000003EBC27410000008062744C41 8.02999999999999936 6.20000000000000018 18.1000000000000014 59.2000000000000028 777759 3729605 13247
|
||||
66 0101000020BF0800009A999999401F2D410000000063364C41 41.9600000000000009 18.1999999999999993 17.3000000000000007 9.90000000000000036 954272.300000000047 3697862 13245
|
||||
67 0101000020BF080000CDCCCCCCA09B244100000080601E4C41 13.3800000000000008 19.1000000000000014 5.70000000000000018 100 675280.400000000023 3685569 13149
|
||||
74 0101000020BF080000CDCCCCCC6387254100000000842F4C41 22.5899999999999999 11.4000000000000004 13.3000000000000007 76.0999999999999943 705457.900000000023 3694344 13077
|
||||
112 0101000020BF0800009A999999C7662D410000008033294B41 29.1900000000000013 21.8999999999999986 6.5 79.2999999999999972 963427.800000000047 3560039 13267
|
||||
117 0101000020BF0800009A9999993E6A2841000000004E314B41 48.9799999999999969 32.8999999999999986 9.5 72.5999999999999943 800031.300000000047 3564188 13093
|
||||
127 0101000020BF080000CDCCCCCC209628410000008067FC4A41 40.6599999999999966 29 10 48.3999999999999986 805648.400000000023 3537103 13081
|
||||
166 0101000020BF08000066666666E4462841000000800E1B4A41 37.9299999999999997 22.6000000000000014 13.4000000000000004 55.2000000000000028 795506.199999999953 3421725 13275
|
||||
48 0101000020BF080000000000003EBC27410000008062744C41 8.02999999999999936 6.20000000000000018 18.1000000000000014 59.2000000000000028 777759 3729605 13247
|
||||
3 0101000020BF08000033333333A0B6274100000080AD704D41 0.100000000000000006 18.3000000000000007 10.0999999999999996 100 777040.099999999977 3858779 13291
|
||||
1 0101000020BF080000000000008B2A294100000080727C4D41 0.349999999999999978 13.5999999999999996 11.5999999999999996 100 824645.5 3864805 13241
|
||||
2 0101000020BF080000666666663B5A284100000000C08B4D41 0 14 11.4000000000000004 100 797981.699999999953 3872640 13281
|
||||
4 0101000020BF0800009A9999996F8F264100000000F67F4D41 0.0299999999999999989 17.1999999999999993 7.79999999999999982 100 739255.800000000047 3866604 13111
|
||||
18 0101000020BF08000033333333C5ED234100000000C0184D41 8.60999999999999943 14.5999999999999996 5.90000000000000036 77.4000000000000057 653026.599999999977 3813760 13055
|
||||
6 0101000020BF080000CDCCCCCC56F6244100000000D5694D41 4.05999999999999961 11.0999999999999996 12 70 686891.400000000023 3855274 13313
|
||||
5 0101000020BF0800009A999999F499254100000000B6674D41 0.260000000000000009 11.3000000000000007 5.5 89 707834.300000000047 3854188 13213
|
||||
7 0101000020BF080000CDCCCCCCCF7224410000000097774D41 0.910000000000000031 12 8.09999999999999964 43.6000000000000014 670055.900000000023 3862318 13047
|
||||
8 0101000020BF080000CDCCCCCC6C1B2441000000803B504D41 3.72999999999999998 12.8000000000000007 8.40000000000000036 44.7999999999999972 658870.400000000023 3842167 13295
|
||||
10 0101000020BF0800009A9999993C5C26410000008064554D41 0.260000000000000009 16.6000000000000014 8.59999999999999964 100 732702.300000000047 3844809 13123
|
||||
11 0101000020BF08000033333333CAFD284100000080DD4B4D41 5.41999999999999993 11.5999999999999996 12 88.5 818917.099999999977 3839931 13137
|
||||
12 0101000020BF08000033333333D3512841000000001F4E4D41 2.58999999999999986 12.5 13.5999999999999996 100 796905.599999999977 3841086 13311
|
||||
13 0101000020BF08000000000000F093274100000080363D4D41 1.40999999999999992 15.3000000000000007 11.0999999999999996 78.5999999999999943 772600 3832429 13187
|
||||
14 0101000020BF080000CDCCCCCCCBB2294100000080C1324D41 11.8100000000000005 17 13.0999999999999996 64.5 842085.900000000023 3827075 13257
|
||||
15 0101000020BF080000333333333A382541000000801B294D41 3.7799999999999998 11.0999999999999996 9.19999999999999929 79.7000000000000028 695325.099999999977 3822135 13129
|
||||
17 0101000020BF080000CDCCCCCCE235244100000000B0E94C41 13.5600000000000005 13.5999999999999996 13.6999999999999993 36.1000000000000014 662257.400000000023 3789664 13115
|
||||
19 0101000020BF0800009A9999990ACF294100000080E5174D41 9.89000000000000057 16.5 9.5 87.2000000000000028 845701.300000000047 3813323 13119
|
||||
20 0101000020BF080000666666662D65264100000000EE164D41 1.47999999999999998 12.8000000000000007 9 100 733846.699999999953 3812828 13227
|
||||
21 0101000020BF080000CDCCCCCCBB922A4100000080FF114D41 20.4100000000000001 14.1999999999999993 9.09999999999999964 73.7999999999999972 870749.900000000023 3810303 13147
|
||||
25 0101000020BF08000000000000075525410000000000F14C41 9.21000000000000085 10.6999999999999993 9 75.2000000000000028 699011.5 3793408 13015
|
||||
22 0101000020BF08000000000000673E28410000000068044D41 8.48000000000000043 10.5999999999999996 15.4000000000000004 81.0999999999999943 794419.5 3803344 13139
|
||||
23 0101000020BF0800009A999999EA00294100000000C00C4D41 3.49000000000000021 15.0999999999999996 6.40000000000000036 100 819317.300000000047 3807616 13011
|
||||
24 0101000020BF080000CDCCCCCC41682641000000005FF24C41 1.77000000000000002 6.09999999999999964 18.3999999999999986 57.7999999999999972 734240.900000000023 3794110 13057
|
||||
44 0101000020BF0800009A9999999B52244100000000E7894C41 6.46999999999999975 14.4000000000000004 7.5 67.7999999999999972 665933.800000000047 3740622 13143
|
||||
26 0101000020BF0800009A999999AA5B27410000008066E84C41 0 6.79999999999999982 15.5999999999999996 93.7000000000000028 765397.300000000047 3789005 13117
|
||||
27 0101000020BF080000666666666AD72A410000008068E14C41 29.9899999999999984 19.6999999999999993 8 70 879541.199999999953 3785425 13105
|
||||
28 0101000020BF0800003333333312E528410000008086DE4C41 9.58000000000000007 14.0999999999999996 9 78 815753.099999999977 3783949 13157
|
||||
29 0101000020BF0800009A999999FDE52941000000805EE14C41 8.32000000000000028 15.6999999999999993 9.69999999999999929 100 848638.800000000047 3785405 13195
|
||||
31 0101000020BF080000CDCCCCCC4064264100000000807B4C41 49.9200000000000017 18.3999999999999986 31.6000000000000014 4.20000000000000018 733728.400000000023 3733248 13121
|
||||
32 0101000020BF08000033333333359427410000000029B84C41 5.11000000000000032 4 29.6000000000000014 13.5999999999999996 772634.599999999977 3764306 13135
|
||||
33 0101000020BF0800003333333346872841000000808BC24C41 11.4399999999999995 14.6999999999999993 9.19999999999999929 64.5999999999999943 803747.099999999977 3769623 13013
|
||||
35 0101000020BF0800009A99999977582A410000008074A94C41 24.7399999999999984 16.1999999999999993 12.8000000000000007 100 863291.800000000047 3756777 13221
|
||||
36 0101000020BF0800009A9999994D1D26410000008041AA4C41 9.83999999999999986 5.59999999999999964 33 5.79999999999999982 724646.800000000047 3757187 13067
|
||||
38 0101000020BF08000033333333F9672941000000806CB54C41 26.2300000000000004 27 37.5 17.6000000000000014 832508.599999999977 3762905 13059
|
||||
46 0101000020BF08000033333333F5B624410000000071544C41 15.4600000000000009 14.4000000000000004 12 68.5 678778.599999999977 3713250 13045
|
||||
39 0101000020BF08000000000000B9322B4100000080C49B4C41 45.9399999999999977 22.6000000000000014 10.4000000000000004 59.6000000000000014 891228.5 3749769 13317
|
||||
40 0101000020BF08000000000000C90E2C410000000039A14C41 38.1899999999999977 17.8000000000000007 8.19999999999999929 100 919396.5 3752562 13181
|
||||
41 0101000020BF080000CDCCCCCC1F5A294100000080FB9D4C41 7.37000000000000011 7.90000000000000036 28.3999999999999986 95.2000000000000028 830735.900000000023 3750903 13219
|
||||
42 0101000020BF080000CDCCCCCC7F2B2741000000806A7F4C41 42.2299999999999969 9.90000000000000036 32.7000000000000028 2.5 759231.900000000023 3735253 13089
|
||||
43 0101000020BF0800009A999999006D284100000080F18D4C41 18.370000000000001 13.1999999999999993 9.40000000000000036 61.2000000000000028 800384.300000000047 3742691 13297
|
||||
49 0101000020BF0800009A999999321C2A41000000002D664C41 49.8900000000000006 25.1000000000000014 8.80000000000000071 75.7000000000000028 855577.300000000047 3722330 13133
|
||||
50 0101000020BF080000CDCCCCCC31FD2A4100000080BA5C4C41 61.3599999999999994 31.8999999999999986 5.59999999999999964 100 884376.900000000023 3717493 13265
|
||||
86 0101000020BF080000000000004E6B294100000000DEA54B41 45.9299999999999997 26 4.79999999999999982 100 832935 3623868 13289
|
||||
51 0101000020BF080000CDCCCCCC7FC32C4100000000BA654C41 10.9299999999999997 6.59999999999999964 23.8999999999999986 30.6000000000000014 942527.900000000023 3722100 13073
|
||||
87 0101000020BF08000066666666B4C72C4100000000AD974B41 32.5799999999999983 25.6999999999999993 9.09999999999999964 64.2000000000000028 943066.199999999953 3616602 13107
|
||||
52 0101000020BF080000CDCCCCCC5F352841000000001B614C41 22.3500000000000014 14.4000000000000004 9.5 76 793263.900000000023 3719734 13217
|
||||
53 0101000020BF080000CDCCCCCCC5012C4100000000885A4C41 36.3800000000000026 21.6000000000000014 10.4000000000000004 65.9000000000000057 917730.900000000023 3716368 13189
|
||||
55 0101000020BF080000CDCCCCCCC04C274100000000023A4C41 10.2400000000000002 6.09999999999999964 10.6999999999999993 76 763488.400000000023 3699716 13151
|
||||
54 0101000020BF080000333333338E8A2B4100000000533A4C41 60.2299999999999969 32.6000000000000014 4.20000000000000018 100 902471.099999999977 3699878 13301
|
||||
56 0101000020BF0800009A99999985C026410000000077514C41 23.8200000000000003 8.59999999999999964 14.6999999999999993 4.40000000000000036 745538.800000000047 3711726 13063
|
||||
57 0101000020BF0800009A999999401F2D410000000063364C41 41.9600000000000009 18.1999999999999993 17.3000000000000007 9.90000000000000036 954272.300000000047 3697862 13245
|
||||
59 0101000020BF080000666666669952264100000000C23B4C41 5.12999999999999989 2.60000000000000009 25.8000000000000007 53.8999999999999986 731468.699999999953 3700612 13113
|
||||
60 0101000020BF08000033333333A2A2284100000000FA304C41 34.7999999999999972 17.3999999999999986 10.8000000000000007 100 807249.099999999977 3695092 13159
|
||||
61 0101000020BF080000000000003EBC27410000008062744C41 8.02999999999999936 6.20000000000000018 18.1000000000000014 59.2000000000000028 777759 3729605 13247
|
||||
146 0101000020BF080000CDCCCCCCA951274100000080EFA84A41 50.1499999999999986 24.3999999999999986 17 10 764116.900000000023 3494367 13095
|
||||
142 0101000020BF0800009A9999994B1B2A41000000803AC04A41 30.5 27.1999999999999993 8.30000000000000071 63.3999999999999986 855461.800000000047 3506293 13155
|
||||
62 0101000020BF08000033333333D2A32941000000004B314C41 32.7899999999999991 16.3999999999999986 11.6999999999999993 66.5 840169.099999999977 3695254 13237
|
||||
63 0101000020BF080000CDCCCCCC6387254100000000842F4C41 22.5899999999999999 11.4000000000000004 13.3000000000000007 76.0999999999999943 705457.900000000023 3694344 13077
|
||||
64 0101000020BF0800009A9999995DA82A4100000080C2264C41 79.6400000000000006 30.1000000000000014 6.79999999999999982 100 873518.800000000047 3689861 13141
|
||||
65 0101000020BF08000066666666E0E02741000000004C1C4C41 35.4799999999999969 15.5999999999999996 7.20000000000000018 73.4000000000000057 782448.199999999953 3684504 13035
|
||||
68 0101000020BF0800009A999999C5B82B4100000000BC1E4C41 12.6899999999999995 16.8000000000000007 5.29999999999999982 100 908386.800000000047 3685752 13125
|
||||
69 0101000020BF0800003333333398332C410000000038FC4B41 55.9200000000000017 31.3000000000000007 6.20000000000000018 100 924108.099999999977 3668080 13163
|
||||
114 0101000020BF0800009A999999BFF52D4100000080393F4B41 33.8800000000000026 25.3999999999999986 8.59999999999999964 100 981727.800000000047 3571315 13109
|
||||
70 0101000020BF0800009A99999993A62D4100000000B1024C41 52.1899999999999977 30.3000000000000007 9.59999999999999964 72.2999999999999972 971593.800000000047 3671394 13033
|
||||
71 0101000020BF08000066666666C809274100000080521D4C41 29.0799999999999983 15.5999999999999996 11.0999999999999996 53.6000000000000014 754916.199999999953 3685029 13255
|
||||
72 0101000020BF0800009A999999E04D2B410000008023D64B41 51.8599999999999994 21.6000000000000014 9.80000000000000071 67.0999999999999943 894704.300000000047 3648583 13303
|
||||
73 0101000020BF0800009A999999BFD4254100000080F9EC4B41 44.6199999999999974 22.3999999999999986 6.70000000000000018 82.2999999999999972 715359.800000000047 3660275 13199
|
||||
76 0101000020BF0800009A999999F1D4244100000000EFEC4B41 30.0300000000000011 16.3000000000000007 13.5999999999999996 44 682616.800000000047 3660254 13285
|
||||
77 0101000020BF08000066666666851E284100000000A0ED4B41 31.7800000000000011 13.8000000000000007 12.9000000000000004 75.0999999999999943 790338.699999999953 3660608 13207
|
||||
79 0101000020BF08000033333333EE10294100000080B7EC4B41 25.6000000000000014 10.8000000000000007 12 81.9000000000000057 821367.099999999977 3660143 13169
|
||||
80 0101000020BF0800009A999999E9B52641000000804CF74B41 20.0399999999999991 13.4000000000000004 9.30000000000000071 100 744180.800000000047 3665561 13231
|
||||
92 0101000020BF080000CDCCCCCCBC002B4100000080DD754B41 33.3200000000000003 20.5 12 52.8999999999999986 884830.400000000023 3599291 13175
|
||||
89 0101000020BF08000066666666B9BA2B410000000039A74B41 33.8900000000000006 22.1999999999999993 4.90000000000000036 100 908636.699999999953 3624562 13167
|
||||
81 0101000020BF08000000000000F8A32E41000000001FC94B41 44.6899999999999977 22.8999999999999986 8.59999999999999964 79.2999999999999972 1004028 3641918 13251
|
||||
82 0101000020BF080000CDCCCCCC59352A410000008041C14B41 41.990000000000002 15.3000000000000007 8.80000000000000071 100 858796.900000000023 3637891 13319
|
||||
84 0101000020BF080000666666664AF4264100000000CCC34B41 27.7800000000000011 14.6999999999999993 9 65.2999999999999972 752165.199999999953 3639192 13293
|
||||
85 0101000020BF080000CDCCCCCC11B62841000000007ABE4B41 41.6799999999999997 19.1999999999999993 17 16.1000000000000014 809736.900000000023 3636468 13021
|
||||
88 0101000020BF080000CDCCCCCC13682641000000007DA44B41 62.3400000000000034 24.8999999999999986 7.09999999999999964 97.9000000000000057 734217.900000000023 3623162 13263
|
||||
90 0101000020BF0800000000000071E8274100000080D7A44B41 30.6600000000000001 14 5.70000000000000018 100 783416.5 3623343 13079
|
||||
98 0101000020BF080000CDCCCCCC516D2D4100000000FD744B41 30.9400000000000013 24.1000000000000014 9.90000000000000036 52.1000000000000014 964264.900000000023 3598842 13043
|
||||
95 0101000020BF080000CDCCCCCCDA5A28410000008001894B41 47.5300000000000011 24 15.1999999999999993 61.2999999999999972 798061.400000000023 3609091 13225
|
||||
93 0101000020BF0800009A999999E52C27410000008039874B41 43.2100000000000009 29.5 7.09999999999999964 100 759410.800000000047 3608179 13269
|
||||
120 0101000020BF0800009A99999931762541000000802C1B4B41 63.4600000000000009 31.3999999999999986 8 100 703256.800000000047 3552857 13259
|
||||
94 0101000020BF080000CDCCCCCCAE5C2E410000008036784B41 25.9499999999999993 27.5 19.8999999999999986 63.2000000000000028 994903.400000000023 3600493 13031
|
||||
96 0101000020BF080000CDCCCCCC4DD8284100000080CC644B41 21.8000000000000007 10.5999999999999996 16 20.8999999999999986 814118.900000000023 3590553 13153
|
||||
134 0101000020BF080000000000002F8327410000008050DB4A41 19.2199999999999989 12.5999999999999996 13.6999999999999993 78.2000000000000028 770455.5 3520161 13177
|
||||
97 0101000020BF08000000000000B67D2F4100000080AA6F4B41 14.0299999999999994 12.6999999999999993 7.59999999999999964 89.0999999999999943 1031899 3596117 13103
|
||||
100 0101000020BF080000666666664363254100000000CA734B41 37.9500000000000028 18.6000000000000014 16.6000000000000014 3.20000000000000018 700833.699999999953 3598228 13215
|
||||
101 0101000020BF080000333333334B0C2C4100000000D16D4B41 33.1000000000000014 27.1000000000000014 6.29999999999999982 53.2999999999999972 919077.599999999977 3595170 13283
|
||||
102 0101000020BF0800009A999999995D264100000080C4584B41 41.3200000000000003 28.1999999999999993 4.59999999999999964 100 732876.800000000047 3584393 13197
|
||||
105 0101000020BF080000666666667E83254100000000844B4B41 30.9400000000000013 10.4000000000000004 20.1999999999999993 13.6999999999999993 704959.199999999953 3577608 13053
|
||||
119 0101000020BF0800009A9999997053264100000000460B4B41 50.2000000000000028 22.5 5.5 100 731576.300000000047 3544716 13307
|
||||
106 0101000020BF0800009A999999BEB62741000000809A594B41 58.7199999999999989 29.1999999999999993 10.0999999999999996 65.5999999999999943 777055.300000000047 3584821 13193
|
||||
107 0101000020BF080000CDCCCCCC46422A4100000080863C4B41 27.6400000000000006 21.8000000000000007 8 70.7000000000000028 860451.400000000023 3569933 13091
|
||||
109 0101000020BF080000333333333772294100000080AB374B41 32.4600000000000009 24.3000000000000007 10.6999999999999993 56.5 833819.599999999977 3567447 13235
|
||||
110 0101000020BF080000CDCCCCCC6E1A2C4100000080AC394B41 28.2699999999999996 24.5 10.0999999999999996 98.5999999999999943 920887.400000000023 3568473 13209
|
||||
111 0101000020BF080000CDCCCCCC4CBD2C4100000000F1374B41 23.379999999999999 24 11.4000000000000004 35.7000000000000028 941734.400000000023 3567586 13279
|
||||
113 0101000020BF0800009A999999B06D2B4100000000BC2F4B41 30.0599999999999987 30.3000000000000007 8.59999999999999964 100 898776.300000000047 3563384 13309
|
||||
133 0101000020BF08000033333333EABD25410000008045DA4A41 58.1700000000000017 35.8999999999999986 6 53.5 712437.099999999977 3519627 13243
|
||||
115 0101000020BF080000000000007A2B304100000080C5224B41 38.0200000000000031 17.1999999999999993 18.6000000000000014 5.09999999999999964 1059706 3556747 13051
|
||||
145 0101000020BF080000CDCCCCCC04692C410000008061B94A41 15.4199999999999999 24.1000000000000014 6.59999999999999964 61.7000000000000028 930946.400000000023 3502787 13005
|
||||
116 0101000020BF0800000000000052392F4100000000531F4B41 14.8499999999999996 13.1999999999999993 11.8000000000000007 80.5999999999999943 1023145 3554982 13029
|
||||
118 0101000020BF08000033333333824C27410000000004194B41 46.5300000000000011 24.8000000000000007 15.9000000000000004 45.3999999999999986 763457.099999999977 3551752 13261
|
||||
123 0101000020BF08000000000000ACF72E4100000080A4FC4A41 39.1499999999999986 17.1999999999999993 13.4000000000000004 32.8999999999999986 1014742 3537225 13179
|
||||
124 0101000020BF080000CDCCCCCC2AEB2A410000000043F74A41 34.4500000000000028 27.3000000000000007 8.59999999999999964 72.5999999999999943 882069.400000000023 3534470 13271
|
||||
125 0101000020BF080000000000002F9729410000008039FF4A41 31.7600000000000016 28.6000000000000014 7.59999999999999964 100 838551.5 3538547 13315
|
||||
128 0101000020BF080000CDCCCCCC3BF22B41000000803AF04A41 15.3599999999999994 18.8000000000000007 8.30000000000000071 65.0999999999999943 915741.900000000023 3530869 13161
|
||||
126 0101000020BF0800000000000000A82E4100000000C5D64A41 21.75 23.6999999999999993 5.20000000000000018 100 1004544 3517834 13183
|
||||
132 0101000020BF0800009A999999EFAC26410000000026E04A41 59.8999999999999986 29.1000000000000014 9.19999999999999929 50.2999999999999972 743031.800000000047 3522636 13273
|
||||
129 0101000020BF08000033333333A9BA2C410000000072DE4A41 20.7600000000000016 19.8999999999999986 8.19999999999999929 75.5999999999999943 941396.599999999977 3521764 13001
|
||||
130 0101000020BF080000CDCCCCCC36F62441000000000EE34A41 49.9299999999999997 33 7.29999999999999982 100 686875.400000000023 3524124 13239
|
||||
135 0101000020BF0800009A999999A11D2E4100000080D9A84A41 19.4499999999999993 21.1999999999999993 9.59999999999999964 59.8999999999999986 986832.800000000047 3494323 13305
|
||||
137 0101000020BF080000333333338F0129410000008017D14A41 40.6599999999999966 31.3000000000000007 7.20000000000000018 44.5 819399.599999999977 3514927 13287
|
||||
138 0101000020BF08000033333333F471284100000000309B4A41 30.7100000000000009 26.1999999999999993 6.29999999999999982 71.0999999999999943 801018.099999999977 3487328 13321
|
||||
141 0101000020BF080000CDCCCCCCFF4B2B410000008038A54A41 25.4600000000000009 22.5 11.0999999999999996 64.5999999999999943 894463.900000000023 3492465 13069
|
||||
143 0101000020BF08000000000000C8722F4100000080FBB44A41 43.3400000000000034 22.3000000000000007 8.69999999999999929 100 1030500 3500535 13191
|
||||
144 0101000020BF080000CDCCCCCCE33B25410000008099AA4A41 60.759999999999998 35.7000000000000028 11.1999999999999993 100 695793.900000000023 3495219 13061
|
||||
147 0101000020BF080000666666660A1E26410000008096A54A41 58.8900000000000006 31.8000000000000007 10.0999999999999996 100 724741.199999999953 3492653 13037
|
||||
148 0101000020BF0800009A9999998461294100000080F19B4A41 26.6799999999999997 22.8999999999999986 14 51.1000000000000014 831682.300000000047 3487715 13277
|
||||
152 0101000020BF080000333333330E78254100000000C8734A41 44.0900000000000034 31.3999999999999986 9.40000000000000036 52.7999999999999972 703495.099999999977 3467152 13099
|
||||
149 0101000020BF0800009A9999997B192D4100000000DE904A41 11.6899999999999995 21.3000000000000007 6.29999999999999982 74.4000000000000057 953533.800000000047 3482044 13229
|
||||
150 0101000020BF08000000000000663B2F41000000806B7B4A41 25.5700000000000003 14.3000000000000007 19.8999999999999986 20.3000000000000007 1023411 3471063 13127
|
||||
151 0101000020BF08000033333333DBA22C4100000080C94B4A41 25.879999999999999 21.1000000000000014 10.4000000000000004 54.2000000000000028 938349.599999999977 3446675 13299
|
||||
153 0101000020BF0800009A999999173E2A410000008044724A41 11.6199999999999992 19.3000000000000007 7.5 66.2000000000000028 859915.800000000047 3466377 13019
|
||||
154 0101000020BF0800000000000082542B4100000000167D4A41 26.8599999999999994 26 6.40000000000000036 100 895553 3471916 13003
|
||||
155 0101000020BF080000333333336DBF264100000080A6824A41 51.6700000000000017 24.8000000000000007 9.40000000000000036 100 745398.599999999977 3474765 13007
|
||||
156 0101000020BF080000333333333D62274100000000F5594A41 47.9099999999999966 28.6999999999999993 7.79999999999999982 56.2000000000000028 766238.599999999977 3453930 13205
|
||||
157 0101000020BF080000CDCCCCCCB1E22D4100000080546D4A41 4.58000000000000007 18.1999999999999993 5.79999999999999982 100 979288.900000000023 3463849 13025
|
||||
162 0101000020BF080000333333331CB62B4100000000FA274A41 27.2899999999999991 26.3999999999999986 6.70000000000000018 58.6000000000000014 908046.099999999977 3428340 13065
|
||||
158 0101000020BF0800003333333310A129410000008057504A41 29.9400000000000013 22.3999999999999986 6.5 62 839816.099999999977 3449007 13075
|
||||
159 0101000020BF0800009A999999E7AD284100000000FD5D4A41 24.1600000000000001 22.8000000000000007 10 59.3999999999999986 808691.800000000047 3455994 13071
|
||||
163 0101000020BF0800009A99999998AA2A4100000080B63E4A41 26.5799999999999983 25.8999999999999986 5.40000000000000036 100 873804.300000000047 3439981 13173
|
||||
161 0101000020BF08000000000000C0C62E4100000080B63A4A41 20.1900000000000013 11.5 13.5 47.1000000000000014 1008480 3437933 13039
|
||||
172 0101000020BF080000000000005C43294100000000E31A4A41 41.4699999999999989 25.8999999999999986 9.09999999999999964 65.5999999999999943 827822 3421638 13027
|
||||
164 0101000020BF0800009A99999968602D4100000080A0304A41 27.0500000000000007 18.3000000000000007 6.40000000000000036 100 962612.300000000047 3432769 13049
|
||||
165 0101000020BF080000000000005C43294100000000E31A4A41 41.4699999999999989 25.8999999999999986 9.09999999999999964 65.5999999999999943 827822 3421638 13027
|
||||
167 0101000020BF0800003333333304592741000000803C1B4A41 31.5 22.3000000000000007 7.70000000000000018 55.3999999999999986 765058.099999999977 3421817 13131
|
||||
168 0101000020BF080000CDCCCCCCA85B264100000000341B4A41 39.4699999999999989 23.3000000000000007 11.6999999999999993 58 732628.400000000023 3421800 13087
|
||||
169 0101000020BF08000033333333DF7F254100000000991B4A41 32.740000000000002 29.1000000000000014 7.79999999999999982 69.4000000000000057 704495.599999999977 3422002 13253
|
||||
170 0101000020BF080000333333331A642A410000008058164A41 31.879999999999999 19.8999999999999986 16.3000000000000007 47.6000000000000014 864781.099999999977 3419313 13185
|
||||
171 0101000020BF080000000000001C5D2B4100000000DEF24941 11.4800000000000004 14.5999999999999996 4.70000000000000018 100 896654 3401148 13101
|
||||
\.
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
@@ -1,6 +1,6 @@
|
||||
-- Install dependencies
|
||||
CREATE EXTENSION plpythonu;
|
||||
CREATE EXTENSION postgis VERSION '2.2.2';
|
||||
CREATE EXTENSION postgis;
|
||||
|
||||
-- Create role publicuser if it does not exist
|
||||
DO
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
SET client_min_messages TO WARNING;
|
||||
\set ECHO none
|
||||
\set VERBOSITY TERSE
|
||||
\pset format unaligned
|
||||
|
||||
--
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
-- test of Geographically Weighted Regression (GWR)
|
||||
SET client_min_messages TO WARNING;
|
||||
\set ECHO none
|
||||
\pset format unaligned
|
||||
\i test/fixtures/gwr_georgia.sql
|
||||
|
||||
SELECT
|
||||
rowid,
|
||||
round((coeffs->>'pctrural')::numeric, 4) As coeff_pctrural,
|
||||
round((stand_errs->>'pctrural')::numeric, 4) As std_errs_pctrural,
|
||||
round((t_vals->>'pctrural')::numeric, 4) As t_vals_pctrural,
|
||||
round(predicted, 4) As predicted,
|
||||
round(residuals, 4) As residuals,
|
||||
round(r_squared, 4) As r_squared,
|
||||
bandwidth As bandwidth
|
||||
FROM
|
||||
cdb_crankshaft.CDB_GWR('SELECT * FROM g_utm_testing', 'pctbach',
|
||||
Array['pctrural', 'pctpov', 'pctblack']::text[],
|
||||
90.0,
|
||||
False,
|
||||
'bisquare',
|
||||
'the_geom',
|
||||
'areakey')
|
||||
WHERE rowid in (13001, 13027, 13039, 13231, 13321, 13293)
|
||||
ORDER BY rowid ASC;
|
||||
|
||||
|
||||
-- comparison data from known calculated values in
|
||||
-- https://github.com/TaylorOshan/pysal/blob/1d6af33bda46b1d623f70912c56155064463383f/pysal/examples/georgia/georgia_BS_NN_listwise.csv
|
||||
-- Note: values output from this analysis were correct with 1% of the values in that table, possibly due to projection differences.
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@ include ../../Makefile.global
|
||||
|
||||
# Install the package locally for development
|
||||
install:
|
||||
pip install --upgrade ./crankshaft
|
||||
$(PIP) install --upgrade ./crankshaft
|
||||
|
||||
# Test develpment install
|
||||
test:
|
||||
nosetests crankshaft/test/
|
||||
$(NOSETESTS) crankshaft/test/
|
||||
|
||||
release: ../../release/$(EXTENSION).control $(SOURCES_DATA)
|
||||
mkdir -p ../../release/python/$(EXTVERSION)
|
||||
@@ -14,4 +14,4 @@ release: ../../release/$(EXTENSION).control $(SOURCES_DATA)
|
||||
$(SED) -i -r 's/version='"'"'[0-9]+\.[0-9]+\.[0-9]+'"'"'/version='"'"'$(EXTVERSION)'"'"'/g' ../../release/python/$(EXTVERSION)/$(PACKAGE)/setup.py
|
||||
|
||||
deploy:
|
||||
pip install $(RUN_OPTIONS) --upgrade ../../release/python/$(RELEASE_VERSION)/$(PACKAGE)
|
||||
$(PIP) install $(RUN_OPTIONS) --upgrade ../../release/python/$(RELEASE_VERSION)/$(PACKAGE)
|
||||
|
||||
@@ -3,4 +3,5 @@ import crankshaft.random_seeds
|
||||
import crankshaft.clustering
|
||||
import crankshaft.space_time_dynamics
|
||||
import crankshaft.segmentation
|
||||
import crankshaft.regression
|
||||
import analysis_data_provider
|
||||
|
||||
@@ -6,11 +6,13 @@ NULL_VALUE_ERROR = ('No usable data passed to analysis. Check your input rows '
|
||||
'for null values and fill in appropriately.')
|
||||
|
||||
|
||||
def verify_data(f):
|
||||
def verify_data(func):
|
||||
"""decorator to verify data result before returning to algorithm"""
|
||||
def wrapper(*args, **kwargs):
|
||||
"""Error checking"""
|
||||
try:
|
||||
data = f(*args, **kwargs)
|
||||
if len(data) == 0:
|
||||
data = func(*args, **kwargs)
|
||||
if not data:
|
||||
plpy.error(NULL_VALUE_ERROR)
|
||||
else:
|
||||
return data
|
||||
@@ -59,3 +61,14 @@ class AnalysisDataProvider(object):
|
||||
'''.format(**params)
|
||||
|
||||
return plpy.execute(query)
|
||||
|
||||
@verify_data
|
||||
def get_gwr(self, params):
|
||||
"""fetch data for gwr analysis"""
|
||||
query = pu.gwr_query(params)
|
||||
return plpy.execute(query)
|
||||
|
||||
def get_gwr_predict(self, params):
|
||||
"""fetch data for gwr predict"""
|
||||
query = pu.gwr_predict_query(params)
|
||||
return plpy.execute(query)
|
||||
|
||||
@@ -88,7 +88,7 @@ class Moran(object):
|
||||
"""
|
||||
params = OrderedDict([("id_col", id_col),
|
||||
("attr1", numerator),
|
||||
("attr2", denominator)
|
||||
("attr2", denominator),
|
||||
("geom_col", geom_col),
|
||||
("subquery", subquery),
|
||||
("num_ngbrs", num_ngbrs)])
|
||||
|
||||
@@ -35,7 +35,7 @@ def get_weight(query_res, w_type='knn', num_ngbrs=5):
|
||||
return built_weight
|
||||
|
||||
|
||||
def query_attr_select(params):
|
||||
def query_attr_select(params, table_ref=True):
|
||||
"""
|
||||
Create portion of SELECT statement for attributes inolved in query.
|
||||
Defaults to order in the params
|
||||
@@ -51,11 +51,17 @@ def query_attr_select(params):
|
||||
"""
|
||||
|
||||
attr_string = ""
|
||||
template = "i.\"%(col)s\"::numeric As attr%(alias_num)s, "
|
||||
template = "\"%(col)s\"::numeric As attr%(alias_num)s, "
|
||||
|
||||
if 'time_cols' in params:
|
||||
# if markov analysis
|
||||
attrs = params['time_cols']
|
||||
if table_ref:
|
||||
template = "i." + template
|
||||
|
||||
if ('time_cols' in params) or ('ind_vars' in params):
|
||||
# if markov or gwr analysis
|
||||
attrs = (params['time_cols'] if 'time_cols' in params
|
||||
else params['ind_vars'])
|
||||
if 'ind_vars' in params:
|
||||
template = "array_agg(\"%(col)s\"::numeric) As attr%(alias_num)s, "
|
||||
|
||||
for idx, val in enumerate(attrs):
|
||||
attr_string += template % {"col": val, "alias_num": idx + 1}
|
||||
@@ -72,7 +78,7 @@ def query_attr_select(params):
|
||||
return attr_string
|
||||
|
||||
|
||||
def query_attr_where(params):
|
||||
def query_attr_where(params, table_ref=True):
|
||||
"""
|
||||
Construct where conditions when building neighbors query
|
||||
Create portion of WHERE clauses for weeding out NULL-valued geometries
|
||||
@@ -91,11 +97,14 @@ def query_attr_where(params):
|
||||
NULL AND idx_replace."time3" IS NOT NULL'
|
||||
"""
|
||||
attr_string = []
|
||||
template = "idx_replace.\"%s\" IS NOT NULL"
|
||||
template = "\"%s\" IS NOT NULL"
|
||||
if table_ref:
|
||||
template = "idx_replace." + template
|
||||
|
||||
if 'time_cols' in params:
|
||||
# markov where clauses
|
||||
attrs = params['time_cols']
|
||||
if ('time_cols' in params) or ('ind_vars' in params):
|
||||
# markov or gwr where clauses
|
||||
attrs = (params['time_cols'] if 'time_cols' in params
|
||||
else params['ind_vars'])
|
||||
# add values to template
|
||||
for attr in attrs:
|
||||
attr_string.append(template % attr)
|
||||
@@ -125,8 +134,8 @@ def knn(params):
|
||||
@param vars: dict of values to fill template
|
||||
"""
|
||||
|
||||
attr_select = query_attr_select(params)
|
||||
attr_where = query_attr_where(params)
|
||||
attr_select = query_attr_select(params, table_ref=True)
|
||||
attr_where = query_attr_where(params, table_ref=True)
|
||||
|
||||
replacements = {"attr_select": attr_select,
|
||||
"attr_where_i": attr_where.replace("idx_replace", "i"),
|
||||
@@ -180,6 +189,56 @@ def queen(params):
|
||||
|
||||
return query.format(**params)
|
||||
|
||||
|
||||
def gwr_query(params):
|
||||
"""
|
||||
GWR query
|
||||
"""
|
||||
|
||||
replacements = {"ind_vars_select": query_attr_select(params,
|
||||
table_ref=None),
|
||||
"ind_vars_where": query_attr_where(params,
|
||||
table_ref=None)}
|
||||
|
||||
query = '''
|
||||
SELECT
|
||||
array_agg(ST_X(ST_Centroid("{geom_col}"))) As x,
|
||||
array_agg(ST_Y(ST_Centroid("{geom_col}"))) As y,
|
||||
array_agg("{dep_var}") As dep_var,
|
||||
%(ind_vars_select)s
|
||||
array_agg("{id_col}") As rowid
|
||||
FROM ({subquery}) As q
|
||||
WHERE
|
||||
"{dep_var}" IS NOT NULL AND
|
||||
%(ind_vars_where)s
|
||||
''' % replacements
|
||||
|
||||
return query.format(**params).strip()
|
||||
|
||||
|
||||
def gwr_predict_query(params):
|
||||
"""
|
||||
GWR query
|
||||
"""
|
||||
|
||||
replacements = {"ind_vars_select": query_attr_select(params,
|
||||
table_ref=None),
|
||||
"ind_vars_where": query_attr_where(params,
|
||||
table_ref=None)}
|
||||
|
||||
query = '''
|
||||
SELECT
|
||||
array_agg(ST_X(ST_Centroid({geom_col}))) As x,
|
||||
array_agg(ST_Y(ST_Centroid({geom_col}))) As y,
|
||||
array_agg({dep_var}) As dep_var,
|
||||
%(ind_vars_select)s
|
||||
array_agg({id_col}) As rowid
|
||||
FROM ({subquery}) As q
|
||||
WHERE
|
||||
%(ind_vars_where)s
|
||||
''' % replacements
|
||||
|
||||
return query.format(**params).strip()
|
||||
# to add more weight methods open a ticket or pull request
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from crankshaft.regression.gwr import *
|
||||
from crankshaft.regression.glm import *
|
||||
from crankshaft.regression.gwr_cs import *
|
||||
@@ -0,0 +1,444 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#Import GLM and pysal\n",
|
||||
"import os\n",
|
||||
"import numpy as np\n",
|
||||
"os.chdir('/Users/toshan/dev/pysal/pysal/contrib/glm')\n",
|
||||
"from glm import GLM\n",
|
||||
"import pysal\n",
|
||||
"import pandas as pd\n",
|
||||
"import statsmodels.formula.api as smf\n",
|
||||
"import statsmodels.api as sm\n",
|
||||
"from family import Gaussian, Binomial, Poisson, QuasiPoisson\n",
|
||||
"\n",
|
||||
"from statsmodels.api import families"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#Prepare some test data - columbus example\n",
|
||||
"db = pysal.open(pysal.examples.get_path('columbus.dbf'),'r')\n",
|
||||
"y = np.array(db.by_col(\"HOVAL\"))\n",
|
||||
"y = np.reshape(y, (49,1))\n",
|
||||
"X = []\n",
|
||||
"#X.append(np.ones(len(y)))\n",
|
||||
"X.append(db.by_col(\"INC\"))\n",
|
||||
"X.append(db.by_col(\"CRIME\"))\n",
|
||||
"X = np.array(X).T"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[ 46.42818268]\n",
|
||||
" [ 0.62898397]\n",
|
||||
" [ -0.48488854]]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#First fit pysal OLS model\n",
|
||||
"from pysal.spreg import ols\n",
|
||||
"OLS = ols.OLS(y, X)\n",
|
||||
"print OLS.betas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"<class 'family.Gaussian'>\n",
|
||||
"<class 'family.Gaussian'>\n",
|
||||
"<class 'family.Gaussian'>\n",
|
||||
"[ 46.42818268 0.62898397 -0.48488854]\n",
|
||||
"[ 46.42818268 0.62898397 -0.48488854]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#Then fit Gaussian GLM\n",
|
||||
"\n",
|
||||
"#create Gaussian GLM model object\n",
|
||||
"model = GLM(y, X, Gaussian())\n",
|
||||
"model\n",
|
||||
"\n",
|
||||
"#Fit model to estimate coefficients and return GLMResults object\n",
|
||||
"results = model.fit()\n",
|
||||
"\n",
|
||||
"#Check coefficients - R betas [46.4282, 0.6290, -0.4849]\n",
|
||||
"print results.params\n",
|
||||
"\n",
|
||||
"# Gaussian GLM results from statsmodels\n",
|
||||
"sm_model = smf.GLM(y, sm.add_constant(X), family=families.Gaussian())\n",
|
||||
"sm_results = sm_model.fit()\n",
|
||||
"print sm_results.params"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"2 2\n",
|
||||
"<class 'family.Gaussian'>\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"<class 'family.Gaussian'>\n",
|
||||
"<class 'family.Gaussian'>\n",
|
||||
"<class 'family.Gaussian'>\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print results.df_model, sm_results.df_model\n",
|
||||
"print np.allclose(results.aic, sm_results.aic)\n",
|
||||
"print np.allclose(results.bic, sm_results.bic)\n",
|
||||
"print np.allclose(results.deviance, sm_results.deviance)\n",
|
||||
"print np.allclose(results.df_model, sm_results.df_model)\n",
|
||||
"print np.allclose(results.df_resid, sm_results.df_resid)\n",
|
||||
"print np.allclose(results.llf, sm_results.llf)\n",
|
||||
"print np.allclose(results.mu, sm_results.mu)\n",
|
||||
"print np.allclose(results.n, sm_results.nobs)\n",
|
||||
"print np.allclose(results.null, sm_results.null)\n",
|
||||
"print np.allclose(results.null_deviance, sm_results.null_deviance)\n",
|
||||
"print np.allclose(results.params, sm_results.params)\n",
|
||||
"print np.allclose(results.pearson_chi2, sm_results.pearson_chi2)\n",
|
||||
"print np.allclose(results.resid_anscombe, sm_results.resid_anscombe)\n",
|
||||
"print np.allclose(results.resid_deviance, sm_results.resid_deviance)\n",
|
||||
"print np.allclose(results.resid_pearson, sm_results.resid_pearson)\n",
|
||||
"print np.allclose(results.resid_response, sm_results.resid_response)\n",
|
||||
"print np.allclose(results.resid_working, sm_results.resid_working)\n",
|
||||
"print np.allclose(results.scale, sm_results.scale)\n",
|
||||
"print np.allclose(results.normalized_cov_params, sm_results.normalized_cov_params)\n",
|
||||
"print np.allclose(results.cov_params(), sm_results.cov_params())\n",
|
||||
"print np.allclose(results.bse, sm_results.bse)\n",
|
||||
"print np.allclose(results.conf_int(), sm_results.conf_int())\n",
|
||||
"print np.allclose(results.pvalues, sm_results.pvalues)\n",
|
||||
"print np.allclose(results.tvalues, sm_results.tvalues)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"<class 'family.Poisson'>\n",
|
||||
"<class 'family.Poisson'>\n",
|
||||
"<class 'family.Poisson'>\n",
|
||||
"[ 3.92159085 0.01183491 -0.01371397]\n",
|
||||
"[ 3.92159085 0.01183491 -0.01371397]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#Now fit a Poisson GLM \n",
|
||||
"\n",
|
||||
"poisson_y = np.round(y).astype(int)\n",
|
||||
"\n",
|
||||
"#create Poisson GLM model object\n",
|
||||
"model = GLM(poisson_y, X, Poisson())\n",
|
||||
"model\n",
|
||||
"\n",
|
||||
"#Fit model to estimate coefficients and return GLMResults object\n",
|
||||
"results = model.fit()\n",
|
||||
"\n",
|
||||
"#Check coefficients - R betas [3.91926, 0.01198, -0.01371]\n",
|
||||
"print results.params.T\n",
|
||||
"\n",
|
||||
"# Poisson GLM results from statsmodels\n",
|
||||
"sm_results = smf.GLM(poisson_y, sm.add_constant(X), family=families.Poisson()).fit()\n",
|
||||
"print sm_results.params"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"<class 'family.Poisson'>\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"<class 'family.Poisson'>\n",
|
||||
"<class 'family.Poisson'>\n",
|
||||
"<class 'family.Poisson'>\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"[ 0.13049161 0.00511599 0.00193769] [ 0.13049161 0.00511599 0.00193769]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print np.allclose(results.aic, sm_results.aic)\n",
|
||||
"print np.allclose(results.bic, sm_results.bic)\n",
|
||||
"print np.allclose(results.deviance, sm_results.deviance)\n",
|
||||
"print np.allclose(results.df_model, sm_results.df_model)\n",
|
||||
"print np.allclose(results.df_resid, sm_results.df_resid)\n",
|
||||
"print np.allclose(results.llf, sm_results.llf)\n",
|
||||
"print np.allclose(results.mu, sm_results.mu)\n",
|
||||
"print np.allclose(results.n, sm_results.nobs)\n",
|
||||
"print np.allclose(results.null, sm_results.null)\n",
|
||||
"print np.allclose(results.null_deviance, sm_results.null_deviance)\n",
|
||||
"print np.allclose(results.params, sm_results.params)\n",
|
||||
"print np.allclose(results.pearson_chi2, sm_results.pearson_chi2)\n",
|
||||
"print np.allclose(results.resid_anscombe, sm_results.resid_anscombe)\n",
|
||||
"print np.allclose(results.resid_deviance, sm_results.resid_deviance)\n",
|
||||
"print np.allclose(results.resid_pearson, sm_results.resid_pearson)\n",
|
||||
"print np.allclose(results.resid_response, sm_results.resid_response)\n",
|
||||
"print np.allclose(results.resid_working, sm_results.resid_working)\n",
|
||||
"print np.allclose(results.scale, sm_results.scale)\n",
|
||||
"print np.allclose(results.normalized_cov_params, sm_results.normalized_cov_params)\n",
|
||||
"print np.allclose(results.cov_params(), sm_results.cov_params())\n",
|
||||
"print np.allclose(results.bse, sm_results.bse)\n",
|
||||
"print np.allclose(results.conf_int(), sm_results.conf_int())\n",
|
||||
"print np.allclose(results.pvalues, sm_results.pvalues)\n",
|
||||
"print np.allclose(results.tvalues, sm_results.tvalues)\n",
|
||||
"print results.bse, sm_results.bse"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 82,
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[-5.33638276 0.0287754 ]\n",
|
||||
"[-5.33638276 0.0287754 ]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#Now fit a binomial GLM\n",
|
||||
"londonhp = pd.read_csv('/Users/toshan/projects/londonhp.csv')\n",
|
||||
"#londonhp = pd.read_csv('/Users/qszhao/Dropbox/pysal/pysal/contrib/gwr/londonhp.csv')\n",
|
||||
"y = londonhp['BATH2'].values\n",
|
||||
"y = np.reshape(y, (316,1))\n",
|
||||
"X = londonhp['FLOORSZ'].values\n",
|
||||
"X = np.reshape(X, (316,1))\n",
|
||||
"\n",
|
||||
"#create logistic GLM model object\n",
|
||||
"model = GLM(y, X, Binomial())\n",
|
||||
"model\n",
|
||||
"\n",
|
||||
"#Fit model to estimate coefficients and return GLMResults object\n",
|
||||
"results = model.fit()\n",
|
||||
"\n",
|
||||
"#Check coefficients - R betas [-5.33638, 0.02878]\n",
|
||||
"print results.params.T\n",
|
||||
"\n",
|
||||
"# Logistic GLM results from statsmodels\n",
|
||||
"sm_results = smf.GLM(y, sm.add_constant(X), family=families.Binomial()).fit()\n",
|
||||
"print sm_results.params"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 76,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"1 1\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n",
|
||||
"True\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print results.df_model, sm_results.df_model\n",
|
||||
"print np.allclose(results.aic, sm_results.aic)\n",
|
||||
"print np.allclose(results.bic, sm_results.bic)\n",
|
||||
"print np.allclose(results.deviance, sm_results.deviance)\n",
|
||||
"print np.allclose(results.df_model, sm_results.df_model)\n",
|
||||
"print np.allclose(results.df_resid, sm_results.df_resid)\n",
|
||||
"print np.allclose(results.llf, sm_results.llf)\n",
|
||||
"print np.allclose(results.mu, sm_results.mu)\n",
|
||||
"print np.allclose(results.n, sm_results.nobs)\n",
|
||||
"print np.allclose(results.null, sm_results.null)\n",
|
||||
"print np.allclose(results.null_deviance, sm_results.null_deviance)\n",
|
||||
"print np.allclose(results.params, sm_results.params)\n",
|
||||
"print np.allclose(results.pearson_chi2, sm_results.pearson_chi2)\n",
|
||||
"print np.allclose(results.resid_anscombe, sm_results.resid_anscombe)\n",
|
||||
"print np.allclose(results.resid_deviance, sm_results.resid_deviance)\n",
|
||||
"print np.allclose(results.resid_pearson, sm_results.resid_pearson)\n",
|
||||
"print np.allclose(results.resid_response, sm_results.resid_response)\n",
|
||||
"print np.allclose(results.resid_working, sm_results.resid_working)\n",
|
||||
"print np.allclose(results.scale, sm_results.scale)\n",
|
||||
"print np.allclose(results.normalized_cov_params, sm_results.normalized_cov_params)\n",
|
||||
"print np.allclose(results.cov_params(), sm_results.cov_params())\n",
|
||||
"print np.allclose(results.bse, sm_results.bse)\n",
|
||||
"print np.allclose(results.conf_int(), sm_results.conf_int())\n",
|
||||
"print np.allclose(results.pvalues, sm_results.pvalues)\n",
|
||||
"print np.allclose(results.tvalues, sm_results.tvalues)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"<class 'family.QuasiPoisson'>\n",
|
||||
"<class 'family.QuasiPoisson'>\n",
|
||||
"<class 'family.QuasiPoisson'>\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"#create QUasiPoisson GLM model object\n",
|
||||
"model = GLM(poisson_y, X, QuasiPoisson())\n",
|
||||
"model\n",
|
||||
"\n",
|
||||
"#Fit model to estimate coefficients and return GLMResults object\n",
|
||||
"results = model.fit()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.9"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import glm
|
||||
import family
|
||||
import utils
|
||||
import iwls
|
||||
@@ -0,0 +1,959 @@
|
||||
|
||||
from __future__ import print_function
|
||||
import numpy as np
|
||||
from scipy import stats
|
||||
from utils import cache_readonly
|
||||
|
||||
class Results(object):
|
||||
"""
|
||||
Class to contain model results
|
||||
Parameters
|
||||
----------
|
||||
model : class instance
|
||||
the previously specified model instance
|
||||
params : array
|
||||
parameter estimates from the fit model
|
||||
"""
|
||||
def __init__(self, model, params, **kwd):
|
||||
self.__dict__.update(kwd)
|
||||
self.initialize(model, params, **kwd)
|
||||
self._data_attr = []
|
||||
|
||||
def initialize(self, model, params, **kwd):
|
||||
self.params = params
|
||||
self.model = model
|
||||
if hasattr(model, 'k_constant'):
|
||||
self.k_constant = model.k_constant
|
||||
|
||||
def predict(self, exog=None, transform=True, *args, **kwargs):
|
||||
"""
|
||||
Call self.model.predict with self.params as the first argument.
|
||||
Parameters
|
||||
----------
|
||||
exog : array-like, optional
|
||||
The values for which you want to predict.
|
||||
transform : bool, optional
|
||||
If the model was fit via a formula, do you want to pass
|
||||
exog through the formula. Default is True. E.g., if you fit
|
||||
a model y ~ log(x1) + log(x2), and transform is True, then
|
||||
you can pass a data structure that contains x1 and x2 in
|
||||
their original form. Otherwise, you'd need to log the data
|
||||
first.
|
||||
args, kwargs :
|
||||
Some models can take additional arguments or keywords, see the
|
||||
predict method of the model for the details.
|
||||
Returns
|
||||
-------
|
||||
prediction : ndarray or pandas.Series
|
||||
See self.model.predict
|
||||
"""
|
||||
if transform and hasattr(self.model, 'formula') and exog is not None:
|
||||
from patsy import dmatrix
|
||||
exog = dmatrix(self.model.data.design_info.builder,
|
||||
exog)
|
||||
|
||||
if exog is not None:
|
||||
exog = np.asarray(exog)
|
||||
if exog.ndim == 1 and (self.model.exog.ndim == 1 or
|
||||
self.model.exog.shape[1] == 1):
|
||||
exog = exog[:, None]
|
||||
exog = np.atleast_2d(exog) # needed in count model shape[1]
|
||||
|
||||
return self.model.predict(self.params, exog, *args, **kwargs)
|
||||
|
||||
|
||||
#TODO: public method?
|
||||
class LikelihoodModelResults(Results):
|
||||
"""
|
||||
Class to contain results from likelihood models
|
||||
Parameters
|
||||
-----------
|
||||
model : LikelihoodModel instance or subclass instance
|
||||
LikelihoodModelResults holds a reference to the model that is fit.
|
||||
params : 1d array_like
|
||||
parameter estimates from estimated model
|
||||
normalized_cov_params : 2d array
|
||||
Normalized (before scaling) covariance of params. (dot(X.T,X))**-1
|
||||
scale : float
|
||||
For (some subset of models) scale will typically be the
|
||||
mean square error from the estimated model (sigma^2)
|
||||
Returns
|
||||
-------
|
||||
**Attributes**
|
||||
mle_retvals : dict
|
||||
Contains the values returned from the chosen optimization method if
|
||||
full_output is True during the fit. Available only if the model
|
||||
is fit by maximum likelihood. See notes below for the output from
|
||||
the different methods.
|
||||
mle_settings : dict
|
||||
Contains the arguments passed to the chosen optimization method.
|
||||
Available if the model is fit by maximum likelihood. See
|
||||
LikelihoodModel.fit for more information.
|
||||
model : model instance
|
||||
LikelihoodResults contains a reference to the model that is fit.
|
||||
params : ndarray
|
||||
The parameters estimated for the model.
|
||||
scale : float
|
||||
The scaling factor of the model given during instantiation.
|
||||
tvalues : array
|
||||
The t-values of the standard errors.
|
||||
Notes
|
||||
-----
|
||||
The covariance of params is given by scale times normalized_cov_params.
|
||||
Return values by solver if full_output is True during fit:
|
||||
'newton'
|
||||
fopt : float
|
||||
The value of the (negative) loglikelihood at its
|
||||
minimum.
|
||||
iterations : int
|
||||
Number of iterations performed.
|
||||
score : ndarray
|
||||
The score vector at the optimum.
|
||||
Hessian : ndarray
|
||||
The Hessian at the optimum.
|
||||
warnflag : int
|
||||
1 if maxiter is exceeded. 0 if successful convergence.
|
||||
converged : bool
|
||||
True: converged. False: did not converge.
|
||||
allvecs : list
|
||||
List of solutions at each iteration.
|
||||
'nm'
|
||||
fopt : float
|
||||
The value of the (negative) loglikelihood at its
|
||||
minimum.
|
||||
iterations : int
|
||||
Number of iterations performed.
|
||||
warnflag : int
|
||||
1: Maximum number of function evaluations made.
|
||||
2: Maximum number of iterations reached.
|
||||
converged : bool
|
||||
True: converged. False: did not converge.
|
||||
allvecs : list
|
||||
List of solutions at each iteration.
|
||||
'bfgs'
|
||||
fopt : float
|
||||
Value of the (negative) loglikelihood at its minimum.
|
||||
gopt : float
|
||||
Value of gradient at minimum, which should be near 0.
|
||||
Hinv : ndarray
|
||||
value of the inverse Hessian matrix at minimum. Note
|
||||
that this is just an approximation and will often be
|
||||
different from the value of the analytic Hessian.
|
||||
fcalls : int
|
||||
Number of calls to loglike.
|
||||
gcalls : int
|
||||
Number of calls to gradient/score.
|
||||
warnflag : int
|
||||
1: Maximum number of iterations exceeded. 2: Gradient
|
||||
and/or function calls are not changing.
|
||||
converged : bool
|
||||
True: converged. False: did not converge.
|
||||
allvecs : list
|
||||
Results at each iteration.
|
||||
'lbfgs'
|
||||
fopt : float
|
||||
Value of the (negative) loglikelihood at its minimum.
|
||||
gopt : float
|
||||
Value of gradient at minimum, which should be near 0.
|
||||
fcalls : int
|
||||
Number of calls to loglike.
|
||||
warnflag : int
|
||||
Warning flag:
|
||||
- 0 if converged
|
||||
- 1 if too many function evaluations or too many iterations
|
||||
- 2 if stopped for another reason
|
||||
converged : bool
|
||||
True: converged. False: did not converge.
|
||||
'powell'
|
||||
fopt : float
|
||||
Value of the (negative) loglikelihood at its minimum.
|
||||
direc : ndarray
|
||||
Current direction set.
|
||||
iterations : int
|
||||
Number of iterations performed.
|
||||
fcalls : int
|
||||
Number of calls to loglike.
|
||||
warnflag : int
|
||||
1: Maximum number of function evaluations. 2: Maximum number
|
||||
of iterations.
|
||||
converged : bool
|
||||
True : converged. False: did not converge.
|
||||
allvecs : list
|
||||
Results at each iteration.
|
||||
'cg'
|
||||
fopt : float
|
||||
Value of the (negative) loglikelihood at its minimum.
|
||||
fcalls : int
|
||||
Number of calls to loglike.
|
||||
gcalls : int
|
||||
Number of calls to gradient/score.
|
||||
warnflag : int
|
||||
1: Maximum number of iterations exceeded. 2: Gradient and/
|
||||
or function calls not changing.
|
||||
converged : bool
|
||||
True: converged. False: did not converge.
|
||||
allvecs : list
|
||||
Results at each iteration.
|
||||
'ncg'
|
||||
fopt : float
|
||||
Value of the (negative) loglikelihood at its minimum.
|
||||
fcalls : int
|
||||
Number of calls to loglike.
|
||||
gcalls : int
|
||||
Number of calls to gradient/score.
|
||||
hcalls : int
|
||||
Number of calls to hessian.
|
||||
warnflag : int
|
||||
1: Maximum number of iterations exceeded.
|
||||
converged : bool
|
||||
True: converged. False: did not converge.
|
||||
allvecs : list
|
||||
Results at each iteration.
|
||||
"""
|
||||
|
||||
# by default we use normal distribution
|
||||
# can be overwritten by instances or subclasses
|
||||
use_t = False
|
||||
|
||||
def __init__(self, model, params, normalized_cov_params=None, scale=1.,
|
||||
**kwargs):
|
||||
super(LikelihoodModelResults, self).__init__(model, params)
|
||||
self.normalized_cov_params = normalized_cov_params
|
||||
self.scale = scale
|
||||
|
||||
# robust covariance
|
||||
# We put cov_type in kwargs so subclasses can decide in fit whether to
|
||||
# use this generic implementation
|
||||
if 'use_t' in kwargs:
|
||||
use_t = kwargs['use_t']
|
||||
if use_t is not None:
|
||||
self.use_t = use_t
|
||||
if 'cov_type' in kwargs:
|
||||
cov_type = kwargs.get('cov_type', 'nonrobust')
|
||||
cov_kwds = kwargs.get('cov_kwds', {})
|
||||
|
||||
if cov_type == 'nonrobust':
|
||||
self.cov_type = 'nonrobust'
|
||||
self.cov_kwds = {'description' : 'Standard Errors assume that the ' +
|
||||
'covariance matrix of the errors is correctly ' +
|
||||
'specified.'}
|
||||
else:
|
||||
from statsmodels.base.covtype import get_robustcov_results
|
||||
if cov_kwds is None:
|
||||
cov_kwds = {}
|
||||
use_t = self.use_t
|
||||
# TODO: we shouldn't need use_t in get_robustcov_results
|
||||
get_robustcov_results(self, cov_type=cov_type, use_self=True,
|
||||
use_t=use_t, **cov_kwds)
|
||||
|
||||
|
||||
def normalized_cov_params(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def _get_robustcov_results(self, cov_type='nonrobust', use_self=True,
|
||||
use_t=None, **cov_kwds):
|
||||
from statsmodels.base.covtype import get_robustcov_results
|
||||
if cov_kwds is None:
|
||||
cov_kwds = {}
|
||||
|
||||
if cov_type == 'nonrobust':
|
||||
self.cov_type = 'nonrobust'
|
||||
self.cov_kwds = {'description' : 'Standard Errors assume that the ' +
|
||||
'covariance matrix of the errors is correctly ' +
|
||||
'specified.'}
|
||||
else:
|
||||
# TODO: we shouldn't need use_t in get_robustcov_results
|
||||
get_robustcov_results(self, cov_type=cov_type, use_self=True,
|
||||
use_t=use_t, **cov_kwds)
|
||||
|
||||
@cache_readonly
|
||||
def llf(self):
|
||||
return self.model.loglike(self.params)
|
||||
|
||||
@cache_readonly
|
||||
def bse(self):
|
||||
return np.sqrt(np.diag(self.cov_params()))
|
||||
|
||||
@cache_readonly
|
||||
def tvalues(self):
|
||||
"""
|
||||
Return the t-statistic for a given parameter estimate.
|
||||
"""
|
||||
return self.params / self.bse
|
||||
|
||||
@cache_readonly
|
||||
def pvalues(self):
|
||||
if self.use_t:
|
||||
df_resid = getattr(self, 'df_resid_inference', self.df_resid)
|
||||
return stats.t.sf(np.abs(self.tvalues), df_resid)*2
|
||||
else:
|
||||
return stats.norm.sf(np.abs(self.tvalues))*2
|
||||
|
||||
|
||||
def cov_params(self, r_matrix=None, column=None, scale=None, cov_p=None,
|
||||
other=None):
|
||||
"""
|
||||
Returns the variance/covariance matrix.
|
||||
The variance/covariance matrix can be of a linear contrast
|
||||
of the estimates of params or all params multiplied by scale which
|
||||
will usually be an estimate of sigma^2. Scale is assumed to be
|
||||
a scalar.
|
||||
Parameters
|
||||
----------
|
||||
r_matrix : array-like
|
||||
Can be 1d, or 2d. Can be used alone or with other.
|
||||
column : array-like, optional
|
||||
Must be used on its own. Can be 0d or 1d see below.
|
||||
scale : float, optional
|
||||
Can be specified or not. Default is None, which means that
|
||||
the scale argument is taken from the model.
|
||||
other : array-like, optional
|
||||
Can be used when r_matrix is specified.
|
||||
Returns
|
||||
-------
|
||||
cov : ndarray
|
||||
covariance matrix of the parameter estimates or of linear
|
||||
combination of parameter estimates. See Notes.
|
||||
Notes
|
||||
-----
|
||||
(The below are assumed to be in matrix notation.)
|
||||
If no argument is specified returns the covariance matrix of a model
|
||||
``(scale)*(X.T X)^(-1)``
|
||||
If contrast is specified it pre and post-multiplies as follows
|
||||
``(scale) * r_matrix (X.T X)^(-1) r_matrix.T``
|
||||
If contrast and other are specified returns
|
||||
``(scale) * r_matrix (X.T X)^(-1) other.T``
|
||||
If column is specified returns
|
||||
``(scale) * (X.T X)^(-1)[column,column]`` if column is 0d
|
||||
OR
|
||||
``(scale) * (X.T X)^(-1)[column][:,column]`` if column is 1d
|
||||
"""
|
||||
if (hasattr(self, 'mle_settings') and
|
||||
self.mle_settings['optimizer'] in ['l1', 'l1_cvxopt_cp']):
|
||||
dot_fun = nan_dot
|
||||
else:
|
||||
dot_fun = np.dot
|
||||
|
||||
if (cov_p is None and self.normalized_cov_params is None and
|
||||
not hasattr(self, 'cov_params_default')):
|
||||
raise ValueError('need covariance of parameters for computing '
|
||||
'(unnormalized) covariances')
|
||||
if column is not None and (r_matrix is not None or other is not None):
|
||||
raise ValueError('Column should be specified without other '
|
||||
'arguments.')
|
||||
if other is not None and r_matrix is None:
|
||||
raise ValueError('other can only be specified with r_matrix')
|
||||
|
||||
if cov_p is None:
|
||||
if hasattr(self, 'cov_params_default'):
|
||||
cov_p = self.cov_params_default
|
||||
else:
|
||||
if scale is None:
|
||||
scale = self.scale
|
||||
cov_p = self.normalized_cov_params * scale
|
||||
|
||||
if column is not None:
|
||||
column = np.asarray(column)
|
||||
if column.shape == ():
|
||||
return cov_p[column, column]
|
||||
else:
|
||||
#return cov_p[column][:, column]
|
||||
return cov_p[column[:, None], column]
|
||||
elif r_matrix is not None:
|
||||
r_matrix = np.asarray(r_matrix)
|
||||
if r_matrix.shape == ():
|
||||
raise ValueError("r_matrix should be 1d or 2d")
|
||||
if other is None:
|
||||
other = r_matrix
|
||||
else:
|
||||
other = np.asarray(other)
|
||||
tmp = dot_fun(r_matrix, dot_fun(cov_p, np.transpose(other)))
|
||||
return tmp
|
||||
else: # if r_matrix is None and column is None:
|
||||
return cov_p
|
||||
|
||||
#TODO: make sure this works as needed for GLMs
|
||||
def t_test(self, r_matrix, cov_p=None, scale=None,
|
||||
use_t=None):
|
||||
"""
|
||||
Compute a t-test for a each linear hypothesis of the form Rb = q
|
||||
Parameters
|
||||
----------
|
||||
r_matrix : array-like, str, tuple
|
||||
- array : If an array is given, a p x k 2d array or length k 1d
|
||||
array specifying the linear restrictions. It is assumed
|
||||
that the linear combination is equal to zero.
|
||||
- str : The full hypotheses to test can be given as a string.
|
||||
See the examples.
|
||||
- tuple : A tuple of arrays in the form (R, q). If q is given,
|
||||
can be either a scalar or a length p row vector.
|
||||
cov_p : array-like, optional
|
||||
An alternative estimate for the parameter covariance matrix.
|
||||
If None is given, self.normalized_cov_params is used.
|
||||
scale : float, optional
|
||||
An optional `scale` to use. Default is the scale specified
|
||||
by the model fit.
|
||||
use_t : bool, optional
|
||||
If use_t is None, then the default of the model is used.
|
||||
If use_t is True, then the p-values are based on the t
|
||||
distribution.
|
||||
If use_t is False, then the p-values are based on the normal
|
||||
distribution.
|
||||
Returns
|
||||
-------
|
||||
res : ContrastResults instance
|
||||
The results for the test are attributes of this results instance.
|
||||
The available results have the same elements as the parameter table
|
||||
in `summary()`.
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> import statsmodels.api as sm
|
||||
>>> data = sm.datasets.longley.load()
|
||||
>>> data.exog = sm.add_constant(data.exog)
|
||||
>>> results = sm.OLS(data.endog, data.exog).fit()
|
||||
>>> r = np.zeros_like(results.params)
|
||||
>>> r[5:] = [1,-1]
|
||||
>>> print(r)
|
||||
[ 0. 0. 0. 0. 0. 1. -1.]
|
||||
r tests that the coefficients on the 5th and 6th independent
|
||||
variable are the same.
|
||||
>>> T_test = results.t_test(r)
|
||||
>>> print(T_test)
|
||||
<T contrast: effect=-1829.2025687192481, sd=455.39079425193762,
|
||||
t=-4.0167754636411717, p=0.0015163772380899498, df_denom=9>
|
||||
>>> T_test.effect
|
||||
-1829.2025687192481
|
||||
>>> T_test.sd
|
||||
455.39079425193762
|
||||
>>> T_test.tvalue
|
||||
-4.0167754636411717
|
||||
>>> T_test.pvalue
|
||||
0.0015163772380899498
|
||||
Alternatively, you can specify the hypothesis tests using a string
|
||||
>>> from statsmodels.formula.api import ols
|
||||
>>> dta = sm.datasets.longley.load_pandas().data
|
||||
>>> formula = 'TOTEMP ~ GNPDEFL + GNP + UNEMP + ARMED + POP + YEAR'
|
||||
>>> results = ols(formula, dta).fit()
|
||||
>>> hypotheses = 'GNPDEFL = GNP, UNEMP = 2, YEAR/1829 = 1'
|
||||
>>> t_test = results.t_test(hypotheses)
|
||||
>>> print(t_test)
|
||||
See Also
|
||||
---------
|
||||
tvalues : individual t statistics
|
||||
f_test : for F tests
|
||||
patsy.DesignInfo.linear_constraint
|
||||
"""
|
||||
from patsy import DesignInfo
|
||||
names = self.model.data.param_names
|
||||
LC = DesignInfo(names).linear_constraint(r_matrix)
|
||||
r_matrix, q_matrix = LC.coefs, LC.constants
|
||||
num_ttests = r_matrix.shape[0]
|
||||
num_params = r_matrix.shape[1]
|
||||
|
||||
if (cov_p is None and self.normalized_cov_params is None and
|
||||
not hasattr(self, 'cov_params_default')):
|
||||
raise ValueError('Need covariance of parameters for computing '
|
||||
'T statistics')
|
||||
if num_params != self.params.shape[0]:
|
||||
raise ValueError('r_matrix and params are not aligned')
|
||||
if q_matrix is None:
|
||||
q_matrix = np.zeros(num_ttests)
|
||||
else:
|
||||
q_matrix = np.asarray(q_matrix)
|
||||
q_matrix = q_matrix.squeeze()
|
||||
if q_matrix.size > 1:
|
||||
if q_matrix.shape[0] != num_ttests:
|
||||
raise ValueError("r_matrix and q_matrix must have the same "
|
||||
"number of rows")
|
||||
|
||||
if use_t is None:
|
||||
#switch to use_t false if undefined
|
||||
use_t = (hasattr(self, 'use_t') and self.use_t)
|
||||
|
||||
_t = _sd = None
|
||||
|
||||
_effect = np.dot(r_matrix, self.params)
|
||||
# nan_dot multiplies with the convention nan * 0 = 0
|
||||
|
||||
# Perform the test
|
||||
if num_ttests > 1:
|
||||
_sd = np.sqrt(np.diag(self.cov_params(
|
||||
r_matrix=r_matrix, cov_p=cov_p)))
|
||||
else:
|
||||
_sd = np.sqrt(self.cov_params(r_matrix=r_matrix, cov_p=cov_p))
|
||||
_t = (_effect - q_matrix) * recipr(_sd)
|
||||
|
||||
df_resid = getattr(self, 'df_resid_inference', self.df_resid)
|
||||
|
||||
if use_t:
|
||||
return ContrastResults(effect=_effect, t=_t, sd=_sd,
|
||||
df_denom=df_resid)
|
||||
else:
|
||||
return ContrastResults(effect=_effect, statistic=_t, sd=_sd,
|
||||
df_denom=df_resid,
|
||||
distribution='norm')
|
||||
|
||||
def f_test(self, r_matrix, cov_p=None, scale=1.0, invcov=None):
|
||||
"""
|
||||
Compute the F-test for a joint linear hypothesis.
|
||||
This is a special case of `wald_test` that always uses the F
|
||||
distribution.
|
||||
Parameters
|
||||
----------
|
||||
r_matrix : array-like, str, or tuple
|
||||
- array : An r x k array where r is the number of restrictions to
|
||||
test and k is the number of regressors. It is assumed
|
||||
that the linear combination is equal to zero.
|
||||
- str : The full hypotheses to test can be given as a string.
|
||||
See the examples.
|
||||
- tuple : A tuple of arrays in the form (R, q), ``q`` can be
|
||||
either a scalar or a length k row vector.
|
||||
cov_p : array-like, optional
|
||||
An alternative estimate for the parameter covariance matrix.
|
||||
If None is given, self.normalized_cov_params is used.
|
||||
scale : float, optional
|
||||
Default is 1.0 for no scaling.
|
||||
invcov : array-like, optional
|
||||
A q x q array to specify an inverse covariance matrix based on a
|
||||
restrictions matrix.
|
||||
Returns
|
||||
-------
|
||||
res : ContrastResults instance
|
||||
The results for the test are attributes of this results instance.
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> import statsmodels.api as sm
|
||||
>>> data = sm.datasets.longley.load()
|
||||
>>> data.exog = sm.add_constant(data.exog)
|
||||
>>> results = sm.OLS(data.endog, data.exog).fit()
|
||||
>>> A = np.identity(len(results.params))
|
||||
>>> A = A[1:,:]
|
||||
This tests that each coefficient is jointly statistically
|
||||
significantly different from zero.
|
||||
>>> print(results.f_test(A))
|
||||
<F contrast: F=330.28533923463488, p=4.98403052872e-10,
|
||||
df_denom=9, df_num=6>
|
||||
Compare this to
|
||||
>>> results.fvalue
|
||||
330.2853392346658
|
||||
>>> results.f_pvalue
|
||||
4.98403096572e-10
|
||||
>>> B = np.array(([0,0,1,-1,0,0,0],[0,0,0,0,0,1,-1]))
|
||||
This tests that the coefficient on the 2nd and 3rd regressors are
|
||||
equal and jointly that the coefficient on the 5th and 6th regressors
|
||||
are equal.
|
||||
>>> print(results.f_test(B))
|
||||
<F contrast: F=9.740461873303655, p=0.00560528853174, df_denom=9,
|
||||
df_num=2>
|
||||
Alternatively, you can specify the hypothesis tests using a string
|
||||
>>> from statsmodels.datasets import longley
|
||||
>>> from statsmodels.formula.api import ols
|
||||
>>> dta = longley.load_pandas().data
|
||||
>>> formula = 'TOTEMP ~ GNPDEFL + GNP + UNEMP + ARMED + POP + YEAR'
|
||||
>>> results = ols(formula, dta).fit()
|
||||
>>> hypotheses = '(GNPDEFL = GNP), (UNEMP = 2), (YEAR/1829 = 1)'
|
||||
>>> f_test = results.f_test(hypotheses)
|
||||
>>> print(f_test)
|
||||
See Also
|
||||
--------
|
||||
statsmodels.stats.contrast.ContrastResults
|
||||
wald_test
|
||||
t_test
|
||||
patsy.DesignInfo.linear_constraint
|
||||
Notes
|
||||
-----
|
||||
The matrix `r_matrix` is assumed to be non-singular. More precisely,
|
||||
r_matrix (pX pX.T) r_matrix.T
|
||||
is assumed invertible. Here, pX is the generalized inverse of the
|
||||
design matrix of the model. There can be problems in non-OLS models
|
||||
where the rank of the covariance of the noise is not full.
|
||||
"""
|
||||
res = self.wald_test(r_matrix, cov_p=cov_p, scale=scale,
|
||||
invcov=invcov, use_f=True)
|
||||
return res
|
||||
|
||||
#TODO: untested for GLMs?
|
||||
def wald_test(self, r_matrix, cov_p=None, scale=1.0, invcov=None,
|
||||
use_f=None):
|
||||
"""
|
||||
Compute a Wald-test for a joint linear hypothesis.
|
||||
Parameters
|
||||
----------
|
||||
r_matrix : array-like, str, or tuple
|
||||
- array : An r x k array where r is the number of restrictions to
|
||||
test and k is the number of regressors. It is assumed that the
|
||||
linear combination is equal to zero.
|
||||
- str : The full hypotheses to test can be given as a string.
|
||||
See the examples.
|
||||
- tuple : A tuple of arrays in the form (R, q), ``q`` can be
|
||||
either a scalar or a length p row vector.
|
||||
cov_p : array-like, optional
|
||||
An alternative estimate for the parameter covariance matrix.
|
||||
If None is given, self.normalized_cov_params is used.
|
||||
scale : float, optional
|
||||
Default is 1.0 for no scaling.
|
||||
invcov : array-like, optional
|
||||
A q x q array to specify an inverse covariance matrix based on a
|
||||
restrictions matrix.
|
||||
use_f : bool
|
||||
If True, then the F-distribution is used. If False, then the
|
||||
asymptotic distribution, chisquare is used. If use_f is None, then
|
||||
the F distribution is used if the model specifies that use_t is True.
|
||||
The test statistic is proportionally adjusted for the distribution
|
||||
by the number of constraints in the hypothesis.
|
||||
Returns
|
||||
-------
|
||||
res : ContrastResults instance
|
||||
The results for the test are attributes of this results instance.
|
||||
See also
|
||||
--------
|
||||
statsmodels.stats.contrast.ContrastResults
|
||||
f_test
|
||||
t_test
|
||||
patsy.DesignInfo.linear_constraint
|
||||
Notes
|
||||
-----
|
||||
The matrix `r_matrix` is assumed to be non-singular. More precisely,
|
||||
r_matrix (pX pX.T) r_matrix.T
|
||||
is assumed invertible. Here, pX is the generalized inverse of the
|
||||
design matrix of the model. There can be problems in non-OLS models
|
||||
where the rank of the covariance of the noise is not full.
|
||||
"""
|
||||
if use_f is None:
|
||||
#switch to use_t false if undefined
|
||||
use_f = (hasattr(self, 'use_t') and self.use_t)
|
||||
|
||||
from patsy import DesignInfo
|
||||
names = self.model.data.param_names
|
||||
LC = DesignInfo(names).linear_constraint(r_matrix)
|
||||
r_matrix, q_matrix = LC.coefs, LC.constants
|
||||
|
||||
if (self.normalized_cov_params is None and cov_p is None and
|
||||
invcov is None and not hasattr(self, 'cov_params_default')):
|
||||
raise ValueError('need covariance of parameters for computing '
|
||||
'F statistics')
|
||||
|
||||
cparams = np.dot(r_matrix, self.params[:, None])
|
||||
J = float(r_matrix.shape[0]) # number of restrictions
|
||||
if q_matrix is None:
|
||||
q_matrix = np.zeros(J)
|
||||
else:
|
||||
q_matrix = np.asarray(q_matrix)
|
||||
if q_matrix.ndim == 1:
|
||||
q_matrix = q_matrix[:, None]
|
||||
if q_matrix.shape[0] != J:
|
||||
raise ValueError("r_matrix and q_matrix must have the same "
|
||||
"number of rows")
|
||||
Rbq = cparams - q_matrix
|
||||
if invcov is None:
|
||||
cov_p = self.cov_params(r_matrix=r_matrix, cov_p=cov_p)
|
||||
if np.isnan(cov_p).max():
|
||||
raise ValueError("r_matrix performs f_test for using "
|
||||
"dimensions that are asymptotically "
|
||||
"non-normal")
|
||||
invcov = np.linalg.inv(cov_p)
|
||||
|
||||
if (hasattr(self, 'mle_settings') and
|
||||
self.mle_settings['optimizer'] in ['l1', 'l1_cvxopt_cp']):
|
||||
F = nan_dot(nan_dot(Rbq.T, invcov), Rbq)
|
||||
else:
|
||||
F = np.dot(np.dot(Rbq.T, invcov), Rbq)
|
||||
|
||||
df_resid = getattr(self, 'df_resid_inference', self.df_resid)
|
||||
if use_f:
|
||||
F /= J
|
||||
return ContrastResults(F=F, df_denom=df_resid,
|
||||
df_num=invcov.shape[0])
|
||||
else:
|
||||
return ContrastResults(chi2=F, df_denom=J, statistic=F,
|
||||
distribution='chi2', distargs=(J,))
|
||||
|
||||
|
||||
def wald_test_terms(self, skip_single=False, extra_constraints=None,
|
||||
combine_terms=None):
|
||||
"""
|
||||
Compute a sequence of Wald tests for terms over multiple columns
|
||||
This computes joined Wald tests for the hypothesis that all
|
||||
coefficients corresponding to a `term` are zero.
|
||||
`Terms` are defined by the underlying formula or by string matching.
|
||||
Parameters
|
||||
----------
|
||||
skip_single : boolean
|
||||
If true, then terms that consist only of a single column and,
|
||||
therefore, refers only to a single parameter is skipped.
|
||||
If false, then all terms are included.
|
||||
extra_constraints : ndarray
|
||||
not tested yet
|
||||
combine_terms : None or list of strings
|
||||
Each string in this list is matched to the name of the terms or
|
||||
the name of the exogenous variables. All columns whose name
|
||||
includes that string are combined in one joint test.
|
||||
Returns
|
||||
-------
|
||||
test_result : result instance
|
||||
The result instance contains `table` which is a pandas DataFrame
|
||||
with the test results: test statistic, degrees of freedom and
|
||||
pvalues.
|
||||
Examples
|
||||
--------
|
||||
>>> res_ols = ols("np.log(Days+1) ~ C(Duration, Sum)*C(Weight, Sum)",
|
||||
data).fit()
|
||||
>>> res_ols.wald_test_terms()
|
||||
<class 'statsmodels.stats.contrast.WaldTestResults'>
|
||||
F P>F df constraint df denom
|
||||
Intercept 279.754525 2.37985521351e-22 1 51
|
||||
C(Duration, Sum) 5.367071 0.0245738436636 1 51
|
||||
C(Weight, Sum) 12.432445 3.99943118767e-05 2 51
|
||||
C(Duration, Sum):C(Weight, Sum) 0.176002 0.83912310946 2 51
|
||||
>>> res_poi = Poisson.from_formula("Days ~ C(Weight) * C(Duration)",
|
||||
data).fit(cov_type='HC0')
|
||||
>>> wt = res_poi.wald_test_terms(skip_single=False,
|
||||
combine_terms=['Duration', 'Weight'])
|
||||
>>> print(wt)
|
||||
chi2 P>chi2 df constraint
|
||||
Intercept 15.695625 7.43960374424e-05 1
|
||||
C(Weight) 16.132616 0.000313940174705 2
|
||||
C(Duration) 1.009147 0.315107378931 1
|
||||
C(Weight):C(Duration) 0.216694 0.897315972824 2
|
||||
Duration 11.187849 0.010752286833 3
|
||||
Weight 30.263368 4.32586407145e-06 4
|
||||
"""
|
||||
# lazy import
|
||||
from collections import defaultdict
|
||||
|
||||
result = self
|
||||
if extra_constraints is None:
|
||||
extra_constraints = []
|
||||
if combine_terms is None:
|
||||
combine_terms = []
|
||||
design_info = getattr(result.model.data.orig_exog, 'design_info', None)
|
||||
|
||||
if design_info is None and extra_constraints is None:
|
||||
raise ValueError('no constraints, nothing to do')
|
||||
|
||||
|
||||
identity = np.eye(len(result.params))
|
||||
constraints = []
|
||||
combined = defaultdict(list)
|
||||
if design_info is not None:
|
||||
for term in design_info.terms:
|
||||
cols = design_info.slice(term)
|
||||
name = term.name()
|
||||
constraint_matrix = identity[cols]
|
||||
|
||||
# check if in combined
|
||||
for cname in combine_terms:
|
||||
if cname in name:
|
||||
combined[cname].append(constraint_matrix)
|
||||
|
||||
k_constraint = constraint_matrix.shape[0]
|
||||
if skip_single:
|
||||
if k_constraint == 1:
|
||||
continue
|
||||
|
||||
constraints.append((name, constraint_matrix))
|
||||
|
||||
combined_constraints = []
|
||||
for cname in combine_terms:
|
||||
combined_constraints.append((cname, np.vstack(combined[cname])))
|
||||
else:
|
||||
# check by exog/params names if there is no formula info
|
||||
for col, name in enumerate(result.model.exog_names):
|
||||
constraint_matrix = identity[col]
|
||||
|
||||
# check if in combined
|
||||
for cname in combine_terms:
|
||||
if cname in name:
|
||||
combined[cname].append(constraint_matrix)
|
||||
|
||||
if skip_single:
|
||||
continue
|
||||
|
||||
constraints.append((name, constraint_matrix))
|
||||
|
||||
combined_constraints = []
|
||||
for cname in combine_terms:
|
||||
combined_constraints.append((cname, np.vstack(combined[cname])))
|
||||
|
||||
use_t = result.use_t
|
||||
distribution = ['chi2', 'F'][use_t]
|
||||
|
||||
res_wald = []
|
||||
index = []
|
||||
for name, constraint in constraints + combined_constraints + extra_constraints:
|
||||
wt = result.wald_test(constraint)
|
||||
row = [wt.statistic.item(), wt.pvalue, constraint.shape[0]]
|
||||
if use_t:
|
||||
row.append(wt.df_denom)
|
||||
res_wald.append(row)
|
||||
index.append(name)
|
||||
|
||||
# distribution nerutral names
|
||||
col_names = ['statistic', 'pvalue', 'df_constraint']
|
||||
if use_t:
|
||||
col_names.append('df_denom')
|
||||
# TODO: maybe move DataFrame creation to results class
|
||||
from pandas import DataFrame
|
||||
table = DataFrame(res_wald, index=index, columns=col_names)
|
||||
res = WaldTestResults(None, distribution, None, table=table)
|
||||
# TODO: remove temp again, added for testing
|
||||
res.temp = constraints + combined_constraints + extra_constraints
|
||||
return res
|
||||
|
||||
|
||||
def conf_int(self, alpha=.05, cols=None, method='default'):
|
||||
"""
|
||||
Returns the confidence interval of the fitted parameters.
|
||||
Parameters
|
||||
----------
|
||||
alpha : float, optional
|
||||
The significance level for the confidence interval.
|
||||
ie., The default `alpha` = .05 returns a 95% confidence interval.
|
||||
cols : array-like, optional
|
||||
`cols` specifies which confidence intervals to return
|
||||
method : string
|
||||
Not Implemented Yet
|
||||
Method to estimate the confidence_interval.
|
||||
"Default" : uses self.bse which is based on inverse Hessian for MLE
|
||||
"hjjh" :
|
||||
"jac" :
|
||||
"boot-bse"
|
||||
"boot_quant"
|
||||
"profile"
|
||||
Returns
|
||||
--------
|
||||
conf_int : array
|
||||
Each row contains [lower, upper] limits of the confidence interval
|
||||
for the corresponding parameter. The first column contains all
|
||||
lower, the second column contains all upper limits.
|
||||
Examples
|
||||
--------
|
||||
>>> import statsmodels.api as sm
|
||||
>>> data = sm.datasets.longley.load()
|
||||
>>> data.exog = sm.add_constant(data.exog)
|
||||
>>> results = sm.OLS(data.endog, data.exog).fit()
|
||||
>>> results.conf_int()
|
||||
array([[-5496529.48322745, -1467987.78596704],
|
||||
[ -177.02903529, 207.15277984],
|
||||
[ -0.1115811 , 0.03994274],
|
||||
[ -3.12506664, -0.91539297],
|
||||
[ -1.5179487 , -0.54850503],
|
||||
[ -0.56251721, 0.460309 ],
|
||||
[ 798.7875153 , 2859.51541392]])
|
||||
>>> results.conf_int(cols=(2,3))
|
||||
array([[-0.1115811 , 0.03994274],
|
||||
[-3.12506664, -0.91539297]])
|
||||
Notes
|
||||
-----
|
||||
The confidence interval is based on the standard normal distribution.
|
||||
Models wish to use a different distribution should overwrite this
|
||||
method.
|
||||
"""
|
||||
bse = self.bse
|
||||
|
||||
if self.use_t:
|
||||
dist = stats.t
|
||||
df_resid = getattr(self, 'df_resid_inference', self.df_resid)
|
||||
q = dist.ppf(1 - alpha / 2, df_resid)
|
||||
else:
|
||||
dist = stats.norm
|
||||
q = dist.ppf(1 - alpha / 2)
|
||||
|
||||
if cols is None:
|
||||
lower = self.params - q * bse
|
||||
upper = self.params + q * bse
|
||||
else:
|
||||
cols = np.asarray(cols)
|
||||
lower = self.params[cols] - q * bse[cols]
|
||||
upper = self.params[cols] + q * bse[cols]
|
||||
return np.asarray(lzip(lower, upper))
|
||||
|
||||
def save(self, fname, remove_data=False):
|
||||
'''
|
||||
save a pickle of this instance
|
||||
Parameters
|
||||
----------
|
||||
fname : string or filehandle
|
||||
fname can be a string to a file path or filename, or a filehandle.
|
||||
remove_data : bool
|
||||
If False (default), then the instance is pickled without changes.
|
||||
If True, then all arrays with length nobs are set to None before
|
||||
pickling. See the remove_data method.
|
||||
In some cases not all arrays will be set to None.
|
||||
Notes
|
||||
-----
|
||||
If remove_data is true and the model result does not implement a
|
||||
remove_data method then this will raise an exception.
|
||||
'''
|
||||
|
||||
from statsmodels.iolib.smpickle import save_pickle
|
||||
|
||||
if remove_data:
|
||||
self.remove_data()
|
||||
|
||||
save_pickle(self, fname)
|
||||
|
||||
@classmethod
|
||||
def load(cls, fname):
|
||||
'''
|
||||
load a pickle, (class method)
|
||||
Parameters
|
||||
----------
|
||||
fname : string or filehandle
|
||||
fname can be a string to a file path or filename, or a filehandle.
|
||||
Returns
|
||||
-------
|
||||
unpickled instance
|
||||
'''
|
||||
|
||||
from statsmodels.iolib.smpickle import load_pickle
|
||||
return load_pickle(fname)
|
||||
|
||||
def remove_data(self):
|
||||
'''remove data arrays, all nobs arrays from result and model
|
||||
This reduces the size of the instance, so it can be pickled with less
|
||||
memory. Currently tested for use with predict from an unpickled
|
||||
results and model instance.
|
||||
.. warning:: Since data and some intermediate results have been removed
|
||||
calculating new statistics that require them will raise exceptions.
|
||||
The exception will occur the first time an attribute is accessed
|
||||
that has been set to None.
|
||||
Not fully tested for time series models, tsa, and might delete too much
|
||||
for prediction or not all that would be possible.
|
||||
The list of arrays to delete is maintained as an attribute of the
|
||||
result and model instance, except for cached values. These lists could
|
||||
be changed before calling remove_data.
|
||||
'''
|
||||
def wipe(obj, att):
|
||||
#get to last element in attribute path
|
||||
p = att.split('.')
|
||||
att_ = p.pop(-1)
|
||||
try:
|
||||
obj_ = reduce(getattr, [obj] + p)
|
||||
|
||||
#print(repr(obj), repr(att))
|
||||
#print(hasattr(obj_, att_))
|
||||
if hasattr(obj_, att_):
|
||||
#print('removing3', att_)
|
||||
setattr(obj_, att_, None)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
model_attr = ['model.' + i for i in self.model._data_attr]
|
||||
for att in self._data_attr + model_attr:
|
||||
#print('removing', att)
|
||||
wipe(self, att)
|
||||
|
||||
data_in_cache = getattr(self, 'data_in_cache', [])
|
||||
data_in_cache += ['fittedvalues', 'resid', 'wresid']
|
||||
for key in data_in_cache:
|
||||
try:
|
||||
self._cache[key] = None
|
||||
except (AttributeError, KeyError):
|
||||
pass
|
||||
|
||||
def lzip(*args, **kwargs):
|
||||
return list(zip(*args, **kwargs))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,326 @@
|
||||
|
||||
import numpy as np
|
||||
import numpy.linalg as la
|
||||
from pysal.spreg.utils import RegressionPropsY, spdot
|
||||
import pysal.spreg.user_output as USER
|
||||
from utils import cache_readonly
|
||||
from base import LikelihoodModelResults
|
||||
import family
|
||||
from iwls import iwls
|
||||
|
||||
__all__ = ['GLM']
|
||||
|
||||
class GLM(RegressionPropsY):
|
||||
"""
|
||||
Generalised linear models. Can currently estimate Guassian, Poisson and
|
||||
Logisitc regression coefficients. GLM object prepares model input and fit
|
||||
method performs estimation which then returns a GLMResults object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
y : array
|
||||
n*1, dependent variable.
|
||||
X : array
|
||||
n*k, independent variable, exlcuding the constant.
|
||||
family : string
|
||||
Model type: 'Gaussian', 'Poisson', 'Binomial'
|
||||
|
||||
Attributes
|
||||
----------
|
||||
y : array
|
||||
n*1, dependent variable.
|
||||
X : array
|
||||
n*k, independent variable, including constant.
|
||||
family : string
|
||||
Model type: 'Gaussian', 'Poisson', 'logistic'
|
||||
n : integer
|
||||
Number of observations
|
||||
k : integer
|
||||
Number of independent variables
|
||||
df_model : float
|
||||
k-1, where k is the number of variables (including
|
||||
intercept)
|
||||
df_residual : float
|
||||
observations minus variables (n-k)
|
||||
mean_y : float
|
||||
Mean of y
|
||||
std_y : float
|
||||
Standard deviation of y
|
||||
fit_params : dict
|
||||
Parameters passed into fit method to define estimation
|
||||
routine.
|
||||
normalized_cov_params : array
|
||||
k*k, approximates [X.T*X]-1
|
||||
"""
|
||||
def __init__(self, y, X, family=family.Gaussian(), constant=True):
|
||||
"""
|
||||
Initialize class
|
||||
"""
|
||||
self.n = USER.check_arrays(y, X)
|
||||
USER.check_y(y, self.n)
|
||||
self.y = y
|
||||
if constant:
|
||||
self.X = USER.check_constant(X)
|
||||
else:
|
||||
self.X = X
|
||||
self.family = family
|
||||
self.k = self.X.shape[1]
|
||||
self.fit_params = {}
|
||||
|
||||
def fit(self, ini_betas=None, tol=1.0e-6, max_iter=200, solve='iwls'):
|
||||
"""
|
||||
Method that fits a model with a particular estimation routine.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
ini_betas : array
|
||||
k*1, initial coefficient values, including constant.
|
||||
Default is None, which calculates initial values during
|
||||
estimation.
|
||||
tol: float
|
||||
Tolerence for estimation convergence.
|
||||
max_iter : integer
|
||||
Maximum number of iterations if convergence not
|
||||
achieved.
|
||||
solve :string
|
||||
Technique to solve MLE equations.
|
||||
'iwls' = iteratively (re)weighted least squares (default)
|
||||
"""
|
||||
self.fit_params['ini_betas'] = ini_betas
|
||||
self.fit_params['tol'] = tol
|
||||
self.fit_params['max_iter'] = max_iter
|
||||
self.fit_params['solve']=solve
|
||||
if solve.lower() == 'iwls':
|
||||
params, predy, w, n_iter = iwls(self.y, self.X, self.family,
|
||||
ini_betas=ini_betas, tol=tol, max_iter=max_iter)
|
||||
self.fit_params['n_iter'] = n_iter
|
||||
return GLMResults(self, params.flatten(), predy, w)
|
||||
|
||||
@cache_readonly
|
||||
def df_model(self):
|
||||
return self.X.shape[1] - 1
|
||||
|
||||
@cache_readonly
|
||||
def df_resid(self):
|
||||
return self.n - self.df_model - 1
|
||||
|
||||
class GLMResults(LikelihoodModelResults):
|
||||
"""
|
||||
Results of estimated GLM and diagnostics.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
model : GLM object
|
||||
Pointer to GLM object with estimation parameters.
|
||||
params : array
|
||||
k*1, estimared coefficients
|
||||
mu : array
|
||||
n*1, predicted y values.
|
||||
w : array
|
||||
n*1, final weight used for iwls
|
||||
|
||||
Attributes
|
||||
----------
|
||||
model : GLM Object
|
||||
Points to GLM object for which parameters have been
|
||||
estimated.
|
||||
y : array
|
||||
n*1, dependent variable.
|
||||
x : array
|
||||
n*k, independent variable, including constant.
|
||||
family : string
|
||||
Model type: 'Gaussian', 'Poisson', 'Logistic'
|
||||
n : integer
|
||||
Number of observations
|
||||
k : integer
|
||||
Number of independent variables
|
||||
df_model : float
|
||||
k-1, where k is the number of variables (including
|
||||
intercept)
|
||||
df_residual : float
|
||||
observations minus variables (n-k)
|
||||
fit_params : dict
|
||||
parameters passed into fit method to define estimation
|
||||
routine.
|
||||
scale : float
|
||||
sigma squared used for subsequent computations.
|
||||
params : array
|
||||
n*k, estimared beta coefficients
|
||||
w : array
|
||||
n*1, final weight values of x
|
||||
mu : array
|
||||
n*1, predicted value of y (i.e., fittedvalues)
|
||||
cov_params : array
|
||||
Variance covariance matrix (kxk) of betas which has been
|
||||
appropriately scaled by sigma-squared
|
||||
bse : array
|
||||
k*1, standard errors of betas
|
||||
pvalues : array
|
||||
k*1, two-tailed pvalues of parameters
|
||||
tvalues : array
|
||||
k*1, the tvalues of the standard errors
|
||||
null : array
|
||||
n*1, predicted values of y for null model
|
||||
deviance : float
|
||||
value of the deviance function evalued at params;
|
||||
see family.py for distribution-specific deviance
|
||||
null_deviance : float
|
||||
value of the deviance function for the model fit with
|
||||
a constant as the only regressor
|
||||
llf : float
|
||||
value of the loglikelihood function evalued at params;
|
||||
see family.py for distribution-specific loglikelihoods
|
||||
llnull : float
|
||||
value of log-likelihood function evaluated at null
|
||||
aic : float
|
||||
AIC
|
||||
bic : float
|
||||
BIC
|
||||
D2 : float
|
||||
percent deviance explained
|
||||
adj_D2 : float
|
||||
adjusted percent deviance explained
|
||||
pseudo_R2 : float
|
||||
McFadden's pseudo R2 (coefficient of determination)
|
||||
adj_pseudoR2 : float
|
||||
adjusted McFadden's pseudo R2
|
||||
resid_response : array
|
||||
response residuals; defined as y-mu
|
||||
resid_pearson : array
|
||||
Pearson residuals; defined as (y-mu)/sqrt(VAR(mu))
|
||||
where VAR is the distribution specific variance
|
||||
function; see family.py and varfuncs.py for more information.
|
||||
resid_working : array
|
||||
Working residuals; the working residuals are defined as
|
||||
resid_response/link'(mu); see links.py for the
|
||||
derivatives of the link functions.
|
||||
|
||||
resid_anscombe : array
|
||||
Anscombe residuals; see family.py for
|
||||
distribution-specific Anscombe residuals.
|
||||
|
||||
resid_deviance : array
|
||||
deviance residuals; see family.py for
|
||||
distribution-specific deviance residuals.
|
||||
|
||||
pearson_chi2 : float
|
||||
chi-Squared statistic is defined as the sum
|
||||
of the squares of the Pearson residuals
|
||||
|
||||
normalized_cov_params : array
|
||||
k*k, approximates [X.T*X]-1
|
||||
"""
|
||||
def __init__(self, model, params, mu, w):
|
||||
self.model = model
|
||||
self.n = model.n
|
||||
self.y = model.y.T.flatten()
|
||||
self.X = model.X
|
||||
self.k = model.k
|
||||
self.family = model.family
|
||||
self.fit_params = model.fit_params
|
||||
self.params = params
|
||||
self.w = w
|
||||
self.mu = mu.flatten()
|
||||
self._cache = {}
|
||||
|
||||
@cache_readonly
|
||||
def df_model(self):
|
||||
return self.model.df_model
|
||||
|
||||
@cache_readonly
|
||||
def df_resid(self):
|
||||
return self.model.df_resid
|
||||
|
||||
@cache_readonly
|
||||
def normalized_cov_params(self):
|
||||
return la.inv(spdot(self.w.T, self.w))
|
||||
|
||||
@cache_readonly
|
||||
def resid_response(self):
|
||||
return (self.y-self.mu)
|
||||
|
||||
@cache_readonly
|
||||
def resid_pearson(self):
|
||||
return ((self.y-self.mu) /
|
||||
np.sqrt(self.family.variance(self.mu)))
|
||||
|
||||
@cache_readonly
|
||||
def resid_working(self):
|
||||
return (self.resid_response / self.family.link.deriv(self.mu))
|
||||
|
||||
@cache_readonly
|
||||
def resid_anscombe(self):
|
||||
return (self.family.resid_anscombe(self.y, self.mu))
|
||||
|
||||
@cache_readonly
|
||||
def resid_deviance(self):
|
||||
return (self.family.resid_dev(self.y, self.mu))
|
||||
|
||||
@cache_readonly
|
||||
def pearson_chi2(self):
|
||||
chisq = (self.y - self.mu)**2 / self.family.variance(self.mu)
|
||||
chisqsum = np.sum(chisq)
|
||||
return chisqsum
|
||||
|
||||
@cache_readonly
|
||||
def null(self):
|
||||
y = np.reshape(self.y, (-1,1))
|
||||
model = self.model
|
||||
X = np.ones((len(y), 1))
|
||||
null_mod = GLM(y, X, family=self.family, constant=False)
|
||||
return null_mod.fit().mu
|
||||
|
||||
@cache_readonly
|
||||
def scale(self):
|
||||
if isinstance(self.family, (family.Binomial, family.Poisson)):
|
||||
return 1.
|
||||
else:
|
||||
return (((np.power(self.resid_response, 2) /
|
||||
self.family.variance(self.mu))).sum() /
|
||||
(self.df_resid))
|
||||
@cache_readonly
|
||||
def deviance(self):
|
||||
return self.family.deviance(self.y, self.mu)
|
||||
|
||||
@cache_readonly
|
||||
def null_deviance(self):
|
||||
return self.family.deviance(self.y, self.null)
|
||||
|
||||
@cache_readonly
|
||||
def llnull(self):
|
||||
return self.family.loglike(self.y, self.null, scale=self.scale)
|
||||
|
||||
@cache_readonly
|
||||
def llf(self):
|
||||
return self.family.loglike(self.y, self.mu, scale=self.scale)
|
||||
|
||||
@cache_readonly
|
||||
def aic(self):
|
||||
if isinstance(self.family, family.QuasiPoisson):
|
||||
return np.nan
|
||||
else:
|
||||
return -2 * self.llf + 2*(self.df_model+1)
|
||||
|
||||
@cache_readonly
|
||||
def bic(self):
|
||||
return (self.deviance -
|
||||
(self.model.n - self.df_model - 1) *
|
||||
np.log(self.model.n))
|
||||
|
||||
@cache_readonly
|
||||
def D2(self):
|
||||
return 1 - (self.deviance / self.null_deviance)
|
||||
|
||||
@cache_readonly
|
||||
def adj_D2(self):
|
||||
return 1.0 - (float(self.n) - 1.0)/(float(self.n) - float(self.k)) * (1.0-self.D2)
|
||||
|
||||
@cache_readonly
|
||||
def pseudoR2(self):
|
||||
return 1 - (self.llf/self.llnull)
|
||||
|
||||
@cache_readonly
|
||||
def adj_pseudoR2(self):
|
||||
return 1 - ((self.llf-self.k)/self.llnull)
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import numpy as np
|
||||
import numpy.linalg as la
|
||||
from scipy import sparse as sp
|
||||
from scipy.sparse import linalg as spla
|
||||
from pysal.spreg.utils import spdot, spmultiply
|
||||
from family import Binomial, Poisson
|
||||
|
||||
def _compute_betas(y, x):
|
||||
"""
|
||||
compute MLE coefficients using iwls routine
|
||||
|
||||
Methods: p189, Iteratively (Re)weighted Least Squares (IWLS),
|
||||
Fotheringham, A. S., Brunsdon, C., & Charlton, M. (2002).
|
||||
Geographically weighted regression: the analysis of spatially varying relationships.
|
||||
"""
|
||||
xT = x.T
|
||||
xtx = spdot(xT, x)
|
||||
xtx_inv = la.inv(xtx)
|
||||
xtx_inv = sp.csr_matrix(xtx_inv)
|
||||
xTy = spdot(xT, y, array_out=False)
|
||||
betas = spdot(xtx_inv, xTy)
|
||||
return betas
|
||||
|
||||
def _compute_betas_gwr(y, x, wi):
|
||||
"""
|
||||
compute MLE coefficients using iwls routine
|
||||
|
||||
Methods: p189, Iteratively (Re)weighted Least Squares (IWLS),
|
||||
Fotheringham, A. S., Brunsdon, C., & Charlton, M. (2002).
|
||||
Geographically weighted regression: the analysis of spatially varying relationships.
|
||||
"""
|
||||
xT = (x * wi).T
|
||||
xtx = np.dot(xT, x)
|
||||
xtx_inv = la.inv(xtx)
|
||||
xtx_inv_xt = np.dot(xtx_inv, xT)
|
||||
betas = np.dot(xtx_inv_xt, y)
|
||||
return betas, xtx_inv_xt
|
||||
|
||||
def iwls(y, x, family, offset=1.0, ini_betas=None, tol=1.0e-8, max_iter=200, wi=None):
|
||||
"""
|
||||
Iteratively re-weighted least squares estimation routine
|
||||
"""
|
||||
n_iter = 0
|
||||
diff = 1.0e6
|
||||
if ini_betas is None:
|
||||
betas = np.zeros((x.shape[1], 1), np.float)
|
||||
else:
|
||||
betas = ini_betas
|
||||
if isinstance(family, Binomial):
|
||||
y = family.link._clean(y)
|
||||
if isinstance(family, Poisson):
|
||||
y_off = y/offset
|
||||
y_off = family.starting_mu(y_off)
|
||||
v = family.predict(y_off)
|
||||
mu = family.starting_mu(y)
|
||||
else:
|
||||
mu = family.starting_mu(y)
|
||||
v = family.predict(mu)
|
||||
|
||||
while diff > tol and n_iter < max_iter:
|
||||
n_iter += 1
|
||||
w = family.weights(mu)
|
||||
z = v + (family.link.deriv(mu)*(y-mu))
|
||||
w = np.sqrt(w)
|
||||
if type(x) != np.ndarray:
|
||||
w = sp.csr_matrix(w)
|
||||
z = sp.csr_matrix(z)
|
||||
wx = spmultiply(x, w, array_out=False)
|
||||
wz = spmultiply(z, w, array_out=False)
|
||||
if wi is None:
|
||||
n_betas = _compute_betas(wz, wx)
|
||||
else:
|
||||
n_betas, xtx_inv_xt = _compute_betas_gwr(wz, wx, wi)
|
||||
v = spdot(x, n_betas)
|
||||
mu = family.fitted(v)
|
||||
if isinstance(family, Poisson):
|
||||
mu = mu * offset
|
||||
diff = min(abs(n_betas-betas))
|
||||
betas = n_betas
|
||||
|
||||
if wi is None:
|
||||
return betas, mu, wx, n_iter
|
||||
else:
|
||||
return betas, mu, v, w, z, xtx_inv_xt, n_iter
|
||||
@@ -0,0 +1,953 @@
|
||||
'''
|
||||
Defines the link functions to be used with GLM and GEE families.
|
||||
'''
|
||||
|
||||
import numpy as np
|
||||
import scipy.stats
|
||||
FLOAT_EPS = np.finfo(float).eps
|
||||
|
||||
|
||||
class Link(object):
|
||||
"""
|
||||
A generic link function for one-parameter exponential family.
|
||||
|
||||
`Link` does nothing, but lays out the methods expected of any subclass.
|
||||
"""
|
||||
|
||||
def __call__(self, p):
|
||||
"""
|
||||
Return the value of the link function. This is just a placeholder.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Probabilities
|
||||
|
||||
Returns
|
||||
-------
|
||||
g(p) : array-like
|
||||
The value of the link function g(p) = z
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def inverse(self, z):
|
||||
"""
|
||||
Inverse of the link function. Just a placeholder.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
`z` is usually the linear predictor of the transformed variable
|
||||
in the IRLS algorithm for GLM.
|
||||
|
||||
Returns
|
||||
-------
|
||||
g^(-1)(z) : array
|
||||
The value of the inverse of the link function g^(-1)(z) = p
|
||||
|
||||
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def deriv(self, p):
|
||||
"""
|
||||
Derivative of the link function g'(p). Just a placeholder.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'(p) : array
|
||||
The value of the derivative of the link function g'(p)
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def deriv2(self, p):
|
||||
"""Second derivative of the link function g''(p)
|
||||
|
||||
implemented through numerical differentiation
|
||||
"""
|
||||
from statsmodels.tools.numdiff import approx_fprime_cs
|
||||
# TODO: workaround proplem with numdiff for 1d
|
||||
return np.diag(approx_fprime_cs(p, self.deriv))
|
||||
|
||||
def inverse_deriv(self, z):
|
||||
"""
|
||||
Derivative of the inverse link function g^(-1)(z).
|
||||
|
||||
Notes
|
||||
-----
|
||||
This reference implementation gives the correct result but is
|
||||
inefficient, so it can be overriden in subclasses.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
`z` is usually the linear predictor for a GLM or GEE model.
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'^(-1)(z) : array
|
||||
The value of the derivative of the inverse of the link function
|
||||
|
||||
"""
|
||||
return 1 / self.deriv(self.inverse(z))
|
||||
|
||||
|
||||
class Logit(Link):
|
||||
"""
|
||||
The logit transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
call and derivative use a private method _clean to make trim p by
|
||||
machine epsilon so that p is in (0,1)
|
||||
|
||||
Alias of Logit:
|
||||
logit = Logit()
|
||||
"""
|
||||
|
||||
def _clean(self, p):
|
||||
"""
|
||||
Clip logistic values to range (eps, 1-eps)
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
p : array-like
|
||||
Probabilities
|
||||
|
||||
Returns
|
||||
--------
|
||||
pclip : array
|
||||
Clipped probabilities
|
||||
"""
|
||||
return np.clip(p, FLOAT_EPS, 1. - FLOAT_EPS)
|
||||
|
||||
def __call__(self, p):
|
||||
"""
|
||||
The logit transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Probabilities
|
||||
|
||||
Returns
|
||||
-------
|
||||
z : array
|
||||
Logit transform of `p`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = log(p / (1 - p))
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return np.log(p / (1. - p))
|
||||
|
||||
def inverse(self, z):
|
||||
"""
|
||||
Inverse of the logit transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
The value of the logit transform at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
p : array
|
||||
Probabilities
|
||||
|
||||
Notes
|
||||
-----
|
||||
g^(-1)(z) = exp(z)/(1+exp(z))
|
||||
"""
|
||||
z = np.asarray(z)
|
||||
t = np.exp(-z)
|
||||
return 1. / (1. + t)
|
||||
|
||||
def deriv(self, p):
|
||||
|
||||
"""
|
||||
Derivative of the logit transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p: array-like
|
||||
Probabilities
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'(p) : array
|
||||
Value of the derivative of logit transform at `p`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g'(p) = 1 / (p * (1 - p))
|
||||
|
||||
Alias for `Logit`:
|
||||
logit = Logit()
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return 1. / (p * (1 - p))
|
||||
|
||||
def inverse_deriv(self, z):
|
||||
"""
|
||||
Derivative of the inverse of the logit transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
`z` is usually the linear predictor for a GLM or GEE model.
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'^(-1)(z) : array
|
||||
The value of the derivative of the inverse of the logit function
|
||||
|
||||
"""
|
||||
t = np.exp(z)
|
||||
return t/(1 + t)**2
|
||||
|
||||
|
||||
def deriv2(self, p):
|
||||
"""
|
||||
Second derivative of the logit function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
probabilities
|
||||
|
||||
Returns
|
||||
-------
|
||||
g''(z) : array
|
||||
The value of the second derivative of the logit function
|
||||
"""
|
||||
v = p * (1 - p)
|
||||
return (2*p - 1) / v**2
|
||||
|
||||
class logit(Logit):
|
||||
pass
|
||||
|
||||
|
||||
class Power(Link):
|
||||
"""
|
||||
The power transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
power : float
|
||||
The exponent of the power transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
Aliases of Power:
|
||||
inverse = Power(power=-1)
|
||||
sqrt = Power(power=.5)
|
||||
inverse_squared = Power(power=-2.)
|
||||
identity = Power(power=1.)
|
||||
"""
|
||||
|
||||
def __init__(self, power=1.):
|
||||
self.power = power
|
||||
|
||||
def __call__(self, p):
|
||||
"""
|
||||
Power transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
z : array-like
|
||||
Power transform of x
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = x**self.power
|
||||
"""
|
||||
|
||||
z = np.power(p, self.power)
|
||||
return z
|
||||
|
||||
def inverse(self, z):
|
||||
"""
|
||||
Inverse of the power transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
`z` : array-like
|
||||
Value of the transformed mean parameters at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
`p` : array
|
||||
Mean parameters
|
||||
|
||||
Notes
|
||||
-----
|
||||
g^(-1)(z`) = `z`**(1/`power`)
|
||||
"""
|
||||
|
||||
p = np.power(z, 1. / self.power)
|
||||
return p
|
||||
|
||||
def deriv(self, p):
|
||||
"""
|
||||
Derivative of the power transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
--------
|
||||
g'(p) : array
|
||||
Derivative of power transform of `p`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g'(`p`) = `power` * `p`**(`power` - 1)
|
||||
"""
|
||||
return self.power * np.power(p, self.power - 1)
|
||||
|
||||
def deriv2(self, p):
|
||||
"""
|
||||
Second derivative of the power transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
--------
|
||||
g''(p) : array
|
||||
Second derivative of the power transform of `p`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g''(`p`) = `power` * (`power` - 1) * `p`**(`power` - 2)
|
||||
"""
|
||||
return self.power * (self.power - 1) * np.power(p, self.power - 2)
|
||||
|
||||
def inverse_deriv(self, z):
|
||||
"""
|
||||
Derivative of the inverse of the power transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
`z` is usually the linear predictor for a GLM or GEE model.
|
||||
|
||||
Returns
|
||||
-------
|
||||
g^(-1)'(z) : array
|
||||
The value of the derivative of the inverse of the power transform
|
||||
function
|
||||
"""
|
||||
return np.power(z, (1 - self.power)/self.power) / self.power
|
||||
|
||||
|
||||
class inverse_power(Power):
|
||||
"""
|
||||
The inverse transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = 1/p
|
||||
|
||||
Alias of statsmodels.family.links.Power(power=-1.)
|
||||
"""
|
||||
def __init__(self):
|
||||
super(inverse_power, self).__init__(power=-1.)
|
||||
|
||||
|
||||
class sqrt(Power):
|
||||
"""
|
||||
The square-root transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(`p`) = sqrt(`p`)
|
||||
|
||||
Alias of statsmodels.family.links.Power(power=.5)
|
||||
"""
|
||||
def __init__(self):
|
||||
super(sqrt, self).__init__(power=.5)
|
||||
|
||||
|
||||
class inverse_squared(Power):
|
||||
"""
|
||||
The inverse squared transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(`p`) = 1/(`p`\ \*\*2)
|
||||
|
||||
Alias of statsmodels.family.links.Power(power=2.)
|
||||
"""
|
||||
def __init__(self):
|
||||
super(inverse_squared, self).__init__(power=-2.)
|
||||
|
||||
|
||||
class identity(Power):
|
||||
"""
|
||||
The identity transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(`p`) = `p`
|
||||
|
||||
Alias of statsmodels.family.links.Power(power=1.)
|
||||
"""
|
||||
def __init__(self):
|
||||
super(identity, self).__init__(power=1.)
|
||||
|
||||
|
||||
class Log(Link):
|
||||
"""
|
||||
The log transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
call and derivative call a private method _clean to trim the data by
|
||||
machine epsilon so that p is in (0,1). log is an alias of Log.
|
||||
"""
|
||||
|
||||
def _clean(self, x):
|
||||
return np.clip(x, FLOAT_EPS, np.inf)
|
||||
|
||||
def __call__(self, p, **extra):
|
||||
"""
|
||||
Log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
z : array
|
||||
log(x)
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = log(p)
|
||||
"""
|
||||
x = self._clean(p)
|
||||
return np.log(x)
|
||||
|
||||
def inverse(self, z):
|
||||
"""
|
||||
Inverse of log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array
|
||||
The inverse of the link function at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
p : array
|
||||
The mean probabilities given the value of the inverse `z`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g^{-1}(z) = exp(z)
|
||||
"""
|
||||
return np.exp(z)
|
||||
|
||||
def deriv(self, p):
|
||||
"""
|
||||
Derivative of log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'(p) : array
|
||||
derivative of log transform of x
|
||||
|
||||
Notes
|
||||
-----
|
||||
g'(x) = 1/x
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return 1. / p
|
||||
|
||||
def deriv2(self, p):
|
||||
"""
|
||||
Second derivative of the log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
g''(p) : array
|
||||
Second derivative of log transform of x
|
||||
|
||||
Notes
|
||||
-----
|
||||
g''(x) = -1/x^2
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return -1. / p**2
|
||||
|
||||
def inverse_deriv(self, z):
|
||||
"""
|
||||
Derivative of the inverse of the log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array
|
||||
The inverse of the link function at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
g^(-1)'(z) : array
|
||||
The value of the derivative of the inverse of the log function,
|
||||
the exponential function
|
||||
"""
|
||||
return np.exp(z)
|
||||
|
||||
|
||||
class log(Log):
|
||||
"""
|
||||
The log transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
log is a an alias of Log.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# TODO: the CDFLink is untested
|
||||
class CDFLink(Logit):
|
||||
"""
|
||||
The use the CDF of a scipy.stats distribution
|
||||
|
||||
CDFLink is a subclass of logit in order to use its _clean method
|
||||
for the link and its derivative.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dbn : scipy.stats distribution
|
||||
Default is dbn=scipy.stats.norm
|
||||
|
||||
Notes
|
||||
-----
|
||||
The CDF link is untested.
|
||||
"""
|
||||
|
||||
def __init__(self, dbn=scipy.stats.norm):
|
||||
self.dbn = dbn
|
||||
|
||||
def __call__(self, p):
|
||||
"""
|
||||
CDF link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
z : array
|
||||
(ppf) inverse of CDF transform of p
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(`p`) = `dbn`.ppf(`p`)
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return self.dbn.ppf(p)
|
||||
|
||||
def inverse(self, z):
|
||||
"""
|
||||
The inverse of the CDF link
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
The value of the inverse of the link function at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
p : array
|
||||
Mean probabilities. The value of the inverse of CDF link of `z`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g^(-1)(`z`) = `dbn`.cdf(`z`)
|
||||
"""
|
||||
return self.dbn.cdf(z)
|
||||
|
||||
def deriv(self, p):
|
||||
"""
|
||||
Derivative of CDF link
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'(p) : array
|
||||
The derivative of CDF transform at `p`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g'(`p`) = 1./ `dbn`.pdf(`dbn`.ppf(`p`))
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return 1. / self.dbn.pdf(self.dbn.ppf(p))
|
||||
|
||||
def deriv2(self, p):
|
||||
"""
|
||||
Second derivative of the link function g''(p)
|
||||
|
||||
implemented through numerical differentiation
|
||||
"""
|
||||
from statsmodels.tools.numdiff import approx_fprime
|
||||
p = np.atleast_1d(p)
|
||||
# Note: special function for norm.ppf does not support complex
|
||||
return np.diag(approx_fprime(p, self.deriv, centered=True))
|
||||
|
||||
def inverse_deriv(self, z):
|
||||
"""
|
||||
Derivative of the inverse of the CDF transformation link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array
|
||||
The inverse of the link function at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
g^(-1)'(z) : array
|
||||
The value of the derivative of the inverse of the logit function
|
||||
"""
|
||||
return 1/self.deriv(self.inverse(z))
|
||||
|
||||
|
||||
class probit(CDFLink):
|
||||
"""
|
||||
The probit (standard normal CDF) transform
|
||||
|
||||
Notes
|
||||
--------
|
||||
g(p) = scipy.stats.norm.ppf(p)
|
||||
|
||||
probit is an alias of CDFLink.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class cauchy(CDFLink):
|
||||
"""
|
||||
The Cauchy (standard Cauchy CDF) transform
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = scipy.stats.cauchy.ppf(p)
|
||||
|
||||
cauchy is an alias of CDFLink with dbn=scipy.stats.cauchy
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(cauchy, self).__init__(dbn=scipy.stats.cauchy)
|
||||
|
||||
def deriv2(self, p):
|
||||
"""
|
||||
Second derivative of the Cauchy link function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p: array-like
|
||||
Probabilities
|
||||
|
||||
Returns
|
||||
-------
|
||||
g''(p) : array
|
||||
Value of the second derivative of Cauchy link function at `p`
|
||||
"""
|
||||
a = np.pi * (p - 0.5)
|
||||
d2 = 2 * np.pi**2 * np.sin(a) / np.cos(a)**3
|
||||
return d2
|
||||
|
||||
class CLogLog(Logit):
|
||||
"""
|
||||
The complementary log-log transform
|
||||
|
||||
CLogLog inherits from Logit in order to have access to its _clean method
|
||||
for the link and its derivative.
|
||||
|
||||
Notes
|
||||
-----
|
||||
CLogLog is untested.
|
||||
"""
|
||||
def __call__(self, p):
|
||||
"""
|
||||
C-Log-Log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
z : array
|
||||
The CLogLog transform of `p`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = log(-log(1-p))
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return np.log(-np.log(1 - p))
|
||||
|
||||
def inverse(self, z):
|
||||
"""
|
||||
Inverse of C-Log-Log transform link function
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
The value of the inverse of the CLogLog link function at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
p : array
|
||||
Mean parameters
|
||||
|
||||
Notes
|
||||
-----
|
||||
g^(-1)(`z`) = 1-exp(-exp(`z`))
|
||||
"""
|
||||
return 1 - np.exp(-np.exp(z))
|
||||
|
||||
def deriv(self, p):
|
||||
"""
|
||||
Derivative of C-Log-Log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'(p) : array
|
||||
The derivative of the CLogLog transform link function
|
||||
|
||||
Notes
|
||||
-----
|
||||
g'(p) = - 1 / ((p-1)*log(1-p))
|
||||
"""
|
||||
p = self._clean(p)
|
||||
return 1. / ((p - 1) * (np.log(1 - p)))
|
||||
|
||||
def deriv2(self, p):
|
||||
"""
|
||||
Second derivative of the C-Log-Log ink function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
g''(p) : array
|
||||
The second derivative of the CLogLog link function
|
||||
"""
|
||||
p = self._clean(p)
|
||||
fl = np.log(1 - p)
|
||||
d2 = -1 / ((1 - p)**2 * fl)
|
||||
d2 *= 1 + 1 / fl
|
||||
return d2
|
||||
|
||||
def inverse_deriv(self, z):
|
||||
"""
|
||||
Derivative of the inverse of the C-Log-Log transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
z : array-like
|
||||
The value of the inverse of the CLogLog link function at `p`
|
||||
|
||||
Returns
|
||||
-------
|
||||
g^(-1)'(z) : array
|
||||
The derivative of the inverse of the CLogLog link function
|
||||
"""
|
||||
return np.exp(z - np.exp(z))
|
||||
|
||||
|
||||
class cloglog(CLogLog):
|
||||
"""
|
||||
The CLogLog transform link function.
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(`p`) = log(-log(1-`p`))
|
||||
|
||||
cloglog is an alias for CLogLog
|
||||
cloglog = CLogLog()
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NegativeBinomial(object):
|
||||
'''
|
||||
The negative binomial link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
alpha : float, optional
|
||||
Alpha is the ancillary parameter of the Negative Binomial link
|
||||
function. It is assumed to be nonstochastic. The default value is 1.
|
||||
Permissible values are usually assumed to be in (.01, 2).
|
||||
'''
|
||||
|
||||
def __init__(self, alpha=1.):
|
||||
self.alpha = alpha
|
||||
|
||||
def _clean(self, x):
|
||||
return np.clip(x, FLOAT_EPS, np.inf)
|
||||
|
||||
def __call__(self, p):
|
||||
'''
|
||||
Negative Binomial transform link function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
z : array
|
||||
The negative binomial transform of `p`
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = log(p/(p + 1/alpha))
|
||||
'''
|
||||
p = self._clean(p)
|
||||
return np.log(p/(p + 1/self.alpha))
|
||||
|
||||
def inverse(self, z):
|
||||
'''
|
||||
Inverse of the negative binomial transform
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
z : array-like
|
||||
The value of the inverse of the negative binomial link at `p`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
p : array
|
||||
Mean parameters
|
||||
|
||||
Notes
|
||||
-----
|
||||
g^(-1)(z) = exp(z)/(alpha*(1-exp(z)))
|
||||
'''
|
||||
return -1/(self.alpha * (1 - np.exp(-z)))
|
||||
|
||||
def deriv(self, p):
|
||||
'''
|
||||
Derivative of the negative binomial transform
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
g'(p) : array
|
||||
The derivative of the negative binomial transform link function
|
||||
|
||||
Notes
|
||||
-----
|
||||
g'(x) = 1/(x+alpha*x^2)
|
||||
'''
|
||||
return 1/(p + self.alpha * p**2)
|
||||
|
||||
def deriv2(self,p):
|
||||
'''
|
||||
Second derivative of the negative binomial link function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
p : array-like
|
||||
Mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
g''(p) : array
|
||||
The second derivative of the negative binomial transform link
|
||||
function
|
||||
|
||||
Notes
|
||||
-----
|
||||
g''(x) = -(1+2*alpha*x)/(x+alpha*x^2)^2
|
||||
'''
|
||||
numer = -(1 + 2 * self.alpha * p)
|
||||
denom = (p + self.alpha * p**2)**2
|
||||
return numer / denom
|
||||
|
||||
def inverse_deriv(self, z):
|
||||
'''
|
||||
Derivative of the inverse of the negative binomial transform
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
z : array-like
|
||||
Usually the linear predictor for a GLM or GEE model
|
||||
|
||||
Returns
|
||||
-------
|
||||
g^(-1)'(z) : array
|
||||
The value of the derivative of the inverse of the negative
|
||||
binomial link
|
||||
'''
|
||||
t = np.exp(z)
|
||||
return t / (self.alpha * (1-t)**2)
|
||||
|
||||
|
||||
class nbinom(NegativeBinomial):
|
||||
"""
|
||||
The negative binomial link function.
|
||||
|
||||
Notes
|
||||
-----
|
||||
g(p) = log(p/(p + 1/alpha))
|
||||
|
||||
nbinom is an alias of NegativeBinomial.
|
||||
nbinom = NegativeBinomial(alpha=1.)
|
||||
"""
|
||||
pass
|
||||
@@ -0,0 +1,993 @@
|
||||
"""
|
||||
Tests for generalized linear models. Majority of code either directly borrowed
|
||||
or closely adapted from statsmodels package. Model results verfiied using glm
|
||||
function in R and GLM function in statsmodels.
|
||||
"""
|
||||
|
||||
__author__ = 'Taylor Oshan tayoshan@gmail.com'
|
||||
|
||||
from pysal.contrib.glm.glm import GLM
|
||||
from pysal.contrib.glm.family import Gaussian, Poisson, Binomial, QuasiPoisson
|
||||
import numpy as np
|
||||
import pysal
|
||||
import unittest
|
||||
import math
|
||||
|
||||
|
||||
class TestGaussian(unittest.TestCase):
|
||||
"""
|
||||
Tests for Poisson GLM
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
db = pysal.open(pysal.examples.get_path('columbus.dbf'),'r')
|
||||
y = np.array(db.by_col("HOVAL"))
|
||||
self.y = np.reshape(y, (49,1))
|
||||
X = []
|
||||
X.append(db.by_col("INC"))
|
||||
X.append(db.by_col("CRIME"))
|
||||
self.X = np.array(X).T
|
||||
|
||||
def testIWLS(self):
|
||||
model = GLM(self.y, self.X, family=Gaussian())
|
||||
results = model.fit()
|
||||
self.assertEqual(results.n, 49)
|
||||
self.assertEqual(results.df_model, 2)
|
||||
self.assertEqual(results.df_resid, 46)
|
||||
self.assertEqual(results.aic, 408.73548964604873)
|
||||
self.assertEqual(results.bic, 10467.991340493107)
|
||||
self.assertEqual(results.deviance, 10647.015074206196)
|
||||
self.assertEqual(results.llf, -201.36774482302437)
|
||||
self.assertEqual(results.null_deviance, 16367.794631703124)
|
||||
self.assertEqual(results.scale, 231.45684943926514)
|
||||
np.testing.assert_allclose(results.params, [ 46.42818268, 0.62898397,
|
||||
-0.48488854])
|
||||
np.testing.assert_allclose(results.bse, [ 13.19175703, 0.53591045,
|
||||
0.18267291])
|
||||
np.testing.assert_allclose(results.cov_params(),
|
||||
[[ 1.74022453e+02, -6.52060364e+00, -2.15109867e+00],
|
||||
[ -6.52060364e+00, 2.87200008e-01, 6.80956787e-02],
|
||||
[ -2.15109867e+00, 6.80956787e-02, 3.33693910e-02]])
|
||||
np.testing.assert_allclose(results.tvalues, [ 3.51948437, 1.17367365,
|
||||
-2.65440864])
|
||||
np.testing.assert_allclose(results.pvalues, [ 0.00043239, 0.24052577,
|
||||
0.00794475], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.conf_int(),
|
||||
[[ 20.57281401, 72.28355135],
|
||||
[ -0.42138121, 1.67934915],
|
||||
[ -0.84292086, -0.12685622]])
|
||||
np.testing.assert_allclose(results.normalized_cov_params,
|
||||
[[ 7.51857004e-01, -2.81720055e-02, -9.29373521e-03],
|
||||
[ -2.81720055e-02, 1.24083607e-03, 2.94204638e-04],
|
||||
[ -9.29373521e-03, 2.94204638e-04, 1.44171110e-04]])
|
||||
np.testing.assert_allclose(results.mu,
|
||||
[ 51.08752105, 50.66601521, 41.61367567, 33.53969014,
|
||||
28.90638232, 43.87074227, 51.64910882, 34.92671563,
|
||||
42.69267622, 38.49449134, 20.92815471, 25.25228436,
|
||||
29.78223486, 25.02403635, 29.07959539, 24.63352275,
|
||||
34.71372149, 33.40443052, 27.29864225, 65.86219802,
|
||||
33.69854751, 37.44976435, 50.01304928, 36.81219959,
|
||||
22.02674837, 31.64775955, 27.63563294, 23.7697291 ,
|
||||
22.43119725, 21.76987089, 48.51169321, 49.05891819,
|
||||
32.31656426, 44.20550354, 35.49244888, 51.27811308,
|
||||
36.55047181, 27.37048914, 48.78812922, 57.31744163,
|
||||
51.22914162, 54.70515578, 37.06622277, 44.5075759 ,
|
||||
41.24328983, 49.93821824, 44.85644299, 40.93838609, 47.32045464])
|
||||
self.assertEqual(results.pearson_chi2, 10647.015074206196)
|
||||
np.testing.assert_allclose(results.resid_response,
|
||||
[ 29.37948195, -6.09901421, -15.26367567, -0.33968914,
|
||||
-5.68138232, -15.12074227, 23.35089118, 2.19828437,
|
||||
9.90732178, 57.90551066, -1.22815371, -5.35228436,
|
||||
11.91776614, 17.87596565, -11.07959539, -5.83352375,
|
||||
7.03627851, 26.59556948, 3.30135775, 15.40479998,
|
||||
-13.72354751, -6.99976335, -2.28004728, 16.38780141,
|
||||
-4.12674837, -11.34776055, 6.46436506, -0.9197291 ,
|
||||
10.06880275, 0.73012911, -16.71169421, -8.75891919,
|
||||
-8.71656426, -15.75550254, -8.49244888, -14.97811408,
|
||||
6.74952719, -4.67048814, -9.18813122, 4.63255937,
|
||||
-9.12914362, -10.37215578, -11.36622177, -11.0075759 ,
|
||||
-13.51028983, 26.16177976, -2.35644299, -14.13838709, -11.52045564])
|
||||
np.testing.assert_allclose(results.resid_working,
|
||||
[ 29.37948195, -6.09901421, -15.26367567, -0.33968914,
|
||||
-5.68138232, -15.12074227, 23.35089118, 2.19828437,
|
||||
9.90732178, 57.90551066, -1.22815371, -5.35228436,
|
||||
11.91776614, 17.87596565, -11.07959539, -5.83352375,
|
||||
7.03627851, 26.59556948, 3.30135775, 15.40479998,
|
||||
-13.72354751, -6.99976335, -2.28004728, 16.38780141,
|
||||
-4.12674837, -11.34776055, 6.46436506, -0.9197291 ,
|
||||
10.06880275, 0.73012911, -16.71169421, -8.75891919,
|
||||
-8.71656426, -15.75550254, -8.49244888, -14.97811408,
|
||||
6.74952719, -4.67048814, -9.18813122, 4.63255937,
|
||||
-9.12914362, -10.37215578, -11.36622177, -11.0075759 ,
|
||||
-13.51028983, 26.16177976, -2.35644299, -14.13838709, -11.52045564])
|
||||
np.testing.assert_allclose(results.resid_pearson,
|
||||
[ 29.37948195, -6.09901421, -15.26367567, -0.33968914,
|
||||
-5.68138232, -15.12074227, 23.35089118, 2.19828437,
|
||||
9.90732178, 57.90551066, -1.22815371, -5.35228436,
|
||||
11.91776614, 17.87596565, -11.07959539, -5.83352375,
|
||||
7.03627851, 26.59556948, 3.30135775, 15.40479998,
|
||||
-13.72354751, -6.99976335, -2.28004728, 16.38780141,
|
||||
-4.12674837, -11.34776055, 6.46436506, -0.9197291 ,
|
||||
10.06880275, 0.73012911, -16.71169421, -8.75891919,
|
||||
-8.71656426, -15.75550254, -8.49244888, -14.97811408,
|
||||
6.74952719, -4.67048814, -9.18813122, 4.63255937,
|
||||
-9.12914362, -10.37215578, -11.36622177, -11.0075759 ,
|
||||
-13.51028983, 26.16177976, -2.35644299, -14.13838709, -11.52045564])
|
||||
np.testing.assert_allclose(results.resid_anscombe,
|
||||
[ 29.37948195, -6.09901421, -15.26367567, -0.33968914,
|
||||
-5.68138232, -15.12074227, 23.35089118, 2.19828437,
|
||||
9.90732178, 57.90551066, -1.22815371, -5.35228436,
|
||||
11.91776614, 17.87596565, -11.07959539, -5.83352375,
|
||||
7.03627851, 26.59556948, 3.30135775, 15.40479998,
|
||||
-13.72354751, -6.99976335, -2.28004728, 16.38780141,
|
||||
-4.12674837, -11.34776055, 6.46436506, -0.9197291 ,
|
||||
10.06880275, 0.73012911, -16.71169421, -8.75891919,
|
||||
-8.71656426, -15.75550254, -8.49244888, -14.97811408,
|
||||
6.74952719, -4.67048814, -9.18813122, 4.63255937,
|
||||
-9.12914362, -10.37215578, -11.36622177, -11.0075759 ,
|
||||
-13.51028983, 26.16177976, -2.35644299, -14.13838709, -11.52045564])
|
||||
np.testing.assert_allclose(results.resid_deviance,
|
||||
[ 29.37948195, -6.09901421, -15.26367567, -0.33968914,
|
||||
-5.68138232, -15.12074227, 23.35089118, 2.19828437,
|
||||
9.90732178, 57.90551066, -1.22815371, -5.35228436,
|
||||
11.91776614, 17.87596565, -11.07959539, -5.83352375,
|
||||
7.03627851, 26.59556948, 3.30135775, 15.40479998,
|
||||
-13.72354751, -6.99976335, -2.28004728, 16.38780141,
|
||||
-4.12674837, -11.34776055, 6.46436506, -0.9197291 ,
|
||||
10.06880275, 0.73012911, -16.71169421, -8.75891919,
|
||||
-8.71656426, -15.75550254, -8.49244888, -14.97811408,
|
||||
6.74952719, -4.67048814, -9.18813122, 4.63255937,
|
||||
-9.12914362, -10.37215578, -11.36622177, -11.0075759 ,
|
||||
-13.51028983, 26.16177976, -2.35644299, -14.13838709, -11.52045564])
|
||||
np.testing.assert_allclose(results.null,
|
||||
[ 38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447,
|
||||
38.43622447, 38.43622447, 38.43622447, 38.43622447, 38.43622447])
|
||||
self.assertAlmostEqual(results.D2, .349514377851)
|
||||
self.assertAlmostEqual(results.adj_D2, 0.32123239427957673)
|
||||
|
||||
class TestPoisson(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
db = pysal.open(pysal.examples.get_path('columbus.dbf'),'r')
|
||||
y = np.array(db.by_col("HOVAL"))
|
||||
y = np.reshape(y, (49,1))
|
||||
self.y = np.round(y).astype(int)
|
||||
X = []
|
||||
X.append(db.by_col("INC"))
|
||||
X.append(db.by_col("CRIME"))
|
||||
self.X = np.array(X).T
|
||||
|
||||
def testIWLS(self):
|
||||
model = GLM(self.y, self.X, family=Poisson())
|
||||
results = model.fit()
|
||||
self.assertEqual(results.n, 49)
|
||||
self.assertEqual(results.df_model, 2)
|
||||
self.assertEqual(results.df_resid, 46)
|
||||
self.assertAlmostEqual(results.aic, 500.85184179938756)
|
||||
self.assertAlmostEqual(results.bic, 51.436404535087661)
|
||||
self.assertAlmostEqual(results.deviance, 230.46013824817649)
|
||||
self.assertAlmostEqual(results.llf, -247.42592089969378)
|
||||
self.assertAlmostEqual(results.null_deviance, 376.97293610347361)
|
||||
self.assertEqual(results.scale, 1.0)
|
||||
np.testing.assert_allclose(results.params, [ 3.92159085, 0.01183491,
|
||||
-0.01371397], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.bse, [ 0.13049161, 0.00511599,
|
||||
0.00193769], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.cov_params(),
|
||||
[[ 1.70280610e-02, -6.18628383e-04, -2.21386966e-04],
|
||||
[ -6.18628383e-04, 2.61733917e-05, 6.77496445e-06],
|
||||
[ -2.21386966e-04, 6.77496445e-06, 3.75463502e-06]])
|
||||
np.testing.assert_allclose(results.tvalues, [ 30.0524361 , 2.31331634,
|
||||
-7.07748998])
|
||||
np.testing.assert_allclose(results.pvalues, [ 2.02901657e-198,
|
||||
2.07052532e-002, 1.46788805e-012])
|
||||
np.testing.assert_allclose(results.conf_int(),
|
||||
[[ 3.66583199e+00, 4.17734972e+00],
|
||||
[ 1.80774841e-03, 2.18620753e-02],
|
||||
[ -1.75117666e-02, -9.91616901e-03]])
|
||||
np.testing.assert_allclose(results.normalized_cov_params,
|
||||
[[ 1.70280610e-02, -6.18628383e-04, -2.21386966e-04],
|
||||
[ -6.18628383e-04, 2.61733917e-05, 6.77496445e-06],
|
||||
[ -2.21386966e-04, 6.77496445e-06, 3.75463502e-06]])
|
||||
np.testing.assert_allclose(results.mu,
|
||||
[ 51.26831574, 50.15022766, 40.06142973, 34.13799739,
|
||||
28.76119226, 42.6836241 , 55.64593703, 34.08277997,
|
||||
40.90389582, 37.19727958, 23.47459217, 26.12384057,
|
||||
29.78303507, 25.96888223, 29.14073823, 26.04369592,
|
||||
34.18996367, 32.28924005, 27.42284396, 72.69207879,
|
||||
33.05316347, 36.52276972, 49.2551479 , 35.33439632,
|
||||
24.07252457, 31.67153709, 27.81699478, 25.38021219,
|
||||
24.31759259, 23.13586161, 48.40724678, 48.57969818,
|
||||
31.92596006, 43.3679231 , 34.32925819, 51.78908089,
|
||||
34.49778584, 27.56236198, 48.34273194, 57.50829097,
|
||||
50.66038226, 54.68701352, 35.77103116, 43.21886784,
|
||||
40.07615759, 49.98658004, 43.13352883, 40.28520774, 46.28910294])
|
||||
self.assertAlmostEqual(results.pearson_chi2, 264.62262932090221)
|
||||
np.testing.assert_allclose(results.resid_response,
|
||||
[ 28.73168426, -5.15022766, -14.06142973, -1.13799739,
|
||||
-5.76119226, -13.6836241 , 19.35406297, 2.91722003,
|
||||
12.09610418, 58.80272042, -3.47459217, -6.12384057,
|
||||
12.21696493, 17.03111777, -11.14073823, -7.04369592,
|
||||
7.81003633, 27.71075995, 3.57715604, 8.30792121,
|
||||
-13.05316347, -6.52276972, -1.2551479 , 17.66560368,
|
||||
-6.07252457, -11.67153709, 6.18300522, -2.38021219,
|
||||
7.68240741, -1.13586161, -16.40724678, -8.57969818,
|
||||
-7.92596006, -15.3679231 , -7.32925819, -15.78908089,
|
||||
8.50221416, -4.56236198, -8.34273194, 4.49170903,
|
||||
-8.66038226, -10.68701352, -9.77103116, -9.21886784,
|
||||
-12.07615759, 26.01341996, -1.13352883, -13.28520774, -10.28910294])
|
||||
np.testing.assert_allclose(results.resid_working,
|
||||
[ 1473.02506034, -258.28508941, -563.32097891, -38.84895192,
|
||||
-165.69875817, -584.06666725, 1076.97496919, 99.42696848,
|
||||
494.77778514, 2187.30123163, -81.56463405, -159.97823479,
|
||||
363.858295 , 442.27909165, -324.64933645, -183.44387481,
|
||||
267.02485844, 894.75938 , 98.09579187, 603.9200634 ,
|
||||
-431.44834594, -238.2296165 , -61.82249568, 624.20344168,
|
||||
-146.18099686, -369.65551968, 171.99262399, -60.41029031,
|
||||
186.81765356, -26.27913713, -794.22964417, -416.79914795,
|
||||
-253.04388425, -666.47490701, -251.6079969 , -817.70198717,
|
||||
293.30756327, -125.74947222, -403.31045369, 258.31051005,
|
||||
-438.73827602, -584.440853 , -349.51985996, -398.42903071,
|
||||
-483.96599444, 1300.32189904, -48.89309853, -535.19735391,
|
||||
-476.27334527])
|
||||
np.testing.assert_allclose(results.resid_pearson,
|
||||
[ 4.01269878, -0.72726045, -2.221602 , -0.19477008, -1.07425881,
|
||||
-2.09445239, 2.59451042, 0.49969118, 1.89131202, 9.64143836,
|
||||
-0.71714142, -1.19813392, 2.23861212, 3.34207756, -2.0637814 ,
|
||||
-1.3802231 , 1.33568403, 4.87662684, 0.68309584, 0.97442591,
|
||||
-2.27043598, -1.07931992, -0.17884182, 2.97186889, -1.23768025,
|
||||
-2.07392709, 1.1723155 , -0.47246327, 1.55789092, -0.23614708,
|
||||
-2.35819937, -1.23096188, -1.40274877, -2.33362391, -1.25091503,
|
||||
-2.19400568, 1.44755952, -0.8690235 , -1.19989348, 0.59230634,
|
||||
-1.21675413, -1.44515442, -1.63370888, -1.40229988, -1.90759306,
|
||||
3.67934693, -0.17259375, -2.09312684, -1.51230062])
|
||||
np.testing.assert_allclose(results.resid_anscombe,
|
||||
[ 3.70889134, -0.74031295, -2.37729865, -0.19586855, -1.11374751,
|
||||
-2.22611959, 2.46352013, 0.49282126, 1.80857757, 8.06444452,
|
||||
-0.73610811, -1.25061371, 2.10820431, 3.05467547, -2.22437611,
|
||||
-1.45136173, 1.28939698, 4.35942058, 0.66904552, 0.95674923,
|
||||
-2.45438937, -1.11429881, -0.17961012, 2.76715848, -1.29658591,
|
||||
-2.22816691, 1.13269136, -0.48017382, 1.48562248, -0.23812278,
|
||||
-2.51664399, -1.2703721 , -1.4683091 , -2.49907536, -1.30026484,
|
||||
-2.32398309, 1.39380683, -0.89495368, -1.23735395, 0.58485202,
|
||||
-1.25435224, -1.4968484 , -1.71888038, -1.45756652, -2.01906267,
|
||||
3.41729922, -0.17335867, -2.22921828, -1.57470549])
|
||||
np.testing.assert_allclose(results.resid_deviance,
|
||||
[ 3.70529668, -0.74027329, -2.37536322, -0.19586751, -1.11349765,
|
||||
-2.22466106, 2.46246446, 0.4928057 , 1.80799655, 8.02696525,
|
||||
-0.73602255, -1.25021555, 2.10699958, 3.05084608, -2.22214376,
|
||||
-1.45072221, 1.28913747, 4.35106213, 0.6689982 , 0.95669662,
|
||||
-2.45171913, -1.11410444, -0.17960956, 2.76494217, -1.29609865,
|
||||
-2.22612429, 1.13247453, -0.48015254, 1.48508549, -0.23812 ,
|
||||
-2.51476072, -1.27015583, -1.46777697, -2.49699318, -1.29992892,
|
||||
-2.32263069, 1.39348459, -0.89482132, -1.23715363, 0.58483655,
|
||||
-1.25415329, -1.49653039, -1.7181055 , -1.45719072, -2.01791949,
|
||||
3.41437156, -0.1733581 , -2.22765605, -1.57426046])
|
||||
np.testing.assert_allclose(results.null,
|
||||
[ 38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143, 38.42857143])
|
||||
self.assertAlmostEqual(results.D2, .388656011675)
|
||||
self.assertAlmostEqual(results.adj_D2, 0.36207583826952761)#.375648692774)
|
||||
|
||||
def testQuasi(self):
|
||||
model = GLM(self.y, self.X, family=QuasiPoisson())
|
||||
results = model.fit()
|
||||
self.assertEqual(results.n, 49)
|
||||
self.assertEqual(results.df_model, 2)
|
||||
self.assertEqual(results.df_resid, 46)
|
||||
self.assertTrue(math.isnan(results.aic))
|
||||
self.assertAlmostEqual(results.bic, 51.436404535087661)
|
||||
self.assertAlmostEqual(results.deviance, 230.46013824817649)
|
||||
self.assertTrue(math.isnan(results.llf))
|
||||
self.assertAlmostEqual(results.null_deviance, 376.97293610347361)
|
||||
self.assertAlmostEqual(results.scale, 5.7526658548022223)
|
||||
np.testing.assert_allclose(results.params, [ 3.92159085, 0.01183491,
|
||||
-0.01371397], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.bse, [ 0.31298042, 0.01227057,
|
||||
0.00464749], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.cov_params(),
|
||||
[[ 9.79567451e-02, -3.55876238e-03, -1.27356524e-03],
|
||||
[ -3.55876238e-03, 1.50566777e-04, 3.89741067e-05],
|
||||
[ -1.27356524e-03, 3.89741067e-05, 2.15991606e-05]])
|
||||
np.testing.assert_allclose(results.tvalues, [ 12.52982796, 0.96449604,
|
||||
-2.95083339])
|
||||
np.testing.assert_allclose(results.pvalues, [ 5.12737770e-36,
|
||||
3.34797291e-01, 3.16917819e-03])
|
||||
np.testing.assert_allclose(results.conf_int(),
|
||||
[[ 3.3081605 , 4.53502121],
|
||||
[-0.01221495, 0.03588478],
|
||||
[-0.02282288, -0.00460506]], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.normalized_cov_params,
|
||||
[[ 1.70280610e-02, -6.18628383e-04, -2.21386966e-04],
|
||||
[ -6.18628383e-04, 2.61733917e-05, 6.77496445e-06],
|
||||
[ -2.21386966e-04, 6.77496445e-06, 3.75463502e-06]])
|
||||
np.testing.assert_allclose(results.mu,
|
||||
[ 51.26831574, 50.15022766, 40.06142973, 34.13799739,
|
||||
28.76119226, 42.6836241 , 55.64593703, 34.08277997,
|
||||
40.90389582, 37.19727958, 23.47459217, 26.12384057,
|
||||
29.78303507, 25.96888223, 29.14073823, 26.04369592,
|
||||
34.18996367, 32.28924005, 27.42284396, 72.69207879,
|
||||
33.05316347, 36.52276972, 49.2551479 , 35.33439632,
|
||||
24.07252457, 31.67153709, 27.81699478, 25.38021219,
|
||||
24.31759259, 23.13586161, 48.40724678, 48.57969818,
|
||||
31.92596006, 43.3679231 , 34.32925819, 51.78908089,
|
||||
34.49778584, 27.56236198, 48.34273194, 57.50829097,
|
||||
50.66038226, 54.68701352, 35.77103116, 43.21886784,
|
||||
40.07615759, 49.98658004, 43.13352883, 40.28520774, 46.28910294])
|
||||
self.assertAlmostEqual(results.pearson_chi2, 264.62262932090221)
|
||||
np.testing.assert_allclose(results.resid_response,
|
||||
[ 28.73168426, -5.15022766, -14.06142973, -1.13799739,
|
||||
-5.76119226, -13.6836241 , 19.35406297, 2.91722003,
|
||||
12.09610418, 58.80272042, -3.47459217, -6.12384057,
|
||||
12.21696493, 17.03111777, -11.14073823, -7.04369592,
|
||||
7.81003633, 27.71075995, 3.57715604, 8.30792121,
|
||||
-13.05316347, -6.52276972, -1.2551479 , 17.66560368,
|
||||
-6.07252457, -11.67153709, 6.18300522, -2.38021219,
|
||||
7.68240741, -1.13586161, -16.40724678, -8.57969818,
|
||||
-7.92596006, -15.3679231 , -7.32925819, -15.78908089,
|
||||
8.50221416, -4.56236198, -8.34273194, 4.49170903,
|
||||
-8.66038226, -10.68701352, -9.77103116, -9.21886784,
|
||||
-12.07615759, 26.01341996, -1.13352883, -13.28520774, -10.28910294])
|
||||
np.testing.assert_allclose(results.resid_working,
|
||||
[ 1473.02506034, -258.28508941, -563.32097891, -38.84895192,
|
||||
-165.69875817, -584.06666725, 1076.97496919, 99.42696848,
|
||||
494.77778514, 2187.30123163, -81.56463405, -159.97823479,
|
||||
363.858295 , 442.27909165, -324.64933645, -183.44387481,
|
||||
267.02485844, 894.75938 , 98.09579187, 603.9200634 ,
|
||||
-431.44834594, -238.2296165 , -61.82249568, 624.20344168,
|
||||
-146.18099686, -369.65551968, 171.99262399, -60.41029031,
|
||||
186.81765356, -26.27913713, -794.22964417, -416.79914795,
|
||||
-253.04388425, -666.47490701, -251.6079969 , -817.70198717,
|
||||
293.30756327, -125.74947222, -403.31045369, 258.31051005,
|
||||
-438.73827602, -584.440853 , -349.51985996, -398.42903071,
|
||||
-483.96599444, 1300.32189904, -48.89309853, -535.19735391,
|
||||
-476.27334527])
|
||||
np.testing.assert_allclose(results.resid_pearson,
|
||||
[ 4.01269878, -0.72726045, -2.221602 , -0.19477008, -1.07425881,
|
||||
-2.09445239, 2.59451042, 0.49969118, 1.89131202, 9.64143836,
|
||||
-0.71714142, -1.19813392, 2.23861212, 3.34207756, -2.0637814 ,
|
||||
-1.3802231 , 1.33568403, 4.87662684, 0.68309584, 0.97442591,
|
||||
-2.27043598, -1.07931992, -0.17884182, 2.97186889, -1.23768025,
|
||||
-2.07392709, 1.1723155 , -0.47246327, 1.55789092, -0.23614708,
|
||||
-2.35819937, -1.23096188, -1.40274877, -2.33362391, -1.25091503,
|
||||
-2.19400568, 1.44755952, -0.8690235 , -1.19989348, 0.59230634,
|
||||
-1.21675413, -1.44515442, -1.63370888, -1.40229988, -1.90759306,
|
||||
3.67934693, -0.17259375, -2.09312684, -1.51230062])
|
||||
np.testing.assert_allclose(results.resid_anscombe,
|
||||
[ 3.70889134, -0.74031295, -2.37729865, -0.19586855, -1.11374751,
|
||||
-2.22611959, 2.46352013, 0.49282126, 1.80857757, 8.06444452,
|
||||
-0.73610811, -1.25061371, 2.10820431, 3.05467547, -2.22437611,
|
||||
-1.45136173, 1.28939698, 4.35942058, 0.66904552, 0.95674923,
|
||||
-2.45438937, -1.11429881, -0.17961012, 2.76715848, -1.29658591,
|
||||
-2.22816691, 1.13269136, -0.48017382, 1.48562248, -0.23812278,
|
||||
-2.51664399, -1.2703721 , -1.4683091 , -2.49907536, -1.30026484,
|
||||
-2.32398309, 1.39380683, -0.89495368, -1.23735395, 0.58485202,
|
||||
-1.25435224, -1.4968484 , -1.71888038, -1.45756652, -2.01906267,
|
||||
3.41729922, -0.17335867, -2.22921828, -1.57470549])
|
||||
np.testing.assert_allclose(results.resid_deviance,
|
||||
[ 3.70529668, -0.74027329, -2.37536322, -0.19586751, -1.11349765,
|
||||
-2.22466106, 2.46246446, 0.4928057 , 1.80799655, 8.02696525,
|
||||
-0.73602255, -1.25021555, 2.10699958, 3.05084608, -2.22214376,
|
||||
-1.45072221, 1.28913747, 4.35106213, 0.6689982 , 0.95669662,
|
||||
-2.45171913, -1.11410444, -0.17960956, 2.76494217, -1.29609865,
|
||||
-2.22612429, 1.13247453, -0.48015254, 1.48508549, -0.23812 ,
|
||||
-2.51476072, -1.27015583, -1.46777697, -2.49699318, -1.29992892,
|
||||
-2.32263069, 1.39348459, -0.89482132, -1.23715363, 0.58483655,
|
||||
-1.25415329, -1.49653039, -1.7181055 , -1.45719072, -2.01791949,
|
||||
3.41437156, -0.1733581 , -2.22765605, -1.57426046])
|
||||
np.testing.assert_allclose(results.null,
|
||||
[ 38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143,
|
||||
38.42857143, 38.42857143, 38.42857143, 38.42857143, 38.42857143])
|
||||
self.assertAlmostEqual(results.D2, .388656011675)
|
||||
self.assertAlmostEqual(results.adj_D2, 0.36207583826952761)
|
||||
|
||||
class TestBinomial(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
#London house price data
|
||||
#y: 'BATH2'
|
||||
y = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
self.y = y.reshape((316,1))
|
||||
#X: 'FLOORSZ'
|
||||
X = np.array([ 77, 75, 64, 95, 107, 100, 81, 151, 98, 260, 171, 161, 91,
|
||||
80, 50, 85, 52, 69, 60, 84, 155, 97, 69, 126, 90, 43,
|
||||
51, 41, 140, 80, 52, 86, 66, 60, 40, 155, 138, 97, 115,
|
||||
148, 206, 60, 53, 96, 88, 160, 31, 43, 154, 60, 131, 60,
|
||||
46, 61, 125, 150, 76, 92, 96, 100, 105, 72, 48, 41, 72,
|
||||
65, 60, 65, 98, 33, 144, 111, 91, 108, 38, 48, 95, 63,
|
||||
98, 129, 108, 51, 131, 66, 48, 127, 76, 68, 52, 64, 57,
|
||||
121, 67, 76, 112, 96, 90, 53, 93, 64, 97, 58, 44, 157,
|
||||
53, 70, 71, 167, 47, 70, 96, 77, 75, 71, 67, 47, 71,
|
||||
90, 69, 64, 65, 95, 60, 60, 65, 54, 121, 105, 50, 85,
|
||||
69, 69, 62, 65, 93, 93, 70, 62, 155, 68, 117, 80, 80,
|
||||
75, 98, 114, 86, 70, 50, 51, 163, 124, 59, 95, 51, 63,
|
||||
85, 53, 46, 102, 114, 83, 47, 40, 63, 123, 100, 63, 110,
|
||||
79, 98, 99, 120, 52, 48, 37, 81, 30, 88, 50, 35, 116,
|
||||
67, 45, 80, 86, 109, 59, 75, 60, 71, 141, 121, 50, 168,
|
||||
90, 51, 133, 75, 133, 127, 37, 68, 105, 61, 123, 151, 110,
|
||||
77, 220, 94, 77, 70, 100, 98, 126, 55, 105, 60, 176, 104,
|
||||
68, 62, 70, 48, 102, 80, 97, 66, 80, 102, 160, 55, 60,
|
||||
71, 125, 85, 85, 190, 137, 48, 41, 42, 51, 57, 60, 114,
|
||||
88, 84, 108, 66, 85, 42, 98, 90, 127, 100, 55, 76, 82,
|
||||
63, 80, 71, 76, 121, 109, 92, 160, 109, 185, 100, 90, 90,
|
||||
86, 88, 95, 116, 135, 61, 74, 60, 235, 76, 66, 100, 49,
|
||||
50, 37, 100, 88, 90, 52, 95, 81, 79, 96, 75, 91, 86,
|
||||
83, 180, 108, 80, 96, 49, 117, 117, 86, 46, 66, 95, 57,
|
||||
120, 137, 68, 240])
|
||||
self.X = X.reshape((316,1))
|
||||
|
||||
def testIWLS(self):
|
||||
model = GLM(self.y, self.X, family=Binomial())
|
||||
results = model.fit()
|
||||
self.assertEqual(results.n, 316)
|
||||
self.assertEqual(results.df_model, 1)
|
||||
self.assertEqual(results.df_resid, 314)
|
||||
self.assertEqual(results.aic, 155.19347530342466)
|
||||
self.assertEqual(results.bic, -1656.1095797628657)
|
||||
self.assertEqual(results.deviance, 151.19347530342466)
|
||||
self.assertEqual(results.llf, -75.596737651712331)
|
||||
self.assertEqual(results.null_deviance, 189.16038985881212)
|
||||
self.assertEqual(results.scale, 1.0)
|
||||
np.testing.assert_allclose(results.params, [-5.33638276, 0.0287754 ])
|
||||
np.testing.assert_allclose(results.bse, [ 0.64499904, 0.00518312],
|
||||
atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.cov_params(),
|
||||
[[ 4.16023762e-01, -3.14338457e-03],
|
||||
[ -3.14338457e-03, 2.68646833e-05]])
|
||||
np.testing.assert_allclose(results.tvalues, [-8.27347396, 5.55175826])
|
||||
np.testing.assert_allclose(results.pvalues, [ 1.30111233e-16,
|
||||
2.82810512e-08])
|
||||
np.testing.assert_allclose(results.conf_int(),
|
||||
[[-6.60055765, -4.07220787],
|
||||
[ 0.01861668, 0.03893412]], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.normalized_cov_params,
|
||||
[[ 4.16023762e-01, -3.14338457e-03],
|
||||
[ -3.14338457e-03, 2.68646833e-05]])
|
||||
np.testing.assert_allclose(results.mu,
|
||||
[ 0.04226237, 0.03999333, 0.02946178, 0.0689636 , 0.09471181,
|
||||
0.07879431, 0.04717464, 0.27065598, 0.07471691, 0.89522144,
|
||||
0.39752487, 0.33102718, 0.06192993, 0.04589793, 0.01988679,
|
||||
0.0526265 , 0.02104007, 0.03386636, 0.02634295, 0.05121018,
|
||||
0.29396682, 0.07275173, 0.03386636, 0.15307528, 0.06027915,
|
||||
0.01631789, 0.02045547, 0.01541937, 0.2128508 , 0.04589793,
|
||||
0.02104007, 0.05407977, 0.0311527 , 0.02634295, 0.01498855,
|
||||
0.29396682, 0.20336776, 0.07275173, 0.11637537, 0.25395607,
|
||||
0.64367488, 0.02634295, 0.02164101, 0.07083428, 0.05710047,
|
||||
0.32468619, 0.01160845, 0.01631789, 0.28803008, 0.02634295,
|
||||
0.17267234, 0.02634295, 0.01776301, 0.02709115, 0.14938186,
|
||||
0.26501331, 0.04111287, 0.06362285, 0.07083428, 0.07879431,
|
||||
0.08989109, 0.03680743, 0.0187955 , 0.01541937, 0.03680743,
|
||||
0.03029581, 0.02634295, 0.03029581, 0.07471691, 0.01228768,
|
||||
0.23277197, 0.10505173, 0.06192993, 0.09720799, 0.01416217,
|
||||
0.0187955 , 0.0689636 , 0.02865003, 0.07471691, 0.16460503,
|
||||
0.09720799, 0.02045547, 0.17267234, 0.0311527 , 0.0187955 ,
|
||||
0.15684317, 0.04111287, 0.03293737, 0.02104007, 0.02946178,
|
||||
0.02421701, 0.1353385 , 0.03203302, 0.04111287, 0.10778798,
|
||||
0.07083428, 0.06027915, 0.02164101, 0.06535882, 0.02946178,
|
||||
0.07275173, 0.02490638, 0.01678627, 0.30605146, 0.02164101,
|
||||
0.03482061, 0.03580075, 0.37030921, 0.0182721 , 0.03482061,
|
||||
0.07083428, 0.04226237, 0.03999333, 0.03580075, 0.03203302,
|
||||
0.0182721 , 0.03580075, 0.06027915, 0.03386636, 0.02946178,
|
||||
0.03029581, 0.0689636 , 0.02634295, 0.02634295, 0.03029581,
|
||||
0.02225873, 0.1353385 , 0.08989109, 0.01988679, 0.0526265 ,
|
||||
0.03386636, 0.03386636, 0.02786 , 0.03029581, 0.06535882,
|
||||
0.06535882, 0.03482061, 0.02786 , 0.29396682, 0.03293737,
|
||||
0.12242534, 0.04589793, 0.04589793, 0.03999333, 0.07471691,
|
||||
0.11344884, 0.05407977, 0.03482061, 0.01988679, 0.02045547,
|
||||
0.34389327, 0.14576223, 0.02561486, 0.0689636 , 0.02045547,
|
||||
0.02865003, 0.0526265 , 0.02164101, 0.01776301, 0.08307425,
|
||||
0.11344884, 0.04982997, 0.0182721 , 0.01498855, 0.02865003,
|
||||
0.14221564, 0.07879431, 0.02865003, 0.10237696, 0.04465416,
|
||||
0.07471691, 0.07673078, 0.13200634, 0.02104007, 0.0187955 ,
|
||||
0.01376599, 0.04717464, 0.01128289, 0.05710047, 0.01988679,
|
||||
0.01300612, 0.11936722, 0.03203302, 0.01726786, 0.04589793,
|
||||
0.05407977, 0.09976271, 0.02561486, 0.03999333, 0.02634295,
|
||||
0.03580075, 0.21771181, 0.1353385 , 0.01988679, 0.37704374,
|
||||
0.06027915, 0.02045547, 0.18104935, 0.03999333, 0.18104935,
|
||||
0.15684317, 0.01376599, 0.03293737, 0.08989109, 0.02709115,
|
||||
0.14221564, 0.27065598, 0.10237696, 0.04226237, 0.72991785,
|
||||
0.06713876, 0.04226237, 0.03482061, 0.07879431, 0.07471691,
|
||||
0.15307528, 0.02289366, 0.08989109, 0.02634295, 0.43243779,
|
||||
0.08756457, 0.03293737, 0.02786 , 0.03482061, 0.0187955 ,
|
||||
0.08307425, 0.04589793, 0.07275173, 0.0311527 , 0.04589793,
|
||||
0.08307425, 0.32468619, 0.02289366, 0.02634295, 0.03580075,
|
||||
0.14938186, 0.0526265 , 0.0526265 , 0.53268924, 0.19874565,
|
||||
0.0187955 , 0.01541937, 0.01586237, 0.02045547, 0.02421701,
|
||||
0.02634295, 0.11344884, 0.05710047, 0.05121018, 0.09720799,
|
||||
0.0311527 , 0.0526265 , 0.01586237, 0.07471691, 0.06027915,
|
||||
0.15684317, 0.07879431, 0.02289366, 0.04111287, 0.04848506,
|
||||
0.02865003, 0.04589793, 0.03580075, 0.04111287, 0.1353385 ,
|
||||
0.09976271, 0.06362285, 0.32468619, 0.09976271, 0.49676673,
|
||||
0.07879431, 0.06027915, 0.06027915, 0.05407977, 0.05710047,
|
||||
0.0689636 , 0.11936722, 0.18973955, 0.02709115, 0.03890304,
|
||||
0.02634295, 0.80625182, 0.04111287, 0.0311527 , 0.07879431,
|
||||
0.0193336 , 0.01988679, 0.01376599, 0.07879431, 0.05710047,
|
||||
0.06027915, 0.02104007, 0.0689636 , 0.04717464, 0.04465416,
|
||||
0.07083428, 0.03999333, 0.06192993, 0.05407977, 0.04982997,
|
||||
0.46087756, 0.09720799, 0.04589793, 0.07083428, 0.0193336 ,
|
||||
0.12242534, 0.12242534, 0.05407977, 0.01776301, 0.0311527 ,
|
||||
0.0689636 , 0.02421701, 0.13200634, 0.19874565, 0.03293737,
|
||||
0.82774282], atol=1.0e-8)
|
||||
self.assertAlmostEqual(results.pearson_chi2, 271.21110541713801)
|
||||
np.testing.assert_allclose(results.resid_response,
|
||||
[-0.04226237, -0.03999333, -0.02946178, -0.0689636 , -0.09471181,
|
||||
-0.07879431, -0.04717464, -0.27065598, -0.07471691, 0.10477856,
|
||||
-0.39752487, 0.66897282, -0.06192993, -0.04589793, -0.01988679,
|
||||
-0.0526265 , -0.02104007, -0.03386636, -0.02634295, -0.05121018,
|
||||
-0.29396682, 0.92724827, -0.03386636, -0.15307528, -0.06027915,
|
||||
-0.01631789, -0.02045547, -0.01541937, -0.2128508 , -0.04589793,
|
||||
-0.02104007, -0.05407977, -0.0311527 , -0.02634295, -0.01498855,
|
||||
-0.29396682, 0.79663224, -0.07275173, -0.11637537, 0.74604393,
|
||||
-0.64367488, -0.02634295, -0.02164101, -0.07083428, -0.05710047,
|
||||
-0.32468619, -0.01160845, -0.01631789, -0.28803008, -0.02634295,
|
||||
-0.17267234, -0.02634295, -0.01776301, -0.02709115, 0.85061814,
|
||||
0.73498669, -0.04111287, -0.06362285, -0.07083428, -0.07879431,
|
||||
0.91010891, -0.03680743, -0.0187955 , -0.01541937, -0.03680743,
|
||||
-0.03029581, -0.02634295, -0.03029581, -0.07471691, -0.01228768,
|
||||
0.76722803, -0.10505173, -0.06192993, -0.09720799, -0.01416217,
|
||||
-0.0187955 , -0.0689636 , -0.02865003, -0.07471691, -0.16460503,
|
||||
-0.09720799, -0.02045547, 0.82732766, -0.0311527 , -0.0187955 ,
|
||||
-0.15684317, -0.04111287, -0.03293737, -0.02104007, -0.02946178,
|
||||
-0.02421701, -0.1353385 , -0.03203302, -0.04111287, -0.10778798,
|
||||
-0.07083428, -0.06027915, -0.02164101, -0.06535882, -0.02946178,
|
||||
-0.07275173, -0.02490638, -0.01678627, -0.30605146, -0.02164101,
|
||||
-0.03482061, -0.03580075, 0.62969079, -0.0182721 , -0.03482061,
|
||||
-0.07083428, -0.04226237, -0.03999333, -0.03580075, -0.03203302,
|
||||
-0.0182721 , -0.03580075, -0.06027915, -0.03386636, -0.02946178,
|
||||
-0.03029581, -0.0689636 , -0.02634295, -0.02634295, -0.03029581,
|
||||
-0.02225873, -0.1353385 , -0.08989109, -0.01988679, -0.0526265 ,
|
||||
-0.03386636, -0.03386636, -0.02786 , -0.03029581, -0.06535882,
|
||||
-0.06535882, -0.03482061, -0.02786 , -0.29396682, -0.03293737,
|
||||
-0.12242534, -0.04589793, -0.04589793, -0.03999333, -0.07471691,
|
||||
-0.11344884, -0.05407977, -0.03482061, -0.01988679, -0.02045547,
|
||||
0.65610673, 0.85423777, -0.02561486, -0.0689636 , -0.02045547,
|
||||
-0.02865003, -0.0526265 , -0.02164101, -0.01776301, -0.08307425,
|
||||
-0.11344884, -0.04982997, -0.0182721 , -0.01498855, -0.02865003,
|
||||
-0.14221564, -0.07879431, -0.02865003, -0.10237696, -0.04465416,
|
||||
-0.07471691, -0.07673078, -0.13200634, -0.02104007, -0.0187955 ,
|
||||
-0.01376599, -0.04717464, -0.01128289, 0.94289953, -0.01988679,
|
||||
-0.01300612, -0.11936722, -0.03203302, -0.01726786, -0.04589793,
|
||||
-0.05407977, -0.09976271, -0.02561486, -0.03999333, -0.02634295,
|
||||
-0.03580075, -0.21771181, 0.8646615 , -0.01988679, 0.62295626,
|
||||
-0.06027915, -0.02045547, -0.18104935, 0.96000667, -0.18104935,
|
||||
-0.15684317, -0.01376599, -0.03293737, -0.08989109, -0.02709115,
|
||||
-0.14221564, 0.72934402, -0.10237696, -0.04226237, -0.72991785,
|
||||
-0.06713876, -0.04226237, -0.03482061, -0.07879431, -0.07471691,
|
||||
-0.15307528, 0.97710634, 0.91010891, -0.02634295, -0.43243779,
|
||||
-0.08756457, -0.03293737, -0.02786 , -0.03482061, -0.0187955 ,
|
||||
0.91692575, -0.04589793, -0.07275173, -0.0311527 , -0.04589793,
|
||||
-0.08307425, 0.67531381, -0.02289366, -0.02634295, -0.03580075,
|
||||
-0.14938186, -0.0526265 , -0.0526265 , 0.46731076, -0.19874565,
|
||||
-0.0187955 , -0.01541937, -0.01586237, -0.02045547, -0.02421701,
|
||||
-0.02634295, -0.11344884, -0.05710047, -0.05121018, -0.09720799,
|
||||
0.9688473 , -0.0526265 , -0.01586237, -0.07471691, -0.06027915,
|
||||
-0.15684317, -0.07879431, -0.02289366, -0.04111287, -0.04848506,
|
||||
-0.02865003, -0.04589793, -0.03580075, -0.04111287, -0.1353385 ,
|
||||
-0.09976271, -0.06362285, 0.67531381, -0.09976271, -0.49676673,
|
||||
-0.07879431, -0.06027915, -0.06027915, -0.05407977, -0.05710047,
|
||||
-0.0689636 , -0.11936722, -0.18973955, -0.02709115, -0.03890304,
|
||||
-0.02634295, 0.19374818, -0.04111287, -0.0311527 , -0.07879431,
|
||||
-0.0193336 , -0.01988679, -0.01376599, -0.07879431, 0.94289953,
|
||||
-0.06027915, -0.02104007, -0.0689636 , -0.04717464, -0.04465416,
|
||||
0.92916572, -0.03999333, -0.06192993, -0.05407977, -0.04982997,
|
||||
-0.46087756, -0.09720799, -0.04589793, -0.07083428, -0.0193336 ,
|
||||
-0.12242534, -0.12242534, -0.05407977, -0.01776301, -0.0311527 ,
|
||||
-0.0689636 , -0.02421701, -0.13200634, -0.19874565, -0.03293737,
|
||||
-0.82774282], atol=1.0e-8)
|
||||
np.testing.assert_allclose(results.resid_working,
|
||||
[ -1.71062283e-03, -1.53549840e-03, -8.42423701e-04,
|
||||
-4.42798906e-03, -8.12073047e-03, -5.71934606e-03,
|
||||
-2.12046213e-03, -5.34278480e-02, -5.16550074e-03,
|
||||
9.82823035e-03, -9.52067472e-02, 1.48142818e-01,
|
||||
-3.59779501e-03, -2.00993083e-03, -3.87619325e-04,
|
||||
-2.62379729e-03, -4.33370579e-04, -1.10808799e-03,
|
||||
-6.75670103e-04, -2.48818484e-03, -6.10129090e-02,
|
||||
6.25511612e-02, -1.10808799e-03, -1.98451739e-02,
|
||||
-3.41454749e-03, -2.61928659e-04, -4.09867263e-04,
|
||||
-2.34090923e-04, -3.56621577e-02, -2.00993083e-03,
|
||||
-4.33370579e-04, -2.76645832e-03, -9.40257152e-04,
|
||||
-6.75670103e-04, -2.21289369e-04, -6.10129090e-02,
|
||||
1.29061842e-01, -4.90775251e-03, -1.19671283e-02,
|
||||
1.41347263e-01, -1.47631680e-01, -6.75670103e-04,
|
||||
-4.58198217e-04, -4.66208406e-03, -3.07429001e-03,
|
||||
-7.11923401e-02, -1.33191898e-04, -2.61928659e-04,
|
||||
-5.90659690e-02, -6.75670103e-04, -2.46673839e-02,
|
||||
-6.75670103e-04, -3.09919962e-04, -7.14047519e-04,
|
||||
1.08085429e-01, 1.43161630e-01, -1.62077632e-03,
|
||||
-3.79032977e-03, -4.66208406e-03, -5.71934606e-03,
|
||||
7.44566288e-02, -1.30492035e-03, -3.46630910e-04,
|
||||
-2.34090923e-04, -1.30492035e-03, -8.90029618e-04,
|
||||
-6.75670103e-04, -8.90029618e-04, -5.16550074e-03,
|
||||
-1.49131762e-04, 1.37018624e-01, -9.87652847e-03,
|
||||
-3.59779501e-03, -8.53083698e-03, -1.97726627e-04,
|
||||
-3.46630910e-04, -4.42798906e-03, -7.97307494e-04,
|
||||
-5.16550074e-03, -2.26348718e-02, -8.53083698e-03,
|
||||
-4.09867263e-04, 1.18189219e-01, -9.40257152e-04,
|
||||
-3.46630910e-04, -2.07414715e-02, -1.62077632e-03,
|
||||
-1.04913757e-03, -4.33370579e-04, -8.42423701e-04,
|
||||
-5.72261321e-04, -1.58375811e-02, -9.93244730e-04,
|
||||
-1.62077632e-03, -1.03659408e-02, -4.66208406e-03,
|
||||
-3.41454749e-03, -4.58198217e-04, -3.99257703e-03,
|
||||
-8.42423701e-04, -4.90775251e-03, -6.04877746e-04,
|
||||
-2.77048947e-04, -6.50004229e-02, -4.58198217e-04,
|
||||
-1.17025566e-03, -1.23580799e-03, 1.46831486e-01,
|
||||
-3.27769165e-04, -1.17025566e-03, -4.66208406e-03,
|
||||
-1.71062283e-03, -1.53549840e-03, -1.23580799e-03,
|
||||
-9.93244730e-04, -3.27769165e-04, -1.23580799e-03,
|
||||
-3.41454749e-03, -1.10808799e-03, -8.42423701e-04,
|
||||
-8.90029618e-04, -4.42798906e-03, -6.75670103e-04,
|
||||
-6.75670103e-04, -8.90029618e-04, -4.84422741e-04,
|
||||
-1.58375811e-02, -7.35405096e-03, -3.87619325e-04,
|
||||
-2.62379729e-03, -1.10808799e-03, -1.10808799e-03,
|
||||
-7.54555329e-04, -8.90029618e-04, -3.99257703e-03,
|
||||
-3.99257703e-03, -1.17025566e-03, -7.54555329e-04,
|
||||
-6.10129090e-02, -1.04913757e-03, -1.31530576e-02,
|
||||
-2.00993083e-03, -2.00993083e-03, -1.53549840e-03,
|
||||
-5.16550074e-03, -1.14104800e-02, -2.76645832e-03,
|
||||
-1.17025566e-03, -3.87619325e-04, -4.09867263e-04,
|
||||
1.48037813e-01, 1.06365931e-01, -6.39314594e-04,
|
||||
-4.42798906e-03, -4.09867263e-04, -7.97307494e-04,
|
||||
-2.62379729e-03, -4.58198217e-04, -3.09919962e-04,
|
||||
-6.32800839e-03, -1.14104800e-02, -2.35929680e-03,
|
||||
-3.27769165e-04, -2.21289369e-04, -7.97307494e-04,
|
||||
-1.73489362e-02, -5.71934606e-03, -7.97307494e-04,
|
||||
-9.40802551e-03, -1.90495384e-03, -5.16550074e-03,
|
||||
-5.43585191e-03, -1.51253748e-02, -4.33370579e-04,
|
||||
-3.46630910e-04, -1.86893696e-04, -2.12046213e-03,
|
||||
-1.25867293e-04, 5.07657192e-02, -3.87619325e-04,
|
||||
-1.66959104e-04, -1.25477263e-02, -9.93244730e-04,
|
||||
-2.93030065e-04, -2.00993083e-03, -2.76645832e-03,
|
||||
-8.95970087e-03, -6.39314594e-04, -1.53549840e-03,
|
||||
-6.75670103e-04, -1.23580799e-03, -3.70792339e-02,
|
||||
1.01184411e-01, -3.87619325e-04, 1.46321062e-01,
|
||||
-3.41454749e-03, -4.09867263e-04, -2.68442736e-02,
|
||||
3.68583645e-02, -2.68442736e-02, -2.07414715e-02,
|
||||
-1.86893696e-04, -1.04913757e-03, -7.35405096e-03,
|
||||
-7.14047519e-04, -1.73489362e-02, 1.43973473e-01,
|
||||
-9.40802551e-03, -1.71062283e-03, -1.43894386e-01,
|
||||
-4.20497779e-03, -1.71062283e-03, -1.17025566e-03,
|
||||
-5.71934606e-03, -5.16550074e-03, -1.98451739e-02,
|
||||
2.18574168e-02, 7.44566288e-02, -6.75670103e-04,
|
||||
-1.06135519e-01, -6.99614755e-03, -1.04913757e-03,
|
||||
-7.54555329e-04, -1.17025566e-03, -3.46630910e-04,
|
||||
6.98449121e-02, -2.00993083e-03, -4.90775251e-03,
|
||||
-9.40257152e-04, -2.00993083e-03, -6.32800839e-03,
|
||||
1.48072729e-01, -5.12120512e-04, -6.75670103e-04,
|
||||
-1.23580799e-03, -1.89814939e-02, -2.62379729e-03,
|
||||
-2.62379729e-03, 1.16328328e-01, -3.16494123e-02,
|
||||
-3.46630910e-04, -2.34090923e-04, -2.47623705e-04,
|
||||
-4.09867263e-04, -5.72261321e-04, -6.75670103e-04,
|
||||
-1.14104800e-02, -3.07429001e-03, -2.48818484e-03,
|
||||
-8.53083698e-03, 2.92419496e-02, -2.62379729e-03,
|
||||
-2.47623705e-04, -5.16550074e-03, -3.41454749e-03,
|
||||
-2.07414715e-02, -5.71934606e-03, -5.12120512e-04,
|
||||
-1.62077632e-03, -2.23682205e-03, -7.97307494e-04,
|
||||
-2.00993083e-03, -1.23580799e-03, -1.62077632e-03,
|
||||
-1.58375811e-02, -8.95970087e-03, -3.79032977e-03,
|
||||
1.48072729e-01, -8.95970087e-03, -1.24186489e-01,
|
||||
-5.71934606e-03, -3.41454749e-03, -3.41454749e-03,
|
||||
-2.76645832e-03, -3.07429001e-03, -4.42798906e-03,
|
||||
-1.25477263e-02, -2.91702648e-02, -7.14047519e-04,
|
||||
-1.45456868e-03, -6.75670103e-04, 3.02653681e-02,
|
||||
-1.62077632e-03, -9.40257152e-04, -5.71934606e-03,
|
||||
-3.66561274e-04, -3.87619325e-04, -1.86893696e-04,
|
||||
-5.71934606e-03, 5.07657192e-02, -3.41454749e-03,
|
||||
-4.33370579e-04, -4.42798906e-03, -2.12046213e-03,
|
||||
-1.90495384e-03, 6.11546973e-02, -1.53549840e-03,
|
||||
-3.59779501e-03, -2.76645832e-03, -2.35929680e-03,
|
||||
-1.14513988e-01, -8.53083698e-03, -2.00993083e-03,
|
||||
-4.66208406e-03, -3.66561274e-04, -1.31530576e-02,
|
||||
-1.31530576e-02, -2.76645832e-03, -3.09919962e-04,
|
||||
-9.40257152e-04, -4.42798906e-03, -5.72261321e-04,
|
||||
-1.51253748e-02, -3.16494123e-02, -1.04913757e-03,
|
||||
-1.18023417e-01])
|
||||
np.testing.assert_allclose(results.resid_pearson,
|
||||
[-0.21006498, -0.20410641, -0.17423009, -0.27216147, -0.3234511 ,
|
||||
-0.29246179, -0.22250903, -0.60917574, -0.28416602, 0.3421141 ,
|
||||
-0.81229277, 1.42158361, -0.25694055, -0.21933056, -0.142444 ,
|
||||
-0.23569027, -0.14660243, -0.18722578, -0.16448609, -0.2323235 ,
|
||||
-0.64526275, 3.57006696, -0.18722578, -0.42513819, -0.25327023,
|
||||
-0.12879668, -0.14450826, -0.12514332, -0.5200069 , -0.21933056,
|
||||
-0.14660243, -0.23910582, -0.17931646, -0.16448609, -0.12335569,
|
||||
-0.64526275, 1.97919183, -0.28010679, -0.36290807, 1.71396874,
|
||||
-1.3440334 , -0.16448609, -0.14872695, -0.27610555, -0.24608613,
|
||||
-0.69339243, -0.1083734 , -0.12879668, -0.63604537, -0.16448609,
|
||||
-0.45684893, -0.16448609, -0.13447767, -0.16686977, 2.3862634 ,
|
||||
1.66535145, -0.20706426, -0.26066405, -0.27610555, -0.29246179,
|
||||
3.18191348, -0.19548397, -0.13840353, -0.12514332, -0.19548397,
|
||||
-0.17675498, -0.16448609, -0.17675498, -0.28416602, -0.11153719,
|
||||
1.81550268, -0.34261205, -0.25694055, -0.32813846, -0.11985666,
|
||||
-0.13840353, -0.27216147, -0.17174127, -0.28416602, -0.44389026,
|
||||
-0.32813846, -0.14450826, 2.18890738, -0.17931646, -0.13840353,
|
||||
-0.43129917, -0.20706426, -0.18455132, -0.14660243, -0.17423009,
|
||||
-0.1575374 , -0.39562855, -0.18191506, -0.20706426, -0.34757708,
|
||||
-0.27610555, -0.25327023, -0.14872695, -0.26444152, -0.17423009,
|
||||
-0.28010679, -0.15982038, -0.13066317, -0.66410018, -0.14872695,
|
||||
-0.189939 , -0.19269154, 1.30401147, -0.13642648, -0.189939 ,
|
||||
-0.27610555, -0.21006498, -0.20410641, -0.19269154, -0.18191506,
|
||||
-0.13642648, -0.19269154, -0.25327023, -0.18722578, -0.17423009,
|
||||
-0.17675498, -0.27216147, -0.16448609, -0.16448609, -0.17675498,
|
||||
-0.15088226, -0.39562855, -0.3142763 , -0.142444 , -0.23569027,
|
||||
-0.18722578, -0.18722578, -0.169288 , -0.17675498, -0.26444152,
|
||||
-0.26444152, -0.189939 , -0.169288 , -0.64526275, -0.18455132,
|
||||
-0.3735026 , -0.21933056, -0.21933056, -0.20410641, -0.28416602,
|
||||
-0.35772404, -0.23910582, -0.189939 , -0.142444 , -0.14450826,
|
||||
1.38125991, 2.42084442, -0.16213645, -0.27216147, -0.14450826,
|
||||
-0.17174127, -0.23569027, -0.14872695, -0.13447767, -0.30099975,
|
||||
-0.35772404, -0.22900483, -0.13642648, -0.12335569, -0.17174127,
|
||||
-0.4071783 , -0.29246179, -0.17174127, -0.33771794, -0.21619749,
|
||||
-0.28416602, -0.28828407, -0.38997712, -0.14660243, -0.13840353,
|
||||
-0.11814455, -0.22250903, -0.10682532, 4.06361781, -0.142444 ,
|
||||
-0.11479334, -0.36816723, -0.18191506, -0.1325567 , -0.21933056,
|
||||
-0.23910582, -0.33289374, -0.16213645, -0.20410641, -0.16448609,
|
||||
-0.19269154, -0.52754269, 2.52762346, -0.142444 , 1.28538406,
|
||||
-0.25327023, -0.14450826, -0.47018591, 4.89940505, -0.47018591,
|
||||
-0.43129917, -0.11814455, -0.18455132, -0.3142763 , -0.16686977,
|
||||
-0.4071783 , 1.64156241, -0.33771794, -0.21006498, -1.6439517 ,
|
||||
-0.26827373, -0.21006498, -0.189939 , -0.29246179, -0.28416602,
|
||||
-0.42513819, 6.53301013, 3.18191348, -0.16448609, -0.87288109,
|
||||
-0.30978696, -0.18455132, -0.169288 , -0.189939 , -0.13840353,
|
||||
3.32226189, -0.21933056, -0.28010679, -0.17931646, -0.21933056,
|
||||
-0.30099975, 1.44218477, -0.1530688 , -0.16448609, -0.19269154,
|
||||
-0.41906522, -0.23569027, -0.23569027, 0.93662539, -0.4980393 ,
|
||||
-0.13840353, -0.12514332, -0.12695686, -0.14450826, -0.1575374 ,
|
||||
-0.16448609, -0.35772404, -0.24608613, -0.2323235 , -0.32813846,
|
||||
5.57673284, -0.23569027, -0.12695686, -0.28416602, -0.25327023,
|
||||
-0.43129917, -0.29246179, -0.1530688 , -0.20706426, -0.22573357,
|
||||
-0.17174127, -0.21933056, -0.19269154, -0.20706426, -0.39562855,
|
||||
-0.33289374, -0.26066405, 1.44218477, -0.33289374, -0.99355423,
|
||||
-0.29246179, -0.25327023, -0.25327023, -0.23910582, -0.24608613,
|
||||
-0.27216147, -0.36816723, -0.48391225, -0.16686977, -0.20119082,
|
||||
-0.16448609, 0.49021146, -0.20706426, -0.17931646, -0.29246179,
|
||||
-0.14040923, -0.142444 , -0.11814455, -0.29246179, 4.06361781,
|
||||
-0.25327023, -0.14660243, -0.27216147, -0.22250903, -0.21619749,
|
||||
3.6218033 , -0.20410641, -0.25694055, -0.23910582, -0.22900483,
|
||||
-0.92458976, -0.32813846, -0.21933056, -0.27610555, -0.14040923,
|
||||
-0.3735026 , -0.3735026 , -0.23910582, -0.13447767, -0.17931646,
|
||||
-0.27216147, -0.1575374 , -0.38997712, -0.4980393 , -0.18455132,
|
||||
-2.19209332])
|
||||
np.testing.assert_allclose(results.resid_anscombe,
|
||||
[-0.31237627, -0.3036605 , -0.25978208, -0.40240831, -0.47552289,
|
||||
-0.43149255, -0.33053793, -0.85617194, -0.41962951, 0.50181328,
|
||||
-1.0954382 , 1.66940149, -0.38048321, -0.3259044 , -0.21280762,
|
||||
-0.34971301, -0.21896842, -0.27890356, -0.2454118 , -0.34482158,
|
||||
-0.90063409, 2.80452413, -0.27890356, -0.61652596, -0.37518169,
|
||||
-0.19255932, -0.2158664 , -0.18713159, -0.74270558, -0.3259044 ,
|
||||
-0.21896842, -0.35467084, -0.2672722 , -0.2454118 , -0.18447466,
|
||||
-0.90063409, 2.05763941, -0.41381347, -0.53089521, 1.88552083,
|
||||
-1.60654218, -0.2454118 , -0.22211425, -0.40807333, -0.3647888 ,
|
||||
-0.95861559, -0.16218047, -0.19255932, -0.88935802, -0.2454118 ,
|
||||
-0.65930821, -0.2454118 , -0.20099345, -0.24892975, 2.28774016,
|
||||
1.85167195, -0.30798858, -0.38585584, -0.40807333, -0.43149255,
|
||||
2.65398426, -0.2910267 , -0.20681747, -0.18713159, -0.2910267 ,
|
||||
-0.26350118, -0.2454118 , -0.26350118, -0.41962951, -0.16689207,
|
||||
1.95381191, -0.50251231, -0.38048321, -0.48214234, -0.17927213,
|
||||
-0.20681747, -0.40240831, -0.25611424, -0.41962951, -0.64189694,
|
||||
-0.48214234, -0.2158664 , 2.18071204, -0.2672722 , -0.20681747,
|
||||
-0.62488429, -0.30798858, -0.27497271, -0.21896842, -0.25978208,
|
||||
-0.23514749, -0.57618899, -0.27109582, -0.30798858, -0.50947546,
|
||||
-0.40807333, -0.37518169, -0.22211425, -0.39130036, -0.25978208,
|
||||
-0.41381347, -0.2385213 , -0.19533116, -0.92350689, -0.22211425,
|
||||
-0.28288904, -0.28692985, 1.5730846 , -0.20388497, -0.28288904,
|
||||
-0.40807333, -0.31237627, -0.3036605 , -0.28692985, -0.27109582,
|
||||
-0.20388497, -0.28692985, -0.37518169, -0.27890356, -0.25978208,
|
||||
-0.26350118, -0.40240831, -0.2454118 , -0.2454118 , -0.26350118,
|
||||
-0.22530448, -0.57618899, -0.46253505, -0.21280762, -0.34971301,
|
||||
-0.27890356, -0.27890356, -0.25249702, -0.26350118, -0.39130036,
|
||||
-0.39130036, -0.28288904, -0.25249702, -0.90063409, -0.27497271,
|
||||
-0.5456246 , -0.3259044 , -0.3259044 , -0.3036605 , -0.41962951,
|
||||
-0.52366614, -0.35467084, -0.28288904, -0.21280762, -0.2158664 ,
|
||||
1.63703418, 2.30570989, -0.24194253, -0.40240831, -0.2158664 ,
|
||||
-0.25611424, -0.34971301, -0.22211425, -0.20099345, -0.44366892,
|
||||
-0.52366614, -0.33999576, -0.20388497, -0.18447466, -0.25611424,
|
||||
-0.59203547, -0.43149255, -0.25611424, -0.49563627, -0.32133344,
|
||||
-0.41962951, -0.42552227, -0.56840788, -0.21896842, -0.20681747,
|
||||
-0.17672552, -0.33053793, -0.15987433, 2.9768074 , -0.21280762,
|
||||
-0.17173916, -0.53821445, -0.27109582, -0.19814236, -0.3259044 ,
|
||||
-0.35467084, -0.48884654, -0.24194253, -0.3036605 , -0.2454118 ,
|
||||
-0.28692985, -0.75249089, 2.35983933, -0.21280762, 1.55726719,
|
||||
-0.37518169, -0.2158664 , -0.67712261, 3.23165236, -0.67712261,
|
||||
-0.62488429, -0.17672552, -0.27497271, -0.46253505, -0.24892975,
|
||||
-0.59203547, 1.83482464, -0.49563627, -0.31237627, -1.83652534,
|
||||
-0.39681759, -0.31237627, -0.28288904, -0.43149255, -0.41962951,
|
||||
-0.61652596, 3.63983609, 2.65398426, -0.2454118 , -1.16171662,
|
||||
-0.45616505, -0.27497271, -0.25249702, -0.28288904, -0.20681747,
|
||||
2.71015945, -0.3259044 , -0.41381347, -0.2672722 , -0.3259044 ,
|
||||
-0.44366892, 1.68567947, -0.22853969, -0.2454118 , -0.28692985,
|
||||
-0.60826548, -0.34971301, -0.34971301, 1.2290223 , -0.71397735,
|
||||
-0.20681747, -0.18713159, -0.1898263 , -0.2158664 , -0.23514749,
|
||||
-0.2454118 , -0.52366614, -0.3647888 , -0.34482158, -0.48214234,
|
||||
3.41271513, -0.34971301, -0.1898263 , -0.41962951, -0.37518169,
|
||||
-0.62488429, -0.43149255, -0.22853969, -0.30798858, -0.3352348 ,
|
||||
-0.25611424, -0.3259044 , -0.28692985, -0.30798858, -0.57618899,
|
||||
-0.48884654, -0.38585584, 1.68567947, -0.48884654, -1.28709718,
|
||||
-0.43149255, -0.37518169, -0.37518169, -0.35467084, -0.3647888 ,
|
||||
-0.40240831, -0.53821445, -0.69534436, -0.24892975, -0.29939131,
|
||||
-0.2454118 , 0.70366797, -0.30798858, -0.2672722 , -0.43149255,
|
||||
-0.2097915 , -0.21280762, -0.17672552, -0.43149255, 2.9768074 ,
|
||||
-0.37518169, -0.21896842, -0.40240831, -0.33053793, -0.32133344,
|
||||
2.82351017, -0.3036605 , -0.38048321, -0.35467084, -0.33999576,
|
||||
-1.21650102, -0.48214234, -0.3259044 , -0.40807333, -0.2097915 ,
|
||||
-0.5456246 , -0.5456246 , -0.35467084, -0.20099345, -0.2672722 ,
|
||||
-0.40240831, -0.23514749, -0.56840788, -0.71397735, -0.27497271,
|
||||
-2.18250381])
|
||||
np.testing.assert_allclose(results.resid_deviance,
|
||||
[-0.29387552, -0.2857098 , -0.24455876, -0.37803944, -0.44609851,
|
||||
-0.40514674, -0.31088148, -0.79449324, -0.39409528, 0.47049798,
|
||||
-1.00668653, 1.48698001, -0.35757692, -0.30654405, -0.20043547,
|
||||
-0.32882173, -0.20622595, -0.26249995, -0.23106769, -0.32424676,
|
||||
-0.83437766, 2.28941155, -0.26249995, -0.57644334, -0.35262564,
|
||||
-0.18139734, -0.20331052, -0.17629229, -0.69186337, -0.30654405,
|
||||
-0.20622595, -0.33345774, -0.251588 , -0.23106769, -0.17379306,
|
||||
-0.83437766, 1.78479093, -0.38867448, -0.4974393 , 1.65565332,
|
||||
-1.43660134, -0.23106769, -0.20918228, -0.38332275, -0.34291558,
|
||||
-0.88609006, -0.15281596, -0.18139734, -0.82428104, -0.23106769,
|
||||
-0.61571821, -0.23106769, -0.18932865, -0.234371 , 1.94999969,
|
||||
1.62970871, -0.2897651 , -0.36259328, -0.38332275, -0.40514674,
|
||||
2.19506559, -0.27386827, -0.19480442, -0.17629229, -0.27386827,
|
||||
-0.24804925, -0.23106769, -0.24804925, -0.39409528, -0.15725009,
|
||||
1.7074519 , -0.47114617, -0.35757692, -0.4522457 , -0.16889886,
|
||||
-0.19480442, -0.37803944, -0.24111595, -0.39409528, -0.59975102,
|
||||
-0.4522457 , -0.20331052, 1.87422489, -0.251588 , -0.19480442,
|
||||
-0.5841272 , -0.2897651 , -0.25881274, -0.20622595, -0.24455876,
|
||||
-0.22142749, -0.53929061, -0.25517563, -0.2897651 , -0.47760126,
|
||||
-0.38332275, -0.35262564, -0.20918228, -0.36767536, -0.24455876,
|
||||
-0.38867448, -0.2245965 , -0.18400413, -0.85481866, -0.20918228,
|
||||
-0.26623785, -0.27002708, 1.40955093, -0.19204738, -0.26623785,
|
||||
-0.38332275, -0.29387552, -0.2857098 , -0.27002708, -0.25517563,
|
||||
-0.19204738, -0.27002708, -0.35262564, -0.26249995, -0.24455876,
|
||||
-0.24804925, -0.37803944, -0.23106769, -0.23106769, -0.24804925,
|
||||
-0.21218006, -0.53929061, -0.43402996, -0.20043547, -0.32882173,
|
||||
-0.26249995, -0.26249995, -0.23772023, -0.24804925, -0.36767536,
|
||||
-0.36767536, -0.26623785, -0.23772023, -0.83437766, -0.25881274,
|
||||
-0.51106408, -0.30654405, -0.30654405, -0.2857098 , -0.39409528,
|
||||
-0.49074728, -0.33345774, -0.26623785, -0.20043547, -0.20331052,
|
||||
1.46111186, 1.96253843, -0.22780971, -0.37803944, -0.20331052,
|
||||
-0.24111595, -0.32882173, -0.20918228, -0.18932865, -0.41648237,
|
||||
-0.49074728, -0.31973217, -0.19204738, -0.17379306, -0.24111595,
|
||||
-0.55389988, -0.40514674, -0.24111595, -0.46476893, -0.30226435,
|
||||
-0.39409528, -0.39958581, -0.53211065, -0.20622595, -0.19480442,
|
||||
-0.16650295, -0.31088148, -0.15064545, 2.39288231, -0.20043547,
|
||||
-0.16181126, -0.5042114 , -0.25517563, -0.18664773, -0.30654405,
|
||||
-0.33345774, -0.45846897, -0.22780971, -0.2857098 , -0.23106769,
|
||||
-0.27002708, -0.7007597 , 1.99998811, -0.20043547, 1.39670618,
|
||||
-0.35262564, -0.20331052, -0.63203077, 2.53733821, -0.63203077,
|
||||
-0.5841272 , -0.16650295, -0.25881274, -0.43402996, -0.234371 ,
|
||||
-0.55389988, 1.61672923, -0.46476893, -0.29387552, -1.61804148,
|
||||
-0.37282386, -0.29387552, -0.26623785, -0.40514674, -0.39409528,
|
||||
-0.57644334, 2.74841605, 2.19506559, -0.23106769, -1.06433539,
|
||||
-0.42810736, -0.25881274, -0.23772023, -0.26623785, -0.19480442,
|
||||
2.23070414, -0.30654405, -0.38867448, -0.251588 , -0.30654405,
|
||||
-0.41648237, 1.49993075, -0.21521982, -0.23106769, -0.27002708,
|
||||
-0.5688444 , -0.32882173, -0.32882173, 1.12233423, -0.66569789,
|
||||
-0.19480442, -0.17629229, -0.17882689, -0.20331052, -0.22142749,
|
||||
-0.23106769, -0.49074728, -0.34291558, -0.32424676, -0.4522457 ,
|
||||
2.63395309, -0.32882173, -0.17882689, -0.39409528, -0.35262564,
|
||||
-0.5841272 , -0.40514674, -0.21521982, -0.2897651 , -0.3152773 ,
|
||||
-0.24111595, -0.30654405, -0.27002708, -0.2897651 , -0.53929061,
|
||||
-0.45846897, -0.36259328, 1.49993075, -0.45846897, -1.17192274,
|
||||
-0.40514674, -0.35262564, -0.35262564, -0.33345774, -0.34291558,
|
||||
-0.37803944, -0.5042114 , -0.64869028, -0.234371 , -0.28170899,
|
||||
-0.23106769, 0.65629132, -0.2897651 , -0.251588 , -0.40514674,
|
||||
-0.19760028, -0.20043547, -0.16650295, -0.40514674, 2.39288231,
|
||||
-0.35262564, -0.20622595, -0.37803944, -0.31088148, -0.30226435,
|
||||
2.30104857, -0.2857098 , -0.35757692, -0.33345774, -0.31973217,
|
||||
-1.11158678, -0.4522457 , -0.30654405, -0.38332275, -0.19760028,
|
||||
-0.51106408, -0.51106408, -0.33345774, -0.18932865, -0.251588 ,
|
||||
-0.37803944, -0.22142749, -0.53211065, -0.66569789, -0.25881274,
|
||||
-1.87550882])
|
||||
np.testing.assert_allclose(results.null,
|
||||
[ 0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759, 0.08860759, 0.08860759, 0.08860759, 0.08860759,
|
||||
0.08860759])
|
||||
self.assertAlmostEqual(results.D2, .200712816165)
|
||||
self.assertAlmostEqual(results.adj_D2, 0.19816731557930456)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,350 @@
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
import numpy as np
|
||||
import warnings
|
||||
|
||||
|
||||
def _bit_length_26(x):
|
||||
if x == 0:
|
||||
return 0
|
||||
elif x == 1:
|
||||
return 1
|
||||
else:
|
||||
return len(bin(x)) - 2
|
||||
|
||||
|
||||
try:
|
||||
from scipy.lib._version import NumpyVersion
|
||||
except ImportError:
|
||||
import re
|
||||
string_types = basestring
|
||||
|
||||
class NumpyVersion():
|
||||
"""Parse and compare numpy version strings.
|
||||
Numpy has the following versioning scheme (numbers given are examples; they
|
||||
can be >9) in principle):
|
||||
- Released version: '1.8.0', '1.8.1', etc.
|
||||
- Alpha: '1.8.0a1', '1.8.0a2', etc.
|
||||
- Beta: '1.8.0b1', '1.8.0b2', etc.
|
||||
- Release candidates: '1.8.0rc1', '1.8.0rc2', etc.
|
||||
- Development versions: '1.8.0.dev-f1234afa' (git commit hash appended)
|
||||
- Development versions after a1: '1.8.0a1.dev-f1234afa',
|
||||
'1.8.0b2.dev-f1234afa',
|
||||
'1.8.1rc1.dev-f1234afa', etc.
|
||||
- Development versions (no git hash available): '1.8.0.dev-Unknown'
|
||||
Comparing needs to be done against a valid version string or other
|
||||
`NumpyVersion` instance.
|
||||
Parameters
|
||||
----------
|
||||
vstring : str
|
||||
Numpy version string (``np.__version__``).
|
||||
Notes
|
||||
-----
|
||||
All dev versions of the same (pre-)release compare equal.
|
||||
Examples
|
||||
--------
|
||||
>>> from scipy.lib._version import NumpyVersion
|
||||
>>> if NumpyVersion(np.__version__) < '1.7.0':
|
||||
... print('skip')
|
||||
skip
|
||||
>>> NumpyVersion('1.7') # raises ValueError, add ".0"
|
||||
"""
|
||||
|
||||
def __init__(self, vstring):
|
||||
self.vstring = vstring
|
||||
ver_main = re.match(r'\d[.]\d+[.]\d+', vstring)
|
||||
if not ver_main:
|
||||
raise ValueError("Not a valid numpy version string")
|
||||
|
||||
self.version = ver_main.group()
|
||||
self.major, self.minor, self.bugfix = [int(x) for x in
|
||||
self.version.split('.')]
|
||||
if len(vstring) == ver_main.end():
|
||||
self.pre_release = 'final'
|
||||
else:
|
||||
alpha = re.match(r'a\d', vstring[ver_main.end():])
|
||||
beta = re.match(r'b\d', vstring[ver_main.end():])
|
||||
rc = re.match(r'rc\d', vstring[ver_main.end():])
|
||||
pre_rel = [m for m in [alpha, beta, rc] if m is not None]
|
||||
if pre_rel:
|
||||
self.pre_release = pre_rel[0].group()
|
||||
else:
|
||||
self.pre_release = ''
|
||||
|
||||
self.is_devversion = bool(re.search(r'.dev-', vstring))
|
||||
|
||||
def _compare_version(self, other):
|
||||
"""Compare major.minor.bugfix"""
|
||||
if self.major == other.major:
|
||||
if self.minor == other.minor:
|
||||
if self.bugfix == other.bugfix:
|
||||
vercmp = 0
|
||||
elif self.bugfix > other.bugfix:
|
||||
vercmp = 1
|
||||
else:
|
||||
vercmp = -1
|
||||
elif self.minor > other.minor:
|
||||
vercmp = 1
|
||||
else:
|
||||
vercmp = -1
|
||||
elif self.major > other.major:
|
||||
vercmp = 1
|
||||
else:
|
||||
vercmp = -1
|
||||
|
||||
return vercmp
|
||||
|
||||
def _compare_pre_release(self, other):
|
||||
"""Compare alpha/beta/rc/final."""
|
||||
if self.pre_release == other.pre_release:
|
||||
vercmp = 0
|
||||
elif self.pre_release == 'final':
|
||||
vercmp = 1
|
||||
elif other.pre_release == 'final':
|
||||
vercmp = -1
|
||||
elif self.pre_release > other.pre_release:
|
||||
vercmp = 1
|
||||
else:
|
||||
vercmp = -1
|
||||
|
||||
return vercmp
|
||||
|
||||
def _compare(self, other):
|
||||
if not isinstance(other, (string_types, NumpyVersion)):
|
||||
raise ValueError("Invalid object to compare with NumpyVersion.")
|
||||
|
||||
if isinstance(other, string_types):
|
||||
other = NumpyVersion(other)
|
||||
|
||||
vercmp = self._compare_version(other)
|
||||
if vercmp == 0:
|
||||
# Same x.y.z version, check for alpha/beta/rc
|
||||
vercmp = self._compare_pre_release(other)
|
||||
if vercmp == 0:
|
||||
# Same version and same pre-release, check if dev version
|
||||
if self.is_devversion is other.is_devversion:
|
||||
vercmp = 0
|
||||
elif self.is_devversion:
|
||||
vercmp = -1
|
||||
else:
|
||||
vercmp = 1
|
||||
|
||||
return vercmp
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._compare(other) < 0
|
||||
|
||||
def __le__(self, other):
|
||||
return self._compare(other) <= 0
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._compare(other) == 0
|
||||
|
||||
def __ne__(self, other):
|
||||
return self._compare(other) != 0
|
||||
|
||||
def __gt__(self, other):
|
||||
return self._compare(other) > 0
|
||||
|
||||
def __ge__(self, other):
|
||||
return self._compare(other) >= 0
|
||||
|
||||
def __repr(self):
|
||||
return "NumpyVersion(%s)" % self.vstring
|
||||
|
||||
|
||||
def _next_regular(target):
|
||||
"""
|
||||
Find the next regular number greater than or equal to target.
|
||||
Regular numbers are composites of the prime factors 2, 3, and 5.
|
||||
Also known as 5-smooth numbers or Hamming numbers, these are the optimal
|
||||
size for inputs to FFTPACK.
|
||||
Target must be a positive integer.
|
||||
"""
|
||||
if target <= 6:
|
||||
return target
|
||||
|
||||
# Quickly check if it's already a power of 2
|
||||
if not (target & (target - 1)):
|
||||
return target
|
||||
|
||||
match = float('inf') # Anything found will be smaller
|
||||
p5 = 1
|
||||
while p5 < target:
|
||||
p35 = p5
|
||||
while p35 < target:
|
||||
# Ceiling integer division, avoiding conversion to float
|
||||
# (quotient = ceil(target / p35))
|
||||
quotient = -(-target // p35)
|
||||
# Quickly find next power of 2 >= quotient
|
||||
try:
|
||||
p2 = 2 ** ((quotient - 1).bit_length())
|
||||
except AttributeError:
|
||||
# Fallback for Python <2.7
|
||||
p2 = 2 ** _bit_length_26(quotient - 1)
|
||||
|
||||
N = p2 * p35
|
||||
if N == target:
|
||||
return N
|
||||
elif N < match:
|
||||
match = N
|
||||
p35 *= 3
|
||||
if p35 == target:
|
||||
return p35
|
||||
if p35 < match:
|
||||
match = p35
|
||||
p5 *= 5
|
||||
if p5 == target:
|
||||
return p5
|
||||
if p5 < match:
|
||||
match = p5
|
||||
return match
|
||||
if NumpyVersion(np.__version__) >= '1.7.1':
|
||||
np_matrix_rank = np.linalg.matrix_rank
|
||||
else:
|
||||
def np_matrix_rank(M, tol=None):
|
||||
"""
|
||||
Return matrix rank of array using SVD method
|
||||
Rank of the array is the number of SVD singular values of the array that are
|
||||
greater than `tol`.
|
||||
Parameters
|
||||
----------
|
||||
M : {(M,), (M, N)} array_like
|
||||
array of <=2 dimensions
|
||||
tol : {None, float}, optional
|
||||
threshold below which SVD values are considered zero. If `tol` is
|
||||
None, and ``S`` is an array with singular values for `M`, and
|
||||
``eps`` is the epsilon value for datatype of ``S``, then `tol` is
|
||||
set to ``S.max() * max(M.shape) * eps``.
|
||||
Notes
|
||||
-----
|
||||
The default threshold to detect rank deficiency is a test on the magnitude
|
||||
of the singular values of `M`. By default, we identify singular values less
|
||||
than ``S.max() * max(M.shape) * eps`` as indicating rank deficiency (with
|
||||
the symbols defined above). This is the algorithm MATLAB uses [1]. It also
|
||||
appears in *Numerical recipes* in the discussion of SVD solutions for linear
|
||||
least squares [2].
|
||||
This default threshold is designed to detect rank deficiency accounting for
|
||||
the numerical errors of the SVD computation. Imagine that there is a column
|
||||
in `M` that is an exact (in floating point) linear combination of other
|
||||
columns in `M`. Computing the SVD on `M` will not produce a singular value
|
||||
exactly equal to 0 in general: any difference of the smallest SVD value from
|
||||
0 will be caused by numerical imprecision in the calculation of the SVD.
|
||||
Our threshold for small SVD values takes this numerical imprecision into
|
||||
account, and the default threshold will detect such numerical rank
|
||||
deficiency. The threshold may declare a matrix `M` rank deficient even if
|
||||
the linear combination of some columns of `M` is not exactly equal to
|
||||
another column of `M` but only numerically very close to another column of
|
||||
`M`.
|
||||
We chose our default threshold because it is in wide use. Other thresholds
|
||||
are possible. For example, elsewhere in the 2007 edition of *Numerical
|
||||
recipes* there is an alternative threshold of ``S.max() *
|
||||
np.finfo(M.dtype).eps / 2. * np.sqrt(m + n + 1.)``. The authors describe
|
||||
this threshold as being based on "expected roundoff error" (p 71).
|
||||
The thresholds above deal with floating point roundoff error in the
|
||||
calculation of the SVD. However, you may have more information about the
|
||||
sources of error in `M` that would make you consider other tolerance values
|
||||
to detect *effective* rank deficiency. The most useful measure of the
|
||||
tolerance depends on the operations you intend to use on your matrix. For
|
||||
example, if your data come from uncertain measurements with uncertainties
|
||||
greater than floating point epsilon, choosing a tolerance near that
|
||||
uncertainty may be preferable. The tolerance may be absolute if the
|
||||
uncertainties are absolute rather than relative.
|
||||
References
|
||||
----------
|
||||
.. [1] MATLAB reference documention, "Rank"
|
||||
http://www.mathworks.com/help/techdoc/ref/rank.html
|
||||
.. [2] W. H. Press, S. A. Teukolsky, W. T. Vetterling and B. P. Flannery,
|
||||
"Numerical Recipes (3rd edition)", Cambridge University Press, 2007,
|
||||
page 795.
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.linalg import matrix_rank
|
||||
>>> matrix_rank(np.eye(4)) # Full rank matrix
|
||||
4
|
||||
>>> I=np.eye(4); I[-1,-1] = 0. # rank deficient matrix
|
||||
>>> matrix_rank(I)
|
||||
3
|
||||
>>> matrix_rank(np.ones((4,))) # 1 dimension - rank 1 unless all 0
|
||||
1
|
||||
>>> matrix_rank(np.zeros((4,)))
|
||||
0
|
||||
"""
|
||||
M = np.asarray(M)
|
||||
if M.ndim > 2:
|
||||
raise TypeError('array should have 2 or fewer dimensions')
|
||||
if M.ndim < 2:
|
||||
return int(not all(M == 0))
|
||||
S = np.linalg.svd(M, compute_uv=False)
|
||||
if tol is None:
|
||||
tol = S.max() * max(M.shape) * np.finfo(S.dtype).eps
|
||||
return np.sum(S > tol)
|
||||
|
||||
|
||||
|
||||
class CacheWriteWarning(UserWarning):
|
||||
pass
|
||||
|
||||
class CachedAttribute(object):
|
||||
|
||||
def __init__(self, func, cachename=None, resetlist=None):
|
||||
self.fget = func
|
||||
self.name = func.__name__
|
||||
self.cachename = cachename or '_cache'
|
||||
self.resetlist = resetlist or ()
|
||||
|
||||
def __get__(self, obj, type=None):
|
||||
if obj is None:
|
||||
return self.fget
|
||||
# Get the cache or set a default one if needed
|
||||
_cachename = self.cachename
|
||||
_cache = getattr(obj, _cachename, None)
|
||||
if _cache is None:
|
||||
setattr(obj, _cachename, resettable_cache())
|
||||
_cache = getattr(obj, _cachename)
|
||||
# Get the name of the attribute to set and cache
|
||||
name = self.name
|
||||
_cachedval = _cache.get(name, None)
|
||||
# print("[_cachedval=%s]" % _cachedval)
|
||||
if _cachedval is None:
|
||||
# Call the "fget" function
|
||||
_cachedval = self.fget(obj)
|
||||
# Set the attribute in obj
|
||||
# print("Setting %s in cache to %s" % (name, _cachedval))
|
||||
try:
|
||||
_cache[name] = _cachedval
|
||||
except KeyError:
|
||||
setattr(_cache, name, _cachedval)
|
||||
# Update the reset list if needed (and possible)
|
||||
resetlist = self.resetlist
|
||||
if resetlist is not ():
|
||||
try:
|
||||
_cache._resetdict[name] = self.resetlist
|
||||
except AttributeError:
|
||||
pass
|
||||
# else:
|
||||
# print("Reading %s from cache (%s)" % (name, _cachedval))
|
||||
return _cachedval
|
||||
|
||||
def __set__(self, obj, value):
|
||||
errmsg = "The attribute '%s' cannot be overwritten" % self.name
|
||||
warnings.warn(errmsg, CacheWriteWarning)
|
||||
|
||||
|
||||
class _cache_readonly(object):
|
||||
"""
|
||||
Decorator for CachedAttribute
|
||||
"""
|
||||
|
||||
def __init__(self, cachename=None, resetlist=None):
|
||||
self.func = None
|
||||
self.cachename = cachename
|
||||
self.resetlist = resetlist or None
|
||||
|
||||
def __call__(self, func):
|
||||
return CachedAttribute(func,
|
||||
cachename=self.cachename,
|
||||
resetlist=self.resetlist)
|
||||
cache_readonly = _cache_readonly()
|
||||
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
"""
|
||||
Variance functions for use with the link functions in statsmodels.family.links
|
||||
"""
|
||||
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
import numpy as np
|
||||
FLOAT_EPS = np.finfo(float).eps
|
||||
|
||||
class VarianceFunction(object):
|
||||
"""
|
||||
Relates the variance of a random variable to its mean. Defaults to 1.
|
||||
|
||||
Methods
|
||||
-------
|
||||
call
|
||||
Returns an array of ones that is the same shape as `mu`
|
||||
|
||||
Notes
|
||||
-----
|
||||
After a variance function is initialized, its call method can be used.
|
||||
|
||||
Alias for VarianceFunction:
|
||||
constant = VarianceFunction()
|
||||
|
||||
See also
|
||||
--------
|
||||
statsmodels.family.family
|
||||
"""
|
||||
|
||||
def __call__(self, mu):
|
||||
"""
|
||||
Default variance function
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
mu : array-like
|
||||
mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
v : array
|
||||
ones(mu.shape)
|
||||
"""
|
||||
mu = np.asarray(mu)
|
||||
return np.ones(mu.shape, np.float64)
|
||||
|
||||
|
||||
def deriv(self, mu):
|
||||
"""
|
||||
Derivative of the variance function v'(mu)
|
||||
"""
|
||||
from statsmodels.tools.numdiff import approx_fprime_cs
|
||||
# TODO: diag workaround proplem with numdiff for 1d
|
||||
return np.diag(approx_fprime_cs(mu, self))
|
||||
|
||||
|
||||
constant = VarianceFunction()
|
||||
constant.__doc__ = """
|
||||
The call method of constant returns a constant variance, i.e., a vector of ones.
|
||||
|
||||
constant is an alias of VarianceFunction()
|
||||
"""
|
||||
|
||||
class Power(object):
|
||||
"""
|
||||
Power variance function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
power : float
|
||||
exponent used in power variance function
|
||||
|
||||
Methods
|
||||
-------
|
||||
call
|
||||
Returns the power variance
|
||||
|
||||
Formulas
|
||||
--------
|
||||
V(mu) = numpy.fabs(mu)**power
|
||||
|
||||
Notes
|
||||
-----
|
||||
Aliases for Power:
|
||||
mu = Power()
|
||||
mu_squared = Power(power=2)
|
||||
mu_cubed = Power(power=3)
|
||||
"""
|
||||
|
||||
def __init__(self, power=1.):
|
||||
self.power = power
|
||||
|
||||
def __call__(self, mu):
|
||||
"""
|
||||
Power variance function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mu : array-like
|
||||
mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
variance : array
|
||||
numpy.fabs(mu)**self.power
|
||||
"""
|
||||
return np.power(np.fabs(mu), self.power)
|
||||
|
||||
|
||||
def deriv(self, mu):
|
||||
"""
|
||||
Derivative of the variance function v'(mu)
|
||||
"""
|
||||
from statsmodels.tools.numdiff import approx_fprime_cs, approx_fprime
|
||||
#return approx_fprime_cs(mu, self) # TODO fix breaks in `fabs
|
||||
# TODO: diag is workaround problem with numdiff for 1d
|
||||
return np.diag(approx_fprime(mu, self))
|
||||
|
||||
|
||||
mu = Power()
|
||||
mu.__doc__ = """
|
||||
Returns np.fabs(mu)
|
||||
|
||||
Notes
|
||||
-----
|
||||
This is an alias of Power()
|
||||
"""
|
||||
mu_squared = Power(power=2)
|
||||
mu_squared.__doc__ = """
|
||||
Returns np.fabs(mu)**2
|
||||
|
||||
Notes
|
||||
-----
|
||||
This is an alias of statsmodels.family.links.Power(power=2)
|
||||
"""
|
||||
mu_cubed = Power(power=3)
|
||||
mu_cubed.__doc__ = """
|
||||
Returns np.fabs(mu)**3
|
||||
|
||||
Notes
|
||||
-----
|
||||
This is an alias of statsmodels.family.links.Power(power=3)
|
||||
"""
|
||||
|
||||
class Binomial(object):
|
||||
"""
|
||||
Binomial variance function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n : int, optional
|
||||
The number of trials for a binomial variable. The default is 1 for
|
||||
p in (0,1)
|
||||
|
||||
Methods
|
||||
-------
|
||||
call
|
||||
Returns the binomial variance
|
||||
|
||||
Formulas
|
||||
--------
|
||||
V(mu) = p * (1 - p) * n
|
||||
|
||||
where p = mu / n
|
||||
|
||||
Notes
|
||||
-----
|
||||
Alias for Binomial:
|
||||
binary = Binomial()
|
||||
|
||||
A private method _clean trims the data by machine epsilon so that p is
|
||||
in (0,1)
|
||||
"""
|
||||
|
||||
def __init__(self, n=1):
|
||||
self.n = n
|
||||
|
||||
def _clean(self, p):
|
||||
return np.clip(p, FLOAT_EPS, 1 - FLOAT_EPS)
|
||||
|
||||
def __call__(self, mu):
|
||||
"""
|
||||
Binomial variance function
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
mu : array-like
|
||||
mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
variance : array
|
||||
variance = mu/n * (1 - mu/n) * self.n
|
||||
"""
|
||||
p = self._clean(mu / self.n)
|
||||
return p * (1 - p) * self.n
|
||||
|
||||
#TODO: inherit from super
|
||||
def deriv(self, mu):
|
||||
"""
|
||||
Derivative of the variance function v'(mu)
|
||||
"""
|
||||
from statsmodels.tools.numdiff import approx_fprime_cs, approx_fprime
|
||||
# TODO: diag workaround proplem with numdiff for 1d
|
||||
return np.diag(approx_fprime_cs(mu, self))
|
||||
|
||||
|
||||
binary = Binomial()
|
||||
binary.__doc__ = """
|
||||
The binomial variance function for n = 1
|
||||
|
||||
Notes
|
||||
-----
|
||||
This is an alias of Binomial(n=1)
|
||||
"""
|
||||
|
||||
class NegativeBinomial(object):
|
||||
'''
|
||||
Negative binomial variance function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
alpha : float
|
||||
The ancillary parameter for the negative binomial variance function.
|
||||
`alpha` is assumed to be nonstochastic. The default is 1.
|
||||
|
||||
Methods
|
||||
-------
|
||||
call
|
||||
Returns the negative binomial variance
|
||||
|
||||
Formulas
|
||||
--------
|
||||
V(mu) = mu + alpha*mu**2
|
||||
|
||||
Notes
|
||||
-----
|
||||
Alias for NegativeBinomial:
|
||||
nbinom = NegativeBinomial()
|
||||
|
||||
A private method _clean trims the data by machine epsilon so that p is
|
||||
in (0,inf)
|
||||
'''
|
||||
|
||||
def __init__(self, alpha=1.):
|
||||
self.alpha = alpha
|
||||
|
||||
def _clean(self, p):
|
||||
return np.clip(p, FLOAT_EPS, np.inf)
|
||||
|
||||
def __call__(self, mu):
|
||||
"""
|
||||
Negative binomial variance function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mu : array-like
|
||||
mean parameters
|
||||
|
||||
Returns
|
||||
-------
|
||||
variance : array
|
||||
variance = mu + alpha*mu**2
|
||||
"""
|
||||
p = self._clean(mu)
|
||||
return p + self.alpha*p**2
|
||||
|
||||
def deriv(self, mu):
|
||||
"""
|
||||
Derivative of the negative binomial variance function.
|
||||
"""
|
||||
|
||||
p = self._clean(mu)
|
||||
return 1 + 2 * self.alpha * p
|
||||
|
||||
nbinom = NegativeBinomial()
|
||||
nbinom.__doc__ = """
|
||||
Negative Binomial variance function.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This is an alias of NegativeBinomial(alpha=1.)
|
||||
"""
|
||||
@@ -0,0 +1 @@
|
||||
from base import *
|
||||
@@ -0,0 +1,4 @@
|
||||
import gwr
|
||||
import sel_bw
|
||||
import diagnostics
|
||||
import kernels
|
||||
@@ -0,0 +1,81 @@
|
||||
"""
|
||||
Diagnostics for estimated gwr modesl
|
||||
"""
|
||||
__author__ = "Taylor Oshan tayoshan@gmail.com"
|
||||
|
||||
import numpy as np
|
||||
from crankshaft.regression.glm.family import Gaussian, Poisson, Binomial
|
||||
|
||||
def get_AICc(gwr):
|
||||
"""
|
||||
Get AICc value
|
||||
|
||||
Gaussian: p61, (2.33), Fotheringham, Brunsdon and Charlton (2002)
|
||||
|
||||
GWGLM: AICc=AIC+2k(k+1)/(n-k-1), Nakaya et al. (2005): p2704, (36)
|
||||
|
||||
"""
|
||||
n = gwr.n
|
||||
k = gwr.tr_S
|
||||
if isinstance(gwr.family, Gaussian):
|
||||
aicc = -2.0*gwr.llf + 2.0*n*(k + 1.0)/(n-k-2.0)
|
||||
elif isinstance(gwr.family, (Poisson, Binomial)):
|
||||
aicc = get_AIC(gwr) + 2.0 * k * (k+1.0) / (n - k - 1.0)
|
||||
return aicc
|
||||
|
||||
def get_AIC(gwr):
|
||||
"""
|
||||
Get AIC calue
|
||||
|
||||
Gaussian: p96, (4.22), Fotheringham, Brunsdon and Charlton (2002)
|
||||
|
||||
GWGLM: AIC(G)=D(G) + 2K(G), where D and K denote the deviance and the effective
|
||||
number of parameters in the model with bandwidth G, respectively.
|
||||
|
||||
"""
|
||||
k = gwr.tr_S
|
||||
#deviance = -2*log-likelihood
|
||||
y = gwr.y
|
||||
mu = gwr.mu
|
||||
if isinstance(gwr.family, Gaussian):
|
||||
aic = -2.0 * gwr.llf + 2.0 * (k+1)
|
||||
elif isinstance(gwr.family, (Poisson, Binomial)):
|
||||
aic = np.sum(gwr.family.resid_dev(y, mu)**2) + 2.0 * k
|
||||
return aic
|
||||
|
||||
def get_BIC(gwr):
|
||||
"""
|
||||
Get BIC value
|
||||
|
||||
Gaussian: p61 (2.34), Fotheringham, Brunsdon and Charlton (2002)
|
||||
BIC = -2log(L)+klog(n)
|
||||
|
||||
GWGLM: BIC = dev + tr_S * log(n)
|
||||
|
||||
"""
|
||||
n = gwr.n # (scalar) number of observations
|
||||
k = gwr.tr_S
|
||||
y = gwr.y
|
||||
mu = gwr.mu
|
||||
if isinstance(gwr.family, Gaussian):
|
||||
bic = -2.0 * gwr.llf + (k+1) * np.log(n)
|
||||
elif isinstance(gwr.family, (Poisson, Binomial)):
|
||||
bic = np.sum(gwr.family.resid_dev(y, mu)**2) + k * np.log(n)
|
||||
return bic
|
||||
|
||||
def get_CV(gwr):
|
||||
"""
|
||||
Get CV value
|
||||
|
||||
Gaussian only
|
||||
|
||||
Methods: p60, (2.31) or p212 (9.4)
|
||||
Fotheringham, A. S., Brunsdon, C., & Charlton, M. (2002).
|
||||
Geographically weighted regression: the analysis of spatially varying relationships.
|
||||
Modification: sum of residual squared is divided by n according to GWR4 results
|
||||
|
||||
"""
|
||||
aa = gwr.resid_response.reshape((-1,1))/(1.0-gwr.influ)
|
||||
cv = np.sum(aa**2)/gwr.n
|
||||
return cv
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,120 @@
|
||||
# GWR kernel function specifications
|
||||
|
||||
__author__ = "Taylor Oshan tayoshan@gmail.com"
|
||||
|
||||
#from pysal.weights.Distance import Kernel
|
||||
import scipy
|
||||
from scipy.spatial.kdtree import KDTree
|
||||
import numpy as np
|
||||
|
||||
#adaptive specifications should be parameterized with nn-1 to match original gwr
|
||||
#implementation. That is, pysal counts self neighbors with knn automatically.
|
||||
|
||||
def fix_gauss(coords, bw, points=None):
|
||||
w = _Kernel(coords, function='gwr_gaussian', bandwidth=bw,
|
||||
truncate=False, points=points)
|
||||
return w.kernel
|
||||
|
||||
def adapt_gauss(coords, nn, points=None):
|
||||
w = _Kernel(coords, fixed=False, k=nn-1, function='gwr_gaussian',
|
||||
truncate=False, points=points)
|
||||
return w.kernel
|
||||
|
||||
def fix_bisquare(coords, bw, points=None):
|
||||
w = _Kernel(coords, function='bisquare', bandwidth=bw, points=points)
|
||||
return w.kernel
|
||||
|
||||
def adapt_bisquare(coords, nn, points=None):
|
||||
w = _Kernel(coords, fixed=False, k=nn-1, function='bisquare', points=points)
|
||||
return w.kernel
|
||||
|
||||
def fix_exp(coords, bw, points=None):
|
||||
w = _Kernel(coords, function='exponential', bandwidth=bw,
|
||||
truncate=False, points=points)
|
||||
return w.kernel
|
||||
|
||||
def adapt_exp(coords, nn, points=None):
|
||||
w = _Kernel(coords, fixed=False, k=nn-1, function='exponential',
|
||||
truncate=False, points=points)
|
||||
return w.kernel
|
||||
|
||||
from scipy.spatial.distance import cdist
|
||||
|
||||
class _Kernel(object):
|
||||
"""
|
||||
|
||||
"""
|
||||
def __init__(self, data, bandwidth=None, fixed=True, k=None,
|
||||
function='triangular', eps=1.0000001, ids=None, truncate=True,
|
||||
points=None): #Added truncate flag
|
||||
if issubclass(type(data), scipy.spatial.KDTree):
|
||||
self.data = data.data
|
||||
data = self.data
|
||||
else:
|
||||
self.data = data
|
||||
if k is not None:
|
||||
self.k = int(k) + 1
|
||||
else:
|
||||
self.k = k
|
||||
if points is None:
|
||||
self.dmat = cdist(self.data, self.data)
|
||||
else:
|
||||
self.points = points
|
||||
self.dmat = cdist(self.points, self.data)
|
||||
self.function = function.lower()
|
||||
self.fixed = fixed
|
||||
self.eps = eps
|
||||
self.trunc = truncate
|
||||
if bandwidth:
|
||||
try:
|
||||
bandwidth = np.array(bandwidth)
|
||||
bandwidth.shape = (len(bandwidth), 1)
|
||||
except:
|
||||
bandwidth = np.ones((len(data), 1), 'float') * bandwidth
|
||||
self.bandwidth = bandwidth
|
||||
else:
|
||||
self._set_bw()
|
||||
self.kernel = self._kernel_funcs(self.dmat/self.bandwidth)
|
||||
|
||||
if self.trunc:
|
||||
mask = np.repeat(self.bandwidth, len(self.data), axis=1)
|
||||
self.kernel[(self.dmat >= mask)] = 0
|
||||
|
||||
def _set_bw(self):
|
||||
if self.k is not None:
|
||||
dmat = np.sort(self.dmat)[:,:self.k]
|
||||
else:
|
||||
dmat = self.dmat
|
||||
if self.fixed:
|
||||
# use max knn distance as bandwidth
|
||||
bandwidth = dmat.max() * self.eps
|
||||
n = len(self.data)
|
||||
self.bandwidth = np.ones((n, 1), 'float') * bandwidth
|
||||
else:
|
||||
# use local max knn distance
|
||||
self.bandwidth = dmat.max(axis=1) * self.eps
|
||||
self.bandwidth.shape = (self.bandwidth.size, 1)
|
||||
|
||||
|
||||
def _kernel_funcs(self, zs):
|
||||
# functions follow Anselin and Rey (2010) table 5.4
|
||||
if self.function == 'triangular':
|
||||
return 1 - zs
|
||||
elif self.function == 'uniform':
|
||||
return np.ones(zi.shape) * 0.5
|
||||
elif self.function == 'quadratic':
|
||||
return (3. / 4) * (1 - zs ** 2)
|
||||
elif self.function == 'quartic':
|
||||
return (15. / 16) * (1 - zs ** 2) ** 2
|
||||
elif self.function == 'gaussian':
|
||||
c = np.pi * 2
|
||||
c = c ** (-0.5)
|
||||
return c * np.exp(-(zs ** 2) / 2.)
|
||||
elif self.function == 'gwr_gaussian':
|
||||
return np.exp(-0.5*(zs)**2)
|
||||
elif self.function == 'bisquare':
|
||||
return (1-(zs)**2)**2
|
||||
elif self.function =='exponential':
|
||||
return np.exp(-zs)
|
||||
else:
|
||||
print('Unsupported kernel function', self.function)
|
||||
@@ -0,0 +1,208 @@
|
||||
#Bandwidth optimization methods
|
||||
|
||||
__author__ = "Taylor Oshan"
|
||||
|
||||
import numpy as np
|
||||
|
||||
def golden_section(a, c, delta, function, tol, max_iter, int_score=False):
|
||||
"""
|
||||
Golden section search routine
|
||||
Method: p212, 9.6.4
|
||||
Fotheringham, A. S., Brunsdon, C., & Charlton, M. (2002).
|
||||
Geographically weighted regression: the analysis of spatially varying relationships.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : float
|
||||
initial max search section value
|
||||
b : float
|
||||
initial min search section value
|
||||
delta : float
|
||||
constant used to determine width of search sections
|
||||
function : function
|
||||
obejective function to be evaluated at different section
|
||||
values
|
||||
int_score : boolean
|
||||
False for float score, True for integer score
|
||||
tol : float
|
||||
tolerance used to determine convergence
|
||||
max_iter : integer
|
||||
maximum iterations if no convergence to tolerance
|
||||
|
||||
Returns
|
||||
-------
|
||||
opt_val : float
|
||||
optimal value
|
||||
opt_score : kernel
|
||||
optimal score
|
||||
output : list of tuples
|
||||
searching history
|
||||
"""
|
||||
b = a + delta * np.abs(c-a)
|
||||
d = c - delta * np.abs(c-a)
|
||||
score = 0.0
|
||||
diff = 1.0e9
|
||||
iters = 0
|
||||
output = []
|
||||
while np.abs(diff) > tol and iters < max_iter:
|
||||
iters += 1
|
||||
if int_score:
|
||||
b = np.round(b)
|
||||
d = np.round(d)
|
||||
|
||||
score_a = function(a)
|
||||
score_b = function(b)
|
||||
score_c = function(c)
|
||||
score_d = function(d)
|
||||
|
||||
if score_b <= score_d:
|
||||
opt_val = b
|
||||
opt_score = score_b
|
||||
c = d
|
||||
d = b
|
||||
b = a + delta * np.abs(c-a)
|
||||
#if int_score:
|
||||
#b = np.round(b)
|
||||
else:
|
||||
opt_val = d
|
||||
opt_score = score_d
|
||||
a = b
|
||||
b = d
|
||||
d = c - delta * np.abs(c-a)
|
||||
#if int_score:
|
||||
#d = np.round(b)
|
||||
|
||||
#if int_score:
|
||||
# opt_val = np.round(opt_val)
|
||||
output.append((opt_val, opt_score))
|
||||
diff = score_b - score_d
|
||||
score = opt_score
|
||||
return np.round(opt_val, 2), opt_score, output
|
||||
|
||||
def equal_interval(l_bound, u_bound, interval, function, int_score=False):
|
||||
"""
|
||||
Interval search, using interval as stepsize
|
||||
|
||||
Parameters
|
||||
----------
|
||||
l_bound : float
|
||||
initial min search section value
|
||||
u_bound : float
|
||||
initial max search section value
|
||||
interval : float
|
||||
constant used to determine width of search sections
|
||||
function : function
|
||||
obejective function to be evaluated at different section
|
||||
values
|
||||
int_score : boolean
|
||||
False for float score, True for integer score
|
||||
|
||||
Returns
|
||||
-------
|
||||
opt_val : float
|
||||
optimal value
|
||||
opt_score : kernel
|
||||
optimal score
|
||||
output : list of tuples
|
||||
searching history
|
||||
"""
|
||||
a = l_bound
|
||||
c = u_bound
|
||||
b = a + interval
|
||||
if int_score:
|
||||
a = np.round(a,0)
|
||||
c = np.round(c,0)
|
||||
b = np.round(b,0)
|
||||
|
||||
output = []
|
||||
|
||||
score_a = function(a)
|
||||
score_c = function(c)
|
||||
|
||||
output.append((a,score_a))
|
||||
output.append((c,score_c))
|
||||
|
||||
if score_a < score_c:
|
||||
opt_val = a
|
||||
opt_score = score_a
|
||||
else:
|
||||
opt_val = c
|
||||
opt_score = score_c
|
||||
|
||||
while b < c:
|
||||
score_b = function(b)
|
||||
|
||||
output.append((b,score_b))
|
||||
|
||||
if score_b < opt_score:
|
||||
opt_val = b
|
||||
opt_score = score_b
|
||||
b = b + interval
|
||||
|
||||
return opt_val, opt_score, output
|
||||
|
||||
|
||||
def flexible_bw(init, y, X, n, k, family, tol, max_iter, rss_score,
|
||||
gwr_func, bw_func, sel_func):
|
||||
if init:
|
||||
bw = sel_func(bw_func(y, X))
|
||||
print bw
|
||||
optim_model = gwr_func(y, X, bw)
|
||||
err = optim_model.resid_response.reshape((-1,1))
|
||||
est = optim_model.params
|
||||
else:
|
||||
model = GLM(y, X, family=self.family, constant=False).fit()
|
||||
err = model.resid_response.reshape((-1,1))
|
||||
est = np.repeat(model.params.T, n, axis=0)
|
||||
|
||||
|
||||
XB = np.multiply(est, X)
|
||||
if rss_score:
|
||||
rss = np.sum((err)**2)
|
||||
iters = 0
|
||||
scores = []
|
||||
delta = 1e6
|
||||
BWs = []
|
||||
VALs = []
|
||||
|
||||
while delta > tol and iters < max_iter:
|
||||
iters += 1
|
||||
new_XB = np.zeros_like(X)
|
||||
bws = []
|
||||
vals = []
|
||||
ests = np.zeros_like(X)
|
||||
f_XB = XB.copy()
|
||||
f_err = err.copy()
|
||||
for i in range(k):
|
||||
temp_y = XB[:,i].reshape((-1,1))
|
||||
temp_y = temp_y + err
|
||||
temp_X = X[:,i].reshape((-1,1))
|
||||
bw_class = bw_func(temp_y, temp_X)
|
||||
bw = sel_func(bw_class)
|
||||
optim_model = gwr_func(temp_y, temp_X, bw)
|
||||
err = optim_model.resid_response.reshape((-1,1))
|
||||
est = optim_model.params.reshape((-1,))
|
||||
|
||||
new_XB[:,i] = np.multiply(est, temp_X.reshape((-1,)))
|
||||
bws.append(bw)
|
||||
ests[:,i] = est
|
||||
vals.append(bw_class.bw[1])
|
||||
|
||||
predy = np.sum(np.multiply(ests, X), axis=1).reshape((-1,1))
|
||||
num = np.sum((new_XB - XB)**2)/n
|
||||
den = np.sum(np.sum(new_XB, axis=1)**2)
|
||||
score = (num/den)**0.5
|
||||
XB = new_XB
|
||||
|
||||
if rss_score:
|
||||
new_rss = np.sum((y - predy)**2)
|
||||
score = np.abs((new_rss - rss)/new_rss)
|
||||
rss = new_rss
|
||||
print score
|
||||
scores.append(score)
|
||||
delta = score
|
||||
BWs.append(bws)
|
||||
VALs.append(vals)
|
||||
|
||||
opt_bws = BWs[-1]
|
||||
return opt_bws, np.array(BWs), np.array(VALs), np.array(scores), f_XB, f_err
|
||||
@@ -0,0 +1,286 @@
|
||||
# GWR Bandwidth selection class
|
||||
|
||||
#Thinking about removing the search method and just having optimization begin in
|
||||
#class __init__
|
||||
|
||||
#x_glob and offset parameters dont yet do anything; former is for semiparametric
|
||||
#GWR and later is for offset variable for Poisson model
|
||||
|
||||
__author__ = "Taylor Oshan Tayoshan@gmail.com"
|
||||
|
||||
from kernels import *
|
||||
from search import golden_section, equal_interval, flexible_bw
|
||||
from gwr import GWR
|
||||
from crankshaft.regression.glm.family import Gaussian, Poisson, Binomial
|
||||
import pysal.spreg.user_output as USER
|
||||
from diagnostics import get_AICc, get_AIC, get_BIC, get_CV
|
||||
from scipy.spatial.distance import pdist, squareform
|
||||
from pysal.common import KDTree
|
||||
import numpy as np
|
||||
|
||||
kernels = {1: fix_gauss, 2: adapt_gauss, 3: fix_bisquare, 4:
|
||||
adapt_bisquare, 5: fix_exp, 6:adapt_exp}
|
||||
getDiag = {'AICc': get_AICc,'AIC':get_AIC, 'BIC': get_BIC, 'CV': get_CV}
|
||||
|
||||
class Sel_BW(object):
|
||||
"""
|
||||
Select bandwidth for kernel
|
||||
|
||||
Methods: p211 - p213, bandwidth selection
|
||||
Fotheringham, A. S., Brunsdon, C., & Charlton, M. (2002).
|
||||
Geographically weighted regression: the analysis of spatially varying relationships.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
y : array
|
||||
n*1, dependent variable.
|
||||
x_glob : array
|
||||
n*k1, fixed independent variable.
|
||||
x_loc : array
|
||||
n*k2, local independent variable, including constant.
|
||||
coords : list of tuples
|
||||
(x,y) of points used in bandwidth selection
|
||||
family : string
|
||||
GWR model type: 'Gaussian', 'logistic, 'Poisson''
|
||||
offset : array
|
||||
n*1, offset variable for Poisson model
|
||||
kernel : string
|
||||
kernel function: 'gaussian', 'bisquare', 'exponetial'
|
||||
fixed : boolean
|
||||
True for fixed bandwidth and False for adaptive (NN)
|
||||
fb : True for flexible (mutliple covaraite-specific) bandwidths
|
||||
False for a traditional (same for all covariates)
|
||||
bandwdith; defualt is False.
|
||||
constant : boolean
|
||||
True to include intercept (default) in model and False to exclude
|
||||
intercept.
|
||||
|
||||
|
||||
Attributes
|
||||
----------
|
||||
y : array
|
||||
n*1, dependent variable.
|
||||
x_glob : array
|
||||
n*k1, fixed independent variable.
|
||||
x_loc : array
|
||||
n*k2, local independent variable, including constant.
|
||||
coords : list of tuples
|
||||
(x,y) of points used in bandwidth selection
|
||||
family : string
|
||||
GWR model type: 'Gaussian', 'logistic, 'Poisson''
|
||||
kernel : string
|
||||
type of kernel used and wether fixed or adaptive
|
||||
criterion : string
|
||||
bw selection criterion: 'AICc', 'AIC', 'BIC', 'CV'
|
||||
search : string
|
||||
bw search method: 'golden', 'interval'
|
||||
bw_min : float
|
||||
min value used in bandwidth search
|
||||
bw_max : float
|
||||
max value used in bandwidth search
|
||||
interval : float
|
||||
interval increment used in interval search
|
||||
tol : float
|
||||
tolerance used to determine convergence
|
||||
max_iter : integer
|
||||
max interations if no convergence to tol
|
||||
fb : True for flexible (mutliple covaraite-specific) bandwidths
|
||||
False for a traditional (same for all covariates)
|
||||
bandwdith; defualt is False.
|
||||
constant : boolean
|
||||
True to include intercept (default) in model and False to exclude
|
||||
intercept.
|
||||
"""
|
||||
def __init__(self, coords, y, x_loc, x_glob=None, family=Gaussian(),
|
||||
offset=None, kernel='bisquare', fixed=False, fb=False, constant=True):
|
||||
self.coords = coords
|
||||
self.y = y
|
||||
self.x_loc = x_loc
|
||||
if x_glob is not None:
|
||||
self.x_glob = x_glob
|
||||
else:
|
||||
self.x_glob = []
|
||||
self.family=family
|
||||
self.fixed = fixed
|
||||
self.kernel = kernel
|
||||
if offset is None:
|
||||
self.offset = np.ones((len(y), 1))
|
||||
else:
|
||||
self.offset = offset * 1.0
|
||||
self.fb = fb
|
||||
self.constant = constant
|
||||
|
||||
def search(self, search='golden_section', criterion='AICc', bw_min=0.0,
|
||||
bw_max=0.0, interval=0.0, tol=1.0e-6, max_iter=200, init_fb=True,
|
||||
tol_fb=1.0e-5, rss_score=False, max_iter_fb=200):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
criterion : string
|
||||
bw selection criterion: 'AICc', 'AIC', 'BIC', 'CV'
|
||||
search : string
|
||||
bw search method: 'golden', 'interval'
|
||||
bw_min : float
|
||||
min value used in bandwidth search
|
||||
bw_max : float
|
||||
max value used in bandwidth search
|
||||
interval : float
|
||||
interval increment used in interval search
|
||||
tol : float
|
||||
tolerance used to determine convergence
|
||||
max_iter : integer
|
||||
max iterations if no convergence to tol
|
||||
init_fb : True to initialize flexible bandwidth search with
|
||||
esitmates from a traditional GWR and False to
|
||||
initialize flexible bandwidth search with global
|
||||
regression estimates
|
||||
tol_fb : convergence tolerence for the flexible bandwidth
|
||||
backfitting algorithm; a larger tolerance may stop the
|
||||
algorith faster though it may result in a less optimal
|
||||
model
|
||||
max_iter_fb : max iterations if no convergence to tol for flexible
|
||||
bandwidth backfittign algorithm
|
||||
rss_score : True to use the residual sum of sqaures to evaluate
|
||||
each iteration of the flexible bandwidth backfitting
|
||||
routine and False to use a smooth function; default is
|
||||
False
|
||||
|
||||
Returns
|
||||
-------
|
||||
bw : scalar or array
|
||||
optimal bandwidth value or values; returns scalar for
|
||||
fb=False and array for fb=True; ordering of bandwidths
|
||||
matches the ordering of the covariates (columns) of the
|
||||
designs matrix, X
|
||||
"""
|
||||
self.search = search
|
||||
self.criterion = criterion
|
||||
self.bw_min = bw_min
|
||||
self.bw_max = bw_max
|
||||
self.interval = interval
|
||||
self.tol = tol
|
||||
self.max_iter = max_iter
|
||||
self.init_fb = init_fb
|
||||
self.tol_fb = tol_fb
|
||||
self.rss_score = rss_score
|
||||
self.max_iter_fb = max_iter_fb
|
||||
|
||||
|
||||
if self.fixed:
|
||||
if self.kernel == 'gaussian':
|
||||
ktype = 1
|
||||
elif self.kernel == 'bisquare':
|
||||
ktype = 3
|
||||
elif self.kernel == 'exponential':
|
||||
ktype = 5
|
||||
else:
|
||||
raise TypeError('Unsupported kernel function ', self.kernel)
|
||||
else:
|
||||
if self.kernel == 'gaussian':
|
||||
ktype = 2
|
||||
elif self.kernel == 'bisquare':
|
||||
ktype = 4
|
||||
elif self.kernel == 'exponential':
|
||||
ktype = 6
|
||||
else:
|
||||
raise TypeError('Unsupported kernel function ', self.kernel)
|
||||
|
||||
function = lambda bw: getDiag[criterion](
|
||||
GWR(self.coords, self.y, self.x_loc, bw, family=self.family,
|
||||
kernel=self.kernel, fixed=self.fixed, offset=self.offset).fit())
|
||||
|
||||
if ktype % 2 == 0:
|
||||
int_score = True
|
||||
else:
|
||||
int_score = False
|
||||
self.int_score = int_score
|
||||
|
||||
if self.fb:
|
||||
self._fbw()
|
||||
print self.bw[1]
|
||||
self.XB = self.bw[4]
|
||||
self.err = self.bw[5]
|
||||
else:
|
||||
self._bw()
|
||||
|
||||
return self.bw[0]
|
||||
|
||||
def _bw(self):
|
||||
gwr_func = lambda bw: getDiag[self.criterion](
|
||||
GWR(self.coords, self.y, self.x_loc, bw, family=self.family,
|
||||
kernel=self.kernel, fixed=self.fixed, constant=self.constant).fit())
|
||||
if self.search == 'golden_section':
|
||||
a,c = self._init_section(self.x_glob, self.x_loc, self.coords,
|
||||
self.constant)
|
||||
delta = 0.38197 #1 - (np.sqrt(5.0)-1.0)/2.0
|
||||
self.bw = golden_section(a, c, delta, gwr_func, self.tol,
|
||||
self.max_iter, self.int_score)
|
||||
elif self.search == 'interval':
|
||||
self.bw = equal_interval(self.bw_min, self.bw_max, self.interval,
|
||||
gwr_func, self.int_score)
|
||||
else:
|
||||
raise TypeError('Unsupported computational search method ', search)
|
||||
|
||||
def _fbw(self):
|
||||
y = self.y
|
||||
if self.constant:
|
||||
X = USER.check_constant(self.x_loc)
|
||||
else:
|
||||
X = self.x_loc
|
||||
n, k = X.shape
|
||||
family = self.family
|
||||
offset = self.offset
|
||||
kernel = self.kernel
|
||||
fixed = self.fixed
|
||||
coords = self.coords
|
||||
search = self.search
|
||||
criterion = self.criterion
|
||||
bw_min = self.bw_min
|
||||
bw_max = self.bw_max
|
||||
interval = self.interval
|
||||
tol = self.tol
|
||||
max_iter = self.max_iter
|
||||
gwr_func = lambda y, X, bw: GWR(coords, y, X, bw, family=family,
|
||||
kernel=kernel, fixed=fixed, offset=offset, constant=False).fit()
|
||||
bw_func = lambda y, X: Sel_BW(coords, y, X, x_glob=[], family=family,
|
||||
kernel=kernel, fixed=fixed, offset=offset, constant=False)
|
||||
sel_func = lambda bw_func: bw_func.search(search=search,
|
||||
criterion=criterion, bw_min=bw_min, bw_max=bw_max,
|
||||
interval=interval, tol=tol, max_iter=max_iter)
|
||||
self.bw = flexible_bw(self.init_fb, y, X, n, k, family, self.tol_fb,
|
||||
self.max_iter_fb, self.rss_score, gwr_func, bw_func, sel_func)
|
||||
|
||||
|
||||
|
||||
def _init_section(self, x_glob, x_loc, coords, constant):
|
||||
if len(x_glob) > 0:
|
||||
n_glob = x_glob.shape[1]
|
||||
else:
|
||||
n_glob = 0
|
||||
if len(x_loc) > 0:
|
||||
n_loc = x_loc.shape[1]
|
||||
else:
|
||||
n_loc = 0
|
||||
if constant:
|
||||
n_vars = n_glob + n_loc + 1
|
||||
else:
|
||||
n_vars = n_glob + n_loc
|
||||
n = np.array(coords).shape[0]
|
||||
|
||||
if self.int_score:
|
||||
a = 40 + 2 * n_vars
|
||||
c = n
|
||||
else:
|
||||
nn = 40 + 2 * n_vars
|
||||
sq_dists = squareform(pdist(coords))
|
||||
sort_dists = np.sort(sq_dists, axis=1)
|
||||
min_dists = sort_dists[:,nn-1]
|
||||
max_dists = sort_dists[:,-1]
|
||||
a = np.min(min_dists)/2.0
|
||||
c = np.max(max_dists)/2.0
|
||||
|
||||
if a < self.bw_min:
|
||||
a = self.bw_min
|
||||
if c > self.bw_max and self.bw_max > 0:
|
||||
c = self.bw_max
|
||||
return a, c
|
||||
@@ -0,0 +1,853 @@
|
||||
"""
|
||||
GWR is tested against results from GWR4
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import pickle as pk
|
||||
from crankshaft.regression.gwr.gwr import GWR, FBGWR
|
||||
from crankshaft.regression.gwr.sel_bw import Sel_BW
|
||||
from crankshaft.regression.gwr.diagnostics import get_AICc, get_AIC, get_BIC, get_CV
|
||||
from crankshaft.regression.glm.family import Gaussian, Poisson, Binomial
|
||||
import numpy as np
|
||||
import pysal
|
||||
|
||||
class TestGWRGaussian(unittest.TestCase):
|
||||
def setUp(self):
|
||||
data = pysal.open(pysal.examples.get_path('GData_utm.csv'))
|
||||
self.coords = zip(data.by_col('X'), data.by_col('Y'))
|
||||
self.y = np.array(data.by_col('PctBach')).reshape((-1,1))
|
||||
rural = np.array(data.by_col('PctRural')).reshape((-1,1))
|
||||
pov = np.array(data.by_col('PctPov')).reshape((-1,1))
|
||||
black = np.array(data.by_col('PctBlack')).reshape((-1,1))
|
||||
self.X = np.hstack([rural, pov, black])
|
||||
self.BS_F = pysal.open(pysal.examples.get_path('georgia_BS_F_listwise.csv'))
|
||||
self.BS_NN = pysal.open(pysal.examples.get_path('georgia_BS_NN_listwise.csv'))
|
||||
self.GS_F = pysal.open(pysal.examples.get_path('georgia_GS_F_listwise.csv'))
|
||||
self.GS_NN = pysal.open(pysal.examples.get_path('georgia_GS_NN_listwise.csv'))
|
||||
self.FB = pk.load(open(pysal.examples.get_path('FB.p'), 'r'))
|
||||
self.XB = pk.load(open(pysal.examples.get_path('XB.p'), 'r'))
|
||||
self.err = pk.load(open(pysal.examples.get_path('err.p'), 'r'))
|
||||
|
||||
def test_BS_F(self):
|
||||
est_Int = self.BS_F.by_col(' est_Intercept')
|
||||
se_Int = self.BS_F.by_col(' se_Intercept')
|
||||
t_Int = self.BS_F.by_col(' t_Intercept')
|
||||
est_rural = self.BS_F.by_col(' est_PctRural')
|
||||
se_rural = self.BS_F.by_col(' se_PctRural')
|
||||
t_rural = self.BS_F.by_col(' t_PctRural')
|
||||
est_pov = self.BS_F.by_col(' est_PctPov')
|
||||
se_pov = self.BS_F.by_col(' se_PctPov')
|
||||
t_pov = self.BS_F.by_col(' t_PctPov')
|
||||
est_black = self.BS_F.by_col(' est_PctBlack')
|
||||
se_black = self.BS_F.by_col(' se_PctBlack')
|
||||
t_black = self.BS_F.by_col(' t_PctBlack')
|
||||
yhat = self.BS_F.by_col(' yhat')
|
||||
res = np.array(self.BS_F.by_col(' residual'))
|
||||
std_res = np.array(self.BS_F.by_col(' std_residual')).reshape((-1,1))
|
||||
localR2 = np.array(self.BS_F.by_col(' localR2')).reshape((-1,1))
|
||||
inf = np.array(self.BS_F.by_col(' influence')).reshape((-1,1))
|
||||
cooksD = np.array(self.BS_F.by_col(' CooksD')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=209267.689, fixed=True)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
CV = get_CV(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 894.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 890.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 944.0)
|
||||
self.assertAlmostEquals(np.round(CV,2), 18.25)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_rural, rslt.params[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_rural, rslt.bse[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_rural, rslt.tvalues[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_pov, rslt.params[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_pov, rslt.bse[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_pov, rslt.tvalues[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_black, rslt.params[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_black, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_black, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-05)
|
||||
np.testing.assert_allclose(res, rslt.resid_response, rtol=1e-04)
|
||||
np.testing.assert_allclose(std_res, rslt.std_res, rtol=1e-04)
|
||||
np.testing.assert_allclose(localR2, rslt.localR2, rtol=1e-05)
|
||||
np.testing.assert_allclose(inf, rslt.influ, rtol=1e-04)
|
||||
np.testing.assert_allclose(cooksD, rslt.cooksD, rtol=1e-00)
|
||||
|
||||
def test_BS_NN(self):
|
||||
est_Int = self.BS_NN.by_col(' est_Intercept')
|
||||
se_Int = self.BS_NN.by_col(' se_Intercept')
|
||||
t_Int = self.BS_NN.by_col(' t_Intercept')
|
||||
est_rural = self.BS_NN.by_col(' est_PctRural')
|
||||
se_rural = self.BS_NN.by_col(' se_PctRural')
|
||||
t_rural = self.BS_NN.by_col(' t_PctRural')
|
||||
est_pov = self.BS_NN.by_col(' est_PctPov')
|
||||
se_pov = self.BS_NN.by_col(' se_PctPov')
|
||||
t_pov = self.BS_NN.by_col(' t_PctPov')
|
||||
est_black = self.BS_NN.by_col(' est_PctBlack')
|
||||
se_black = self.BS_NN.by_col(' se_PctBlack')
|
||||
t_black = self.BS_NN.by_col(' t_PctBlack')
|
||||
yhat = self.BS_NN.by_col(' yhat')
|
||||
res = np.array(self.BS_NN.by_col(' residual'))
|
||||
std_res = np.array(self.BS_NN.by_col(' std_residual')).reshape((-1,1))
|
||||
localR2 = np.array(self.BS_NN.by_col(' localR2')).reshape((-1,1))
|
||||
inf = np.array(self.BS_NN.by_col(' influence')).reshape((-1,1))
|
||||
cooksD = np.array(self.BS_NN.by_col(' CooksD')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=90.000, fixed=False)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
CV = get_CV(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 896.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 892.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 941.0)
|
||||
self.assertAlmostEquals(np.around(CV, 2), 19.19)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_rural, rslt.params[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_rural, rslt.bse[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_rural, rslt.tvalues[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_pov, rslt.params[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_pov, rslt.bse[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_pov, rslt.tvalues[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_black, rslt.params[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_black, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_black, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-05)
|
||||
np.testing.assert_allclose(res, rslt.resid_response, rtol=1e-04)
|
||||
np.testing.assert_allclose(std_res, rslt.std_res, rtol=1e-04)
|
||||
np.testing.assert_allclose(localR2, rslt.localR2, rtol=1e-05)
|
||||
np.testing.assert_allclose(inf, rslt.influ, rtol=1e-04)
|
||||
np.testing.assert_allclose(cooksD, rslt.cooksD, rtol=1e-00)
|
||||
|
||||
def test_GS_F(self):
|
||||
est_Int = self.GS_F.by_col(' est_Intercept')
|
||||
se_Int = self.GS_F.by_col(' se_Intercept')
|
||||
t_Int = self.GS_F.by_col(' t_Intercept')
|
||||
est_rural = self.GS_F.by_col(' est_PctRural')
|
||||
se_rural = self.GS_F.by_col(' se_PctRural')
|
||||
t_rural = self.GS_F.by_col(' t_PctRural')
|
||||
est_pov = self.GS_F.by_col(' est_PctPov')
|
||||
se_pov = self.GS_F.by_col(' se_PctPov')
|
||||
t_pov = self.GS_F.by_col(' t_PctPov')
|
||||
est_black = self.GS_F.by_col(' est_PctBlack')
|
||||
se_black = self.GS_F.by_col(' se_PctBlack')
|
||||
t_black = self.GS_F.by_col(' t_PctBlack')
|
||||
yhat = self.GS_F.by_col(' yhat')
|
||||
res = np.array(self.GS_F.by_col(' residual'))
|
||||
std_res = np.array(self.GS_F.by_col(' std_residual')).reshape((-1,1))
|
||||
localR2 = np.array(self.GS_F.by_col(' localR2')).reshape((-1,1))
|
||||
inf = np.array(self.GS_F.by_col(' influence')).reshape((-1,1))
|
||||
cooksD = np.array(self.GS_F.by_col(' CooksD')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=87308.298,
|
||||
kernel='gaussian', fixed=True)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
CV = get_CV(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 895.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 890.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 943.0)
|
||||
self.assertAlmostEquals(np.around(CV, 2), 18.21)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_rural, rslt.params[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_rural, rslt.bse[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_rural, rslt.tvalues[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_pov, rslt.params[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_pov, rslt.bse[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_pov, rslt.tvalues[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_black, rslt.params[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_black, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_black, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-05)
|
||||
np.testing.assert_allclose(res, rslt.resid_response, rtol=1e-04)
|
||||
np.testing.assert_allclose(std_res, rslt.std_res, rtol=1e-04)
|
||||
np.testing.assert_allclose(localR2, rslt.localR2, rtol=1e-05)
|
||||
np.testing.assert_allclose(inf, rslt.influ, rtol=1e-04)
|
||||
np.testing.assert_allclose(cooksD, rslt.cooksD, rtol=1e-00)
|
||||
|
||||
def test_GS_NN(self):
|
||||
est_Int = self.GS_NN.by_col(' est_Intercept')
|
||||
se_Int = self.GS_NN.by_col(' se_Intercept')
|
||||
t_Int = self.GS_NN.by_col(' t_Intercept')
|
||||
est_rural = self.GS_NN.by_col(' est_PctRural')
|
||||
se_rural = self.GS_NN.by_col(' se_PctRural')
|
||||
t_rural = self.GS_NN.by_col(' t_PctRural')
|
||||
est_pov = self.GS_NN.by_col(' est_PctPov')
|
||||
se_pov = self.GS_NN.by_col(' se_PctPov')
|
||||
t_pov = self.GS_NN.by_col(' t_PctPov')
|
||||
est_black = self.GS_NN.by_col(' est_PctBlack')
|
||||
se_black = self.GS_NN.by_col(' se_PctBlack')
|
||||
t_black = self.GS_NN.by_col(' t_PctBlack')
|
||||
yhat = self.GS_NN.by_col(' yhat')
|
||||
res = np.array(self.GS_NN.by_col(' residual'))
|
||||
std_res = np.array(self.GS_NN.by_col(' std_residual')).reshape((-1,1))
|
||||
localR2 = np.array(self.GS_NN.by_col(' localR2')).reshape((-1,1))
|
||||
inf = np.array(self.GS_NN.by_col(' influence')).reshape((-1,1))
|
||||
cooksD = np.array(self.GS_NN.by_col(' CooksD')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=49.000,
|
||||
kernel='gaussian', fixed=False)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
CV = get_CV(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 896)
|
||||
self.assertAlmostEquals(np.floor(AIC), 894.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 922.0)
|
||||
self.assertAlmostEquals(np.around(CV, 2), 17.91)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_rural, rslt.params[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_rural, rslt.bse[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_rural, rslt.tvalues[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_pov, rslt.params[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_pov, rslt.bse[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(t_pov, rslt.tvalues[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(est_black, rslt.params[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_black, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_black, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-05)
|
||||
np.testing.assert_allclose(res, rslt.resid_response, rtol=1e-04)
|
||||
np.testing.assert_allclose(std_res, rslt.std_res, rtol=1e-04)
|
||||
np.testing.assert_allclose(localR2, rslt.localR2, rtol=1e-05)
|
||||
np.testing.assert_allclose(inf, rslt.influ, rtol=1e-04)
|
||||
np.testing.assert_allclose(cooksD, rslt.cooksD, rtol=1e-00)
|
||||
|
||||
def test_FBGWR(self):
|
||||
model = FBGWR(self.coords, self.y, self.X, [157.0, 65.0, 52.0],
|
||||
XB=self.XB, err=self.err, constant=False)
|
||||
rslt = model.fit()
|
||||
|
||||
np.testing.assert_allclose(rslt.predy, self.FB['predy'], atol=1e-07)
|
||||
np.testing.assert_allclose(rslt.params, self.FB['params'], atol=1e-07)
|
||||
np.testing.assert_allclose(rslt.resid_response, self.FB['u'], atol=1e-05)
|
||||
np.testing.assert_almost_equal(rslt.resid_ss, 6339.3497144025841)
|
||||
|
||||
def test_Prediction(self):
|
||||
coords =np.array(self.coords)
|
||||
index = np.arange(len(self.y))
|
||||
#train = index[0:-10]
|
||||
test = index[-10:]
|
||||
|
||||
#y_train = self.y[train]
|
||||
#X_train = self.X[train]
|
||||
#coords_train = list(coords[train])
|
||||
|
||||
#y_test = self.y[test]
|
||||
X_test = self.X[test]
|
||||
coords_test = list(coords[test])
|
||||
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, 93, family=Gaussian(),
|
||||
fixed=False, kernel='bisquare')
|
||||
results = model.predict(coords_test, X_test)
|
||||
|
||||
params = np.array([22.77198, -0.10254, -0.215093, -0.01405,
|
||||
19.10531, -0.094177, -0.232529, 0.071913,
|
||||
19.743421, -0.080447, -0.30893, 0.083206,
|
||||
17.505759, -0.078919, -0.187955, 0.051719,
|
||||
27.747402, -0.165335, -0.208553, 0.004067,
|
||||
26.210627, -0.138398, -0.360514, 0.072199,
|
||||
18.034833, -0.077047, -0.260556, 0.084319,
|
||||
28.452802, -0.163408, -0.14097, -0.063076,
|
||||
22.353095, -0.103046, -0.226654, 0.002992,
|
||||
18.220508, -0.074034, -0.309812, 0.108636]).reshape((10,4))
|
||||
np.testing.assert_allclose(params, results.params, rtol=1e-03)
|
||||
|
||||
bse = np.array([2.080166, 0.021462, 0.102954, 0.049627,
|
||||
2.536355, 0.022111, 0.123857, 0.051917,
|
||||
1.967813, 0.019716, 0.102562, 0.054918,
|
||||
2.463219, 0.021745, 0.110297, 0.044189,
|
||||
1.556056, 0.019513, 0.12764, 0.040315,
|
||||
1.664108, 0.020114, 0.131208, 0.041613,
|
||||
2.5835, 0.021481, 0.113158, 0.047243,
|
||||
1.709483, 0.019752, 0.116944, 0.043636,
|
||||
1.958233, 0.020947, 0.09974, 0.049821,
|
||||
2.276849, 0.020122, 0.107867, 0.047842]).reshape((10,4))
|
||||
np.testing.assert_allclose(bse, results.bse, rtol=1e-03)
|
||||
|
||||
tvalues = np.array([10.947193, -4.777659, -2.089223, -0.283103,
|
||||
7.532584, -4.259179, -1.877395, 1.385161,
|
||||
10.033179, -4.080362, -3.012133, 1.515096,
|
||||
7.106862, -3.629311, -1.704079, 1.17042,
|
||||
17.831878, -8.473156, -1.633924, 0.100891,
|
||||
15.750552, -6.880725, -2.74765, 1.734978,
|
||||
6.980774, -3.586757, -2.302575, 1.784818,
|
||||
16.644095, -8.273001, -1.205451, -1.445501,
|
||||
11.414933, -4.919384, -2.272458, 0.060064,
|
||||
8.00251, -3.679274, -2.872176, 2.270738]).reshape((10,4))
|
||||
np.testing.assert_allclose(tvalues, results.tvalues, rtol=1e-03)
|
||||
|
||||
localR2 = np.array([[ 0.53068693],
|
||||
[ 0.59582647],
|
||||
[ 0.59700925],
|
||||
[ 0.45769954],
|
||||
[ 0.54634509],
|
||||
[ 0.5494828 ],
|
||||
[ 0.55159604],
|
||||
[ 0.55634237],
|
||||
[ 0.53903842],
|
||||
[ 0.55884954]])
|
||||
np.testing.assert_allclose(localR2, results.localR2, rtol=1e-05)
|
||||
|
||||
class TestGWRPoisson(unittest.TestCase):
|
||||
def setUp(self):
|
||||
data = pysal.open(pysal.examples.get_path('Tokyomortality.csv'), mode='Ur')
|
||||
self.coords = zip(data.by_col('X_CENTROID'), data.by_col('Y_CENTROID'))
|
||||
self.y = np.array(data.by_col('db2564')).reshape((-1,1))
|
||||
self.off = np.array(data.by_col('eb2564')).reshape((-1,1))
|
||||
OCC = np.array(data.by_col('OCC_TEC')).reshape((-1,1))
|
||||
OWN = np.array(data.by_col('OWNH')).reshape((-1,1))
|
||||
POP = np.array(data.by_col('POP65')).reshape((-1,1))
|
||||
UNEMP = np.array(data.by_col('UNEMP')).reshape((-1,1))
|
||||
self.X = np.hstack([OCC,OWN,POP,UNEMP])
|
||||
self.BS_F = pysal.open(pysal.examples.get_path('tokyo_BS_F_listwise.csv'))
|
||||
self.BS_NN = pysal.open(pysal.examples.get_path('tokyo_BS_NN_listwise.csv'))
|
||||
self.GS_F = pysal.open(pysal.examples.get_path('tokyo_GS_F_listwise.csv'))
|
||||
self.GS_NN = pysal.open(pysal.examples.get_path('tokyo_GS_NN_listwise.csv'))
|
||||
self.BS_NN_OFF = pysal.open(pysal.examples.get_path('tokyo_BS_NN_OFF_listwise.csv'))
|
||||
|
||||
def test_BS_F(self):
|
||||
est_Int = self.BS_F.by_col(' est_Intercept')
|
||||
se_Int = self.BS_F.by_col(' se_Intercept')
|
||||
t_Int = self.BS_F.by_col(' t_Intercept')
|
||||
est_OCC = self.BS_F.by_col(' est_OCC_TEC')
|
||||
se_OCC = self.BS_F.by_col(' se_OCC_TEC')
|
||||
t_OCC = self.BS_F.by_col(' t_OCC_TEC')
|
||||
est_OWN = self.BS_F.by_col(' est_OWNH')
|
||||
se_OWN = self.BS_F.by_col(' se_OWNH')
|
||||
t_OWN = self.BS_F.by_col(' t_OWNH')
|
||||
est_POP = self.BS_F.by_col(' est_POP65')
|
||||
se_POP = self.BS_F.by_col(' se_POP65')
|
||||
t_POP = self.BS_F.by_col(' t_POP65')
|
||||
est_UNEMP = self.BS_F.by_col(' est_UNEMP')
|
||||
se_UNEMP = self.BS_F.by_col(' se_UNEMP')
|
||||
t_UNEMP = self.BS_F.by_col(' t_UNEMP')
|
||||
yhat = self.BS_F.by_col(' yhat')
|
||||
pdev = np.array(self.BS_F.by_col(' localpdev')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=26029.625, family=Poisson(),
|
||||
kernel='bisquare', fixed=True)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 13294.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 13247.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 13485.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-05)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-03)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-03)
|
||||
np.testing.assert_allclose(est_OCC, rslt.params[:,1], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_OCC, rslt.bse[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_OCC, rslt.tvalues[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_OWN, rslt.params[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_OWN, rslt.bse[:,2], rtol=1e-03)
|
||||
np.testing.assert_allclose(t_OWN, rslt.tvalues[:,2], rtol=1e-03)
|
||||
np.testing.assert_allclose(est_POP, rslt.params[:,3], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_POP, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_POP, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_UNEMP, rslt.params[:,4], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_UNEMP, rslt.bse[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_UNEMP, rslt.tvalues[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-05)
|
||||
np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
|
||||
def test_BS_NN(self):
|
||||
est_Int = self.BS_NN.by_col(' est_Intercept')
|
||||
se_Int = self.BS_NN.by_col(' se_Intercept')
|
||||
t_Int = self.BS_NN.by_col(' t_Intercept')
|
||||
est_OCC = self.BS_NN.by_col(' est_OCC_TEC')
|
||||
se_OCC = self.BS_NN.by_col(' se_OCC_TEC')
|
||||
t_OCC = self.BS_NN.by_col(' t_OCC_TEC')
|
||||
est_OWN = self.BS_NN.by_col(' est_OWNH')
|
||||
se_OWN = self.BS_NN.by_col(' se_OWNH')
|
||||
t_OWN = self.BS_NN.by_col(' t_OWNH')
|
||||
est_POP = self.BS_NN.by_col(' est_POP65')
|
||||
se_POP = self.BS_NN.by_col(' se_POP65')
|
||||
t_POP = self.BS_NN.by_col(' t_POP65')
|
||||
est_UNEMP = self.BS_NN.by_col(' est_UNEMP')
|
||||
se_UNEMP = self.BS_NN.by_col(' se_UNEMP')
|
||||
t_UNEMP = self.BS_NN.by_col(' t_UNEMP')
|
||||
yhat = self.BS_NN.by_col(' yhat')
|
||||
pdev = np.array(self.BS_NN.by_col(' localpdev')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=50, family=Poisson(),
|
||||
kernel='bisquare', fixed=False)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 13285)
|
||||
self.assertAlmostEquals(np.floor(AIC), 13259.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 13442.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_OCC, rslt.params[:,1], rtol=1e-03)
|
||||
np.testing.assert_allclose(se_OCC, rslt.bse[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_OCC, rslt.tvalues[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_OWN, rslt.params[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_OWN, rslt.bse[:,2], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_OWN, rslt.tvalues[:,2], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_POP, rslt.params[:,3], rtol=1e-03)
|
||||
np.testing.assert_allclose(se_POP, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_POP, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_UNEMP, rslt.params[:,4], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_UNEMP, rslt.bse[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_UNEMP, rslt.tvalues[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-04)
|
||||
np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
def test_BS_NN_Offset(self):
|
||||
est_Int = self.BS_NN_OFF.by_col(' est_Intercept')
|
||||
se_Int = self.BS_NN_OFF.by_col(' se_Intercept')
|
||||
t_Int = self.BS_NN_OFF.by_col(' t_Intercept')
|
||||
est_OCC = self.BS_NN_OFF.by_col(' est_OCC_TEC')
|
||||
se_OCC = self.BS_NN_OFF.by_col(' se_OCC_TEC')
|
||||
t_OCC = self.BS_NN_OFF.by_col(' t_OCC_TEC')
|
||||
est_OWN = self.BS_NN_OFF.by_col(' est_OWNH')
|
||||
se_OWN = self.BS_NN_OFF.by_col(' se_OWNH')
|
||||
t_OWN = self.BS_NN_OFF.by_col(' t_OWNH')
|
||||
est_POP = self.BS_NN_OFF.by_col(' est_POP65')
|
||||
se_POP = self.BS_NN_OFF.by_col(' se_POP65')
|
||||
t_POP = self.BS_NN_OFF.by_col(' t_POP65')
|
||||
est_UNEMP = self.BS_NN_OFF.by_col(' est_UNEMP')
|
||||
se_UNEMP = self.BS_NN_OFF.by_col(' se_UNEMP')
|
||||
t_UNEMP = self.BS_NN_OFF.by_col(' t_UNEMP')
|
||||
yhat = self.BS_NN_OFF.by_col(' yhat')
|
||||
pdev = np.array(self.BS_NN_OFF.by_col(' localpdev')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=100, offset=self.off, family=Poisson(),
|
||||
kernel='bisquare', fixed=False)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 367.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 361.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 451.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-02,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-02, atol=1e-02)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-01,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(est_OCC, rslt.params[:,1], rtol=1e-03,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(se_OCC, rslt.bse[:,1], rtol=1e-02, atol=1e-02)
|
||||
np.testing.assert_allclose(t_OCC, rslt.tvalues[:,1], rtol=1e-01,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(est_OWN, rslt.params[:,2], rtol=1e-04,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(se_OWN, rslt.bse[:,2], rtol=1e-02, atol=1e-02)
|
||||
np.testing.assert_allclose(t_OWN, rslt.tvalues[:,2], rtol=1e-01,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(est_POP, rslt.params[:,3], rtol=1e-03,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(se_POP, rslt.bse[:,3], rtol=1e-02, atol=1e-02)
|
||||
np.testing.assert_allclose(t_POP, rslt.tvalues[:,3], rtol=1e-01,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(est_UNEMP, rslt.params[:,4], rtol=1e-04,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(se_UNEMP, rslt.bse[:,4], rtol=1e-02,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(t_UNEMP, rslt.tvalues[:,4], rtol=1e-01,
|
||||
atol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-03, atol=1e-02)
|
||||
np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-04, atol=1e-02)
|
||||
|
||||
def test_GS_F(self):
|
||||
est_Int = self.GS_F.by_col(' est_Intercept')
|
||||
se_Int = self.GS_F.by_col(' se_Intercept')
|
||||
t_Int = self.GS_F.by_col(' t_Intercept')
|
||||
est_OCC = self.GS_F.by_col(' est_OCC_TEC')
|
||||
se_OCC = self.GS_F.by_col(' se_OCC_TEC')
|
||||
t_OCC = self.GS_F.by_col(' t_OCC_TEC')
|
||||
est_OWN = self.GS_F.by_col(' est_OWNH')
|
||||
se_OWN = self.GS_F.by_col(' se_OWNH')
|
||||
t_OWN = self.GS_F.by_col(' t_OWNH')
|
||||
est_POP = self.GS_F.by_col(' est_POP65')
|
||||
se_POP = self.GS_F.by_col(' se_POP65')
|
||||
t_POP = self.GS_F.by_col(' t_POP65')
|
||||
est_UNEMP = self.GS_F.by_col(' est_UNEMP')
|
||||
se_UNEMP = self.GS_F.by_col(' se_UNEMP')
|
||||
t_UNEMP = self.GS_F.by_col(' t_UNEMP')
|
||||
yhat = self.GS_F.by_col(' yhat')
|
||||
pdev = np.array(self.GS_F.by_col(' localpdev')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=8764.474, family=Poisson(),
|
||||
kernel='gaussian', fixed=True)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 11283.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 11211.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 11497.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-03)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_OCC, rslt.params[:,1], rtol=1e-03)
|
||||
np.testing.assert_allclose(se_OCC, rslt.bse[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_OCC, rslt.tvalues[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_OWN, rslt.params[:,2], rtol=1e-03)
|
||||
np.testing.assert_allclose(se_OWN, rslt.bse[:,2], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_OWN, rslt.tvalues[:,2], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_POP, rslt.params[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_POP, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_POP, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_UNEMP, rslt.params[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_UNEMP, rslt.bse[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_UNEMP, rslt.tvalues[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-04)
|
||||
np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
def test_GS_NN(self):
|
||||
est_Int = self.GS_NN.by_col(' est_Intercept')
|
||||
se_Int = self.GS_NN.by_col(' se_Intercept')
|
||||
t_Int = self.GS_NN.by_col(' t_Intercept')
|
||||
est_OCC = self.GS_NN.by_col(' est_OCC_TEC')
|
||||
se_OCC = self.GS_NN.by_col(' se_OCC_TEC')
|
||||
t_OCC = self.GS_NN.by_col(' t_OCC_TEC')
|
||||
est_OWN = self.GS_NN.by_col(' est_OWNH')
|
||||
se_OWN = self.GS_NN.by_col(' se_OWNH')
|
||||
t_OWN = self.GS_NN.by_col(' t_OWNH')
|
||||
est_POP = self.GS_NN.by_col(' est_POP65')
|
||||
se_POP = self.GS_NN.by_col(' se_POP65')
|
||||
t_POP = self.GS_NN.by_col(' t_POP65')
|
||||
est_UNEMP = self.GS_NN.by_col(' est_UNEMP')
|
||||
se_UNEMP = self.GS_NN.by_col(' se_UNEMP')
|
||||
t_UNEMP = self.GS_NN.by_col(' t_UNEMP')
|
||||
yhat = self.GS_NN.by_col(' yhat')
|
||||
pdev = np.array(self.GS_NN.by_col(' localpdev')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=50, family=Poisson(),
|
||||
kernel='gaussian', fixed=False)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 21070.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 21069.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 21111.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_OCC, rslt.params[:,1], rtol=1e-03)
|
||||
np.testing.assert_allclose(se_OCC, rslt.bse[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_OCC, rslt.tvalues[:,1], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_OWN, rslt.params[:,2], rtol=1e-04)
|
||||
np.testing.assert_allclose(se_OWN, rslt.bse[:,2], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_OWN, rslt.tvalues[:,2], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_POP, rslt.params[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_POP, rslt.bse[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_POP, rslt.tvalues[:,3], rtol=1e-02)
|
||||
np.testing.assert_allclose(est_UNEMP, rslt.params[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(se_UNEMP, rslt.bse[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(t_UNEMP, rslt.tvalues[:,4], rtol=1e-02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-04)
|
||||
np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
class TestGWRBinomial(unittest.TestCase):
|
||||
def setUp(self):
|
||||
data = pysal.open(pysal.examples.get_path('landslides.csv'))
|
||||
self.coords = zip(data.by_col('X'), data.by_col('Y'))
|
||||
self.y = np.array(data.by_col('Landslid')).reshape((-1,1))
|
||||
ELEV = np.array(data.by_col('Elev')).reshape((-1,1))
|
||||
SLOPE = np.array(data.by_col('Slope')).reshape((-1,1))
|
||||
SIN = np.array(data.by_col('SinAspct')).reshape((-1,1))
|
||||
COS = np.array(data.by_col('CosAspct')).reshape((-1,1))
|
||||
SOUTH = np.array(data.by_col('AbsSouth')).reshape((-1,1))
|
||||
DIST = np.array(data.by_col('DistStrm')).reshape((-1,1))
|
||||
self.X = np.hstack([ELEV, SLOPE, SIN, COS, SOUTH, DIST])
|
||||
self.BS_F = pysal.open(pysal.examples.get_path('clearwater_BS_F_listwise.csv'))
|
||||
self.BS_NN = pysal.open(pysal.examples.get_path('clearwater_BS_NN_listwise.csv'))
|
||||
self.GS_F = pysal.open(pysal.examples.get_path('clearwater_GS_F_listwise.csv'))
|
||||
self.GS_NN = pysal.open(pysal.examples.get_path('clearwater_GS_NN_listwise.csv'))
|
||||
|
||||
def test_BS_F(self):
|
||||
est_Int = self.BS_F.by_col(' est_Intercept')
|
||||
se_Int = self.BS_F.by_col(' se_Intercept')
|
||||
t_Int = self.BS_F.by_col(' t_Intercept')
|
||||
est_elev = self.BS_F.by_col(' est_Elev')
|
||||
se_elev = self.BS_F.by_col(' se_Elev')
|
||||
t_elev = self.BS_F.by_col(' t_Elev')
|
||||
est_slope = self.BS_F.by_col(' est_Slope')
|
||||
se_slope = self.BS_F.by_col(' se_Slope')
|
||||
t_slope = self.BS_F.by_col(' t_Slope')
|
||||
est_sin = self.BS_F.by_col(' est_SinAspct')
|
||||
se_sin = self.BS_F.by_col(' se_SinAspct')
|
||||
t_sin = self.BS_F.by_col(' t_SinAspct')
|
||||
est_cos = self.BS_F.by_col(' est_CosAspct')
|
||||
se_cos = self.BS_F.by_col(' se_CosAspct')
|
||||
t_cos = self.BS_F.by_col(' t_CosAspct')
|
||||
est_south = self.BS_F.by_col(' est_AbsSouth')
|
||||
se_south = self.BS_F.by_col(' se_AbsSouth')
|
||||
t_south = self.BS_F.by_col(' t_AbsSouth')
|
||||
est_strm = self.BS_F.by_col(' est_DistStrm')
|
||||
se_strm = self.BS_F.by_col(' se_DistStrm')
|
||||
t_strm = self.BS_F.by_col(' t_DistStrm')
|
||||
yhat = self.BS_F.by_col(' yhat')
|
||||
pdev = np.array(self.BS_F.by_col(' localpdev')).reshape((-1,1))
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=19642.170, family=Binomial(),
|
||||
kernel='bisquare', fixed=True)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 275.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 271.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 349.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_elev, rslt.params[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_elev, rslt.bse[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_elev, rslt.tvalues[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_slope, rslt.params[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_slope, rslt.bse[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_slope, rslt.tvalues[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_sin, rslt.params[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(se_sin, rslt.bse[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(t_sin, rslt.tvalues[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(est_cos, rslt.params[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(se_cos, rslt.bse[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(t_cos, rslt.tvalues[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(est_south, rslt.params[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(se_south, rslt.bse[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(t_south, rslt.tvalues[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(est_strm, rslt.params[:,6], rtol=1e02)
|
||||
np.testing.assert_allclose(se_strm, rslt.bse[:,6], rtol=1e01)
|
||||
np.testing.assert_allclose(t_strm, rslt.tvalues[:,6], rtol=1e02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-01)
|
||||
#This test fails - likely due to compound rounding errors
|
||||
#Has been tested using statsmodels.family calculations and
|
||||
#code from Jing's python version, which both yield the same
|
||||
#np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
def test_BS_NN(self):
|
||||
est_Int = self.BS_NN.by_col(' est_Intercept')
|
||||
se_Int = self.BS_NN.by_col(' se_Intercept')
|
||||
t_Int = self.BS_NN.by_col(' t_Intercept')
|
||||
est_elev = self.BS_NN.by_col(' est_Elev')
|
||||
se_elev = self.BS_NN.by_col(' se_Elev')
|
||||
t_elev = self.BS_NN.by_col(' t_Elev')
|
||||
est_slope = self.BS_NN.by_col(' est_Slope')
|
||||
se_slope = self.BS_NN.by_col(' se_Slope')
|
||||
t_slope = self.BS_NN.by_col(' t_Slope')
|
||||
est_sin = self.BS_NN.by_col(' est_SinAspct')
|
||||
se_sin = self.BS_NN.by_col(' se_SinAspct')
|
||||
t_sin = self.BS_NN.by_col(' t_SinAspct')
|
||||
est_cos = self.BS_NN.by_col(' est_CosAspct')
|
||||
se_cos = self.BS_NN.by_col(' se_CosAspct')
|
||||
t_cos = self.BS_NN.by_col(' t_CosAspct')
|
||||
est_south = self.BS_NN.by_col(' est_AbsSouth')
|
||||
se_south = self.BS_NN.by_col(' se_AbsSouth')
|
||||
t_south = self.BS_NN.by_col(' t_AbsSouth')
|
||||
est_strm = self.BS_NN.by_col(' est_DistStrm')
|
||||
se_strm = self.BS_NN.by_col(' se_DistStrm')
|
||||
t_strm = self.BS_NN.by_col(' t_DistStrm')
|
||||
yhat = self.BS_NN.by_col(' yhat')
|
||||
pdev = self.BS_NN.by_col(' localpdev')
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=158, family=Binomial(),
|
||||
kernel='bisquare', fixed=False)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 277.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 271.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 358.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_elev, rslt.params[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_elev, rslt.bse[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_elev, rslt.tvalues[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_slope, rslt.params[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_slope, rslt.bse[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_slope, rslt.tvalues[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_sin, rslt.params[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(se_sin, rslt.bse[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(t_sin, rslt.tvalues[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(est_cos, rslt.params[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(se_cos, rslt.bse[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(t_cos, rslt.tvalues[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(est_south, rslt.params[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(se_south, rslt.bse[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(t_south, rslt.tvalues[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(est_strm, rslt.params[:,6], rtol=1e03)
|
||||
np.testing.assert_allclose(se_strm, rslt.bse[:,6], rtol=1e01)
|
||||
np.testing.assert_allclose(t_strm, rslt.tvalues[:,6], rtol=1e03)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-01)
|
||||
#This test fails - likely due to compound rounding errors
|
||||
#Has been tested using statsmodels.family calculations and
|
||||
#code from Jing's python version, which both yield the same
|
||||
#np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
def test_GS_F(self):
|
||||
est_Int = self.GS_F.by_col(' est_Intercept')
|
||||
se_Int = self.GS_F.by_col(' se_Intercept')
|
||||
t_Int = self.GS_F.by_col(' t_Intercept')
|
||||
est_elev = self.GS_F.by_col(' est_Elev')
|
||||
se_elev = self.GS_F.by_col(' se_Elev')
|
||||
t_elev = self.GS_F.by_col(' t_Elev')
|
||||
est_slope = self.GS_F.by_col(' est_Slope')
|
||||
se_slope = self.GS_F.by_col(' se_Slope')
|
||||
t_slope = self.GS_F.by_col(' t_Slope')
|
||||
est_sin = self.GS_F.by_col(' est_SinAspct')
|
||||
se_sin = self.GS_F.by_col(' se_SinAspct')
|
||||
t_sin = self.GS_F.by_col(' t_SinAspct')
|
||||
est_cos = self.GS_F.by_col(' est_CosAspct')
|
||||
se_cos = self.GS_F.by_col(' se_CosAspct')
|
||||
t_cos = self.GS_F.by_col(' t_CosAspct')
|
||||
est_south = self.GS_F.by_col(' est_AbsSouth')
|
||||
se_south = self.GS_F.by_col(' se_AbsSouth')
|
||||
t_south = self.GS_F.by_col(' t_AbsSouth')
|
||||
est_strm = self.GS_F.by_col(' est_DistStrm')
|
||||
se_strm = self.GS_F.by_col(' se_DistStrm')
|
||||
t_strm = self.GS_F.by_col(' t_DistStrm')
|
||||
yhat = self.GS_F.by_col(' yhat')
|
||||
pdev = self.GS_F.by_col(' localpdev')
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=8929.061, family=Binomial(),
|
||||
kernel='gaussian', fixed=True)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 276.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 272.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 341.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_elev, rslt.params[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_elev, rslt.bse[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_elev, rslt.tvalues[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_slope, rslt.params[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_slope, rslt.bse[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_slope, rslt.tvalues[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_sin, rslt.params[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(se_sin, rslt.bse[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(t_sin, rslt.tvalues[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(est_cos, rslt.params[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(se_cos, rslt.bse[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(t_cos, rslt.tvalues[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(est_south, rslt.params[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(se_south, rslt.bse[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(t_south, rslt.tvalues[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(est_strm, rslt.params[:,6], rtol=1e02)
|
||||
np.testing.assert_allclose(se_strm, rslt.bse[:,6], rtol=1e01)
|
||||
np.testing.assert_allclose(t_strm, rslt.tvalues[:,6], rtol=1e02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-01)
|
||||
#This test fails - likely due to compound rounding errors
|
||||
#Has been tested using statsmodels.family calculations and
|
||||
#code from Jing's python version, which both yield the same
|
||||
#np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
def test_GS_NN(self):
|
||||
est_Int = self.GS_NN.by_col(' est_Intercept')
|
||||
se_Int = self.GS_NN.by_col(' se_Intercept')
|
||||
t_Int = self.GS_NN.by_col(' t_Intercept')
|
||||
est_elev = self.GS_NN.by_col(' est_Elev')
|
||||
se_elev = self.GS_NN.by_col(' se_Elev')
|
||||
t_elev = self.GS_NN.by_col(' t_Elev')
|
||||
est_slope = self.GS_NN.by_col(' est_Slope')
|
||||
se_slope = self.GS_NN.by_col(' se_Slope')
|
||||
t_slope = self.GS_NN.by_col(' t_Slope')
|
||||
est_sin = self.GS_NN.by_col(' est_SinAspct')
|
||||
se_sin = self.GS_NN.by_col(' se_SinAspct')
|
||||
t_sin = self.GS_NN.by_col(' t_SinAspct')
|
||||
est_cos = self.GS_NN.by_col(' est_CosAspct')
|
||||
se_cos = self.GS_NN.by_col(' se_CosAspct')
|
||||
t_cos = self.GS_NN.by_col(' t_CosAspct')
|
||||
est_south = self.GS_NN.by_col(' est_AbsSouth')
|
||||
se_south = self.GS_NN.by_col(' se_AbsSouth')
|
||||
t_south = self.GS_NN.by_col(' t_AbsSouth')
|
||||
est_strm = self.GS_NN.by_col(' est_DistStrm')
|
||||
se_strm = self.GS_NN.by_col(' se_DistStrm')
|
||||
t_strm = self.GS_NN.by_col(' t_DistStrm')
|
||||
yhat = self.GS_NN.by_col(' yhat')
|
||||
pdev = self.GS_NN.by_col(' localpdev')
|
||||
|
||||
model = GWR(self.coords, self.y, self.X, bw=64, family=Binomial(),
|
||||
kernel='gaussian', fixed=False)
|
||||
rslt = model.fit()
|
||||
|
||||
AICc = get_AICc(rslt)
|
||||
AIC = get_AIC(rslt)
|
||||
BIC = get_BIC(rslt)
|
||||
|
||||
self.assertAlmostEquals(np.floor(AICc), 276.0)
|
||||
self.assertAlmostEquals(np.floor(AIC), 273.0)
|
||||
self.assertAlmostEquals(np.floor(BIC), 331.0)
|
||||
np.testing.assert_allclose(est_Int, rslt.params[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_Int, rslt.bse[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_Int, rslt.tvalues[:,0], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_elev, rslt.params[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_elev, rslt.bse[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_elev, rslt.tvalues[:,1], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_slope, rslt.params[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(se_slope, rslt.bse[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(t_slope, rslt.tvalues[:,2], rtol=1e-00)
|
||||
np.testing.assert_allclose(est_sin, rslt.params[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(se_sin, rslt.bse[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(t_sin, rslt.tvalues[:,3], rtol=1e01)
|
||||
np.testing.assert_allclose(est_cos, rslt.params[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(se_cos, rslt.bse[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(t_cos, rslt.tvalues[:,4], rtol=1e01)
|
||||
np.testing.assert_allclose(est_south, rslt.params[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(se_south, rslt.bse[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(t_south, rslt.tvalues[:,5], rtol=1e01)
|
||||
np.testing.assert_allclose(est_strm, rslt.params[:,6], rtol=1e02)
|
||||
np.testing.assert_allclose(se_strm, rslt.bse[:,6], rtol=1e01)
|
||||
np.testing.assert_allclose(t_strm, rslt.tvalues[:,6], rtol=1e02)
|
||||
np.testing.assert_allclose(yhat, rslt.mu, rtol=1e-00)
|
||||
#This test fails - likely due to compound rounding errors
|
||||
#Has been tested using statsmodels.family calculations and
|
||||
#code from Jing's python version, which both yield the same
|
||||
#np.testing.assert_allclose(pdev, rslt.pDev, rtol=1e-05)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,84 @@
|
||||
import unittest
|
||||
import numpy as np
|
||||
import pysal
|
||||
from pysal.contrib.gwr.kernels import *
|
||||
|
||||
PEGP = pysal.examples.get_path
|
||||
|
||||
class TestKernels(unittest.TestCase):
|
||||
def setUp(self):
|
||||
np.random.seed(1234)
|
||||
x = np.arange(1,6)
|
||||
y = np.arange(5,0, -1)
|
||||
np.random.shuffle(x)
|
||||
np.random.shuffle(y)
|
||||
self.coords = np.array(zip(x, y))
|
||||
self.fix_gauss_kern = np.array([
|
||||
[ 1. , 0.38889556, 0.48567179, 0.48567179, 0.89483932],
|
||||
[ 0.38889556, 1. , 0.89483932, 0.64118039, 0.48567179],
|
||||
[ 0.48567179, 0.89483932, 1. , 0.89483932, 0.48567179],
|
||||
[ 0.48567179, 0.64118039, 0.89483932, 1. , 0.38889556],
|
||||
[ 0.89483932, 0.48567179, 0.48567179, 0.38889556, 1. ]])
|
||||
self.adapt_gauss_kern = np.array([
|
||||
[ 1. , 0.52004183, 0.60653072, 0.60653072, 0.92596109],
|
||||
[ 0.34559083, 1. , 0.88249692, 0.60653072, 0.44374738],
|
||||
[ 0.03877423, 0.60653072, 1. , 0.60653072, 0.03877423],
|
||||
[ 0.44374738, 0.60653072, 0.88249692, 1. , 0.34559083],
|
||||
[ 0.92596109, 0.60653072, 0.60653072, 0.52004183, 1. ]])
|
||||
self.fix_bisquare_kern = np.array([
|
||||
[ 1. , 0. , 0. , 0. , 0.60493827],
|
||||
[ 0. , 1. , 0.60493827, 0.01234568, 0. ],
|
||||
[ 0. , 0.60493827, 1. , 0.60493827, 0. ],
|
||||
[ 0. , 0.01234568, 0.60493827, 1. , 0. ],
|
||||
[ 0.60493827, 0. , 0. , 0. , 1. ]])
|
||||
self.adapt_bisquare_kern = np.array([
|
||||
[ 1.00000000e+00, 0.00000000e+00, 0.00000000e+00,
|
||||
3.99999881e-14, 7.15976383e-01],
|
||||
[ 0.00000000e+00, 1.00000000e+00, 5.62500075e-01,
|
||||
3.99999881e-14, 0.00000000e+00],
|
||||
[ 0.00000000e+00, 3.99999881e-14, 1.00000000e+00,
|
||||
3.99999881e-14, 0.00000000e+00],
|
||||
[ 0.00000000e+00, 3.99999881e-14, 5.62500075e-01,
|
||||
1.00000000e+00, 0.00000000e+00],
|
||||
[ 7.15976383e-01, 0.00000000e+00, 3.99999881e-14,
|
||||
0.00000000e+00, 1.00000000e+00]])
|
||||
self.fix_exp_kern = np.array([
|
||||
[ 1. , 0.2529993 , 0.30063739, 0.30063739, 0.62412506],
|
||||
[ 0.2529993 , 1. , 0.62412506, 0.38953209, 0.30063739],
|
||||
[ 0.30063739, 0.62412506, 1. , 0.62412506, 0.30063739],
|
||||
[ 0.30063739, 0.38953209, 0.62412506, 1. , 0.2529993 ],
|
||||
[ 0.62412506, 0.30063739, 0.30063739, 0.2529993 , 1. ]])
|
||||
self.adapt_exp_kern = np.array([
|
||||
[ 1. , 0.31868771, 0.36787948, 0.36787948, 0.67554721],
|
||||
[ 0.23276223, 1. , 0.60653069, 0.36787948, 0.27949951],
|
||||
[ 0.07811997, 0.36787948, 1. , 0.36787948, 0.07811997],
|
||||
[ 0.27949951, 0.36787948, 0.60653069, 1. , 0.23276223],
|
||||
[ 0.67554721, 0.36787948, 0.36787948, 0.31868771, 1. ]])
|
||||
|
||||
def test_fix_gauss(self):
|
||||
kern = fix_gauss(self.coords, 3)
|
||||
np.testing.assert_allclose(kern, self.fix_gauss_kern)
|
||||
|
||||
def test_adapt_gauss(self):
|
||||
kern = adapt_gauss(self.coords, 3)
|
||||
np.testing.assert_allclose(kern, self.adapt_gauss_kern)
|
||||
|
||||
def test_fix_biqsquare(self):
|
||||
kern = fix_bisquare(self.coords, 3)
|
||||
np.testing.assert_allclose(kern, self.fix_bisquare_kern,
|
||||
atol=1e-01)
|
||||
|
||||
def test_adapt_bisqaure(self):
|
||||
kern = adapt_bisquare(self.coords, 3)
|
||||
np.testing.assert_allclose(kern, self.adapt_bisquare_kern, atol=1e-012)
|
||||
|
||||
def test_fix_exp(self):
|
||||
kern = fix_exp(self.coords, 3)
|
||||
np.testing.assert_allclose(kern, self.fix_exp_kern)
|
||||
|
||||
def test_adapt_exp(self):
|
||||
kern = adapt_exp(self.coords, 3)
|
||||
np.testing.assert_allclose(kern, self.adapt_exp_kern)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,139 @@
|
||||
|
||||
"""
|
||||
GWR is tested against results from GWR4
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import pickle as pk
|
||||
from pysal.contrib.glm.family import Gaussian, Poisson, Binomial
|
||||
from pysal.contrib.gwr.sel_bw import Sel_BW
|
||||
import numpy as np
|
||||
import pysal
|
||||
|
||||
class TestSelBW(unittest.TestCase):
|
||||
def setUp(self):
|
||||
data = pysal.open(pysal.examples.get_path('GData_utm.csv'))
|
||||
self.coords = zip(data.by_col('X'), data.by_col('Y'))
|
||||
self.y = np.array(data.by_col('PctBach')).reshape((-1,1))
|
||||
rural = np.array(data.by_col('PctRural')).reshape((-1,1))
|
||||
pov = np.array(data.by_col('PctPov')).reshape((-1,1))
|
||||
black = np.array(data.by_col('PctBlack')).reshape((-1,1))
|
||||
self.X = np.hstack([rural, pov, black])
|
||||
self.XB = pk.load(open(pysal.examples.get_path('XB.p'), 'r'))
|
||||
self.err = pk.load(open(pysal.examples.get_path('err.p'), 'r'))
|
||||
|
||||
def test_golden_fixed_AICc(self):
|
||||
bw1 = 211027.34
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='bisquare',
|
||||
fixed=True).search(criterion='AICc')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_golden_adapt_AICc(self):
|
||||
bw1 = 93.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='bisquare',
|
||||
fixed=False).search(criterion='AICc')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_golden_fixed_AIC(self):
|
||||
bw1 = 76169.15
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=True).search(criterion='AIC')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_golden_adapt_AIC(self):
|
||||
bw1 = 50.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=False).search(criterion='AIC')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_golden_fixed_BIC(self):
|
||||
bw1 = 279451.43
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=True).search(criterion='BIC')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_golden_adapt_BIC(self):
|
||||
bw1 = 62.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=False).search(criterion='BIC')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_golden_fixed_CV(self):
|
||||
bw1 = 130406.67
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=True).search(criterion='CV')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_golden_adapt_CV(self):
|
||||
bw1 = 68.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=False).search(criterion='CV')
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_fixed_AICc(self):
|
||||
bw1 = 211025.0#211027.00
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='bisquare',
|
||||
fixed=True).search(criterion='AICc', search='interval', bw_min=211001.,
|
||||
bw_max=211035.0, interval=2)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_adapt_AICc(self):
|
||||
bw1 = 93.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='bisquare',
|
||||
fixed=False).search(criterion='AICc', search='interval',
|
||||
bw_min=90.0, bw_max=95.0, interval=1)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_fixed_AIC(self):
|
||||
bw1 = 76175.0#76169.00
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=True).search(criterion='AIC', search='interval',
|
||||
bw_min=76161.0, bw_max=76175.0, interval=1)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_adapt_AIC(self):
|
||||
bw1 = 40.0#50.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=False).search(criterion='AIC', search='interval', bw_min=40.0,
|
||||
bw_max=60.0, interval=2)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_fixed_BIC(self):
|
||||
bw1 = 279461.0#279451.00
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=True).search(criterion='BIC', search='interval', bw_min=279441.0,
|
||||
bw_max=279461.0, interval=2)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_adapt_BIC(self):
|
||||
bw1 = 62.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=False).search(criterion='BIC', search='interval',
|
||||
bw_min=52.0, bw_max=72.0, interval=2)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_fixed_CV(self):
|
||||
bw1 = 130400.0#130406.00
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=True).search(criterion='CV', search='interval', bw_min=130400.0,
|
||||
bw_max=130410.0, interval=1)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_interval_adapt_CV(self):
|
||||
bw1 = 62.0#68.0
|
||||
bw2 = Sel_BW(self.coords, self.y, self.X, kernel='gaussian',
|
||||
fixed=False).search(criterion='CV', search='interval', bw_min=60.0,
|
||||
bw_max=76.0 , interval=2)
|
||||
self.assertAlmostEqual(bw1, bw2)
|
||||
|
||||
def test_FBGWR_AIC(self):
|
||||
bw1 = [157.0, 65.0, 52.0]
|
||||
sel = Sel_BW(self.coords, self.y, self.X, fb=True, kernel='bisquare',
|
||||
constant=False)
|
||||
bw2 = sel.search(tol_fb=1e-03)
|
||||
np.testing.assert_allclose(bw1, bw2)
|
||||
np.testing.assert_allclose(sel.XB, self.XB, atol=1e-05)
|
||||
np.testing.assert_allclose(sel.err, self.err, atol=1e-05)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,202 @@
|
||||
"""
|
||||
Geographically weighted regression
|
||||
"""
|
||||
import numpy as np
|
||||
from gwr.base.gwr import GWR as PySAL_GWR
|
||||
from gwr.base.sel_bw import Sel_BW
|
||||
import json
|
||||
from crankshaft.analysis_data_provider import AnalysisDataProvider
|
||||
import plpy
|
||||
|
||||
|
||||
class GWR:
|
||||
def __init__(self, data_provider=None):
|
||||
if data_provider:
|
||||
self.data_provider = data_provider
|
||||
else:
|
||||
self.data_provider = AnalysisDataProvider()
|
||||
|
||||
def gwr(self, subquery, dep_var, ind_vars,
|
||||
bw=None, fixed=False, kernel='bisquare',
|
||||
geom_col='the_geom', id_col='cartodb_id'):
|
||||
"""
|
||||
subquery: 'select * from demographics'
|
||||
dep_var: 'pctbachelor'
|
||||
ind_vars: ['intercept', 'pctpov', 'pctrural', 'pctblack']
|
||||
bw: value of bandwidth, if None then select optimal
|
||||
fixed: False (kNN) or True ('distance')
|
||||
kernel: 'bisquare' (default), or 'exponential', 'gaussian'
|
||||
"""
|
||||
|
||||
params = {'geom_col': geom_col,
|
||||
'id_col': id_col,
|
||||
'subquery': subquery,
|
||||
'dep_var': dep_var,
|
||||
'ind_vars': ind_vars}
|
||||
|
||||
# get data from data provider
|
||||
query_result = self.data_provider.get_gwr(params)
|
||||
|
||||
# exit if data to analyze is empty
|
||||
if len(query_result) == 0:
|
||||
plpy.error('No data passed to analysis or independent variables '
|
||||
'are all null-valued')
|
||||
|
||||
# unique ids and variable names list
|
||||
rowid = np.array(query_result[0]['rowid'], dtype=np.int)
|
||||
|
||||
# x, y are centroids of input geometries
|
||||
x = np.array(query_result[0]['x'], dtype=np.float)
|
||||
y = np.array(query_result[0]['y'], dtype=np.float)
|
||||
coords = zip(x, y)
|
||||
|
||||
# extract dependent variable
|
||||
Y = np.array(query_result[0]['dep_var'], dtype=np.float).reshape((-1, 1))
|
||||
|
||||
n = Y.shape[0]
|
||||
k = len(ind_vars)
|
||||
X = np.zeros((n, k))
|
||||
|
||||
# extract query result
|
||||
for attr in range(0, k):
|
||||
attr_name = 'attr' + str(attr + 1)
|
||||
X[:, attr] = np.array(
|
||||
query_result[0][attr_name], dtype=np.float).flatten()
|
||||
|
||||
# add intercept variable name
|
||||
ind_vars.insert(0, 'intercept')
|
||||
|
||||
# calculate bandwidth if none is supplied
|
||||
if bw is None:
|
||||
bw = Sel_BW(coords, Y, X,
|
||||
fixed=fixed, kernel=kernel).search()
|
||||
model = PySAL_GWR(coords, Y, X, bw,
|
||||
fixed=fixed, kernel=kernel).fit()
|
||||
|
||||
# containers for outputs
|
||||
coeffs = []
|
||||
stand_errs = []
|
||||
t_vals = []
|
||||
filtered_t_vals = []
|
||||
|
||||
# extracted model information
|
||||
c_alpha = model.adj_alpha
|
||||
filtered_t = model.filter_tvals(c_alpha[1])
|
||||
predicted = model.predy.flatten()
|
||||
residuals = model.resid_response
|
||||
r_squared = model.localR2.flatten()
|
||||
bw = np.repeat(float(bw), n)
|
||||
|
||||
# create lists of json objs for model outputs
|
||||
for idx in xrange(n):
|
||||
coeffs.append(json.dumps({var: model.params[idx, k]
|
||||
for k, var in enumerate(ind_vars)}))
|
||||
stand_errs.append(json.dumps({var: model.bse[idx, k]
|
||||
for k, var in enumerate(ind_vars)}))
|
||||
t_vals.append(json.dumps({var: model.tvalues[idx, k]
|
||||
for k, var in enumerate(ind_vars)}))
|
||||
filtered_t_vals.append(
|
||||
json.dumps({var: filtered_t[idx, k]
|
||||
for k, var in enumerate(ind_vars)}))
|
||||
|
||||
return zip(coeffs, stand_errs, t_vals, filtered_t_vals,
|
||||
predicted, residuals, r_squared, bw, rowid)
|
||||
|
||||
def gwr_predict(self, subquery, dep_var, ind_vars,
|
||||
bw=None, fixed=False, kernel='bisquare',
|
||||
geom_col='the_geom', id_col='cartodb_id'):
|
||||
"""
|
||||
subquery: 'select * from demographics'
|
||||
dep_var: 'pctbachelor'
|
||||
ind_vars: ['intercept', 'pctpov', 'pctrural', 'pctblack']
|
||||
bw: value of bandwidth, if None then select optimal
|
||||
fixed: False (kNN) or True ('distance')
|
||||
kernel: 'bisquare' (default), or 'exponential', 'gaussian'
|
||||
"""
|
||||
|
||||
params = {'geom_col': geom_col,
|
||||
'id_col': id_col,
|
||||
'subquery': subquery,
|
||||
'dep_var': dep_var,
|
||||
'ind_vars': ind_vars}
|
||||
|
||||
# get data from data provider
|
||||
query_result = self.data_provider.get_gwr_predict(params)
|
||||
|
||||
# exit if data to analyze is empty
|
||||
if len(query_result) == 0:
|
||||
plpy.error('No data passed to analysis or independent variables '
|
||||
'are all null-valued')
|
||||
|
||||
# unique ids and variable names list
|
||||
rowid = np.array(query_result[0]['rowid'], dtype=np.int)
|
||||
|
||||
x = np.array(query_result[0]['x'], dtype=np.float)
|
||||
y = np.array(query_result[0]['y'], dtype=np.float)
|
||||
coords = np.array(zip(x, y), dtype=np.float)
|
||||
|
||||
# extract dependent variable
|
||||
Y = np.array(query_result[0]['dep_var']).reshape((-1, 1))
|
||||
|
||||
n = Y.shape[0]
|
||||
k = len(ind_vars)
|
||||
X = np.empty((n, k), dtype=np.float)
|
||||
|
||||
for attr in range(0, k):
|
||||
attr_name = 'attr' + str(attr + 1)
|
||||
X[:, attr] = np.array(
|
||||
query_result[0][attr_name], dtype=np.float).flatten()
|
||||
|
||||
# add intercept variable name
|
||||
ind_vars.insert(0, 'intercept')
|
||||
|
||||
# split data into "training" and "test" for predictions
|
||||
# create index to split based on null y values
|
||||
train = np.where(Y != np.array(None))[0]
|
||||
test = np.where(Y == np.array(None))[0]
|
||||
|
||||
# report error if there is no data to predict
|
||||
if len(test) < 1:
|
||||
plpy.error('No rows flagged for prediction: verify that rows '
|
||||
'denoting prediction locations have a dependent '
|
||||
'variable value of `null`')
|
||||
|
||||
# split dependent variable (only need training which is non-Null's)
|
||||
Y_train = Y[train].reshape((-1, 1))
|
||||
Y_train = Y_train.astype(np.float)
|
||||
|
||||
# split coords
|
||||
coords_train = coords[train]
|
||||
coords_test = coords[test]
|
||||
|
||||
# split explanatory variables
|
||||
X_train = X[train]
|
||||
X_test = X[test]
|
||||
|
||||
# calculate bandwidth if none is supplied
|
||||
if bw is None:
|
||||
bw = Sel_BW(coords_train, Y_train, X_train,
|
||||
fixed=fixed, kernel=kernel).search()
|
||||
|
||||
# estimate model and predict at new locations
|
||||
model = PySAL_GWR(coords_train, Y_train, X_train,
|
||||
bw, fixed=fixed,
|
||||
kernel=kernel).predict(coords_test, X_test)
|
||||
|
||||
coeffs = []
|
||||
stand_errs = []
|
||||
t_vals = []
|
||||
r_squared = model.localR2.flatten()
|
||||
predicted = model.predy.flatten()
|
||||
|
||||
m = len(model.predy)
|
||||
for idx in xrange(m):
|
||||
coeffs.append(json.dumps({var: model.params[idx, k]
|
||||
for k, var in enumerate(ind_vars)}))
|
||||
stand_errs.append(json.dumps({var: model.bse[idx, k]
|
||||
for k, var in enumerate(ind_vars)}))
|
||||
t_vals.append(json.dumps({var: model.tvalues[idx, k]
|
||||
for k, var in enumerate(ind_vars)}))
|
||||
|
||||
return zip(coeffs, stand_errs, t_vals,
|
||||
r_squared, predicted, rowid[test])
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,130 @@
|
||||
import unittest
|
||||
import json
|
||||
import numpy as np
|
||||
|
||||
|
||||
from crankshaft import random_seeds
|
||||
from helper import fixture_file
|
||||
from crankshaft.regression import GWR
|
||||
from crankshaft.analysis_data_provider import AnalysisDataProvider
|
||||
|
||||
|
||||
class FakeDataProvider(AnalysisDataProvider):
|
||||
def __init__(self, mocked_result):
|
||||
self.mocked_result = mocked_result
|
||||
|
||||
def get_gwr(self, params):
|
||||
return self.mocked_result
|
||||
|
||||
def get_gwr_predict(self, params):
|
||||
return self.mocked_result
|
||||
|
||||
|
||||
class GWRTest(unittest.TestCase):
|
||||
"""Testing class for geographically weighted regression (gwr)"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
fixture packed from canonical GWR georgia dataset using the
|
||||
following query:
|
||||
SELECT array_agg(x) As x,
|
||||
array_agg(y) As y,
|
||||
array_agg(pctbach) As dep_var,
|
||||
array_agg(pctrural) As attr1,
|
||||
array_agg(pctpov) As attr2,
|
||||
array_agg(pctblack) As attr3,
|
||||
array_agg(areakey) As rowid
|
||||
FROM g_utm
|
||||
WHERE pctbach is not NULL AND
|
||||
pctrural IS NOT NULL AND
|
||||
pctpov IS NOT NULL AND
|
||||
pctblack IS NOT NULL
|
||||
"""
|
||||
import copy
|
||||
# data packed from https://github.com/TaylorOshan/pysal/blob/1d6af33bda46b1d623f70912c56155064463383f/pysal/examples/georgia/GData_utm.csv
|
||||
self.data = json.loads(
|
||||
open(fixture_file('gwr_packed_data.json')).read())
|
||||
|
||||
# data packed from https://github.com/TaylorOshan/pysal/blob/a44c5541e2e0d10a99ff05edc1b7f81b70f5a82f/pysal/examples/georgia/georgia_BS_NN_listwise.csv
|
||||
self.knowns = json.loads(
|
||||
open(fixture_file('gwr_packed_knowns.json')).read())
|
||||
|
||||
# data for GWR prediction
|
||||
self.data_predict = copy.deepcopy(self.data)
|
||||
self.ids_of_unknowns = [13083, 13009, 13281, 13115, 13247, 13169]
|
||||
self.idx_ids_of_unknowns = [self.data_predict[0]['rowid'].index(idx)
|
||||
for idx in self.ids_of_unknowns]
|
||||
|
||||
for idx in self.idx_ids_of_unknowns:
|
||||
self.data_predict[0]['dep_var'][idx] = None
|
||||
|
||||
self.predicted_knowns = {13009: 10.879,
|
||||
13083: 4.5259,
|
||||
13115: 9.4022,
|
||||
13169: 6.0793,
|
||||
13247: 8.1608,
|
||||
13281: 13.886}
|
||||
|
||||
# params, with ind_vars in same ordering as query above
|
||||
self.params = {'subquery': 'select * from table',
|
||||
'dep_var': 'pctbach',
|
||||
'ind_vars': ['pctrural', 'pctpov', 'pctblack'],
|
||||
'bw': 90.000,
|
||||
'fixed': False,
|
||||
'geom_col': 'the_geom',
|
||||
'id_col': 'areakey'}
|
||||
|
||||
def test_gwr(self):
|
||||
"""
|
||||
"""
|
||||
gwr = GWR(FakeDataProvider(self.data))
|
||||
gwr_resp = gwr.gwr(self.params['subquery'],
|
||||
self.params['dep_var'],
|
||||
self.params['ind_vars'],
|
||||
bw=self.params['bw'],
|
||||
fixed=self.params['fixed'])
|
||||
|
||||
# unpack response
|
||||
coeffs, stand_errs, t_vals, t_vals_filtered, predicteds, \
|
||||
residuals, r_squareds, bws, rowids = zip(*gwr_resp)
|
||||
|
||||
# prepare for comparision
|
||||
coeff_known_pctpov = self.knowns['est_pctpov']
|
||||
tval_known_pctblack = self.knowns['t_pctrural']
|
||||
pctpov_se = self.knowns['se_pctpov']
|
||||
ids = self.knowns['area_key']
|
||||
resp_idx = None
|
||||
|
||||
# test pctpov coefficient estimates
|
||||
for idx, val in enumerate(coeff_known_pctpov):
|
||||
resp_idx = rowids.index(ids[idx])
|
||||
self.assertAlmostEquals(val,
|
||||
json.loads(coeffs[resp_idx])['pctpov'],
|
||||
places=4)
|
||||
# test pctrural tvals
|
||||
for idx, val in enumerate(tval_known_pctblack):
|
||||
resp_idx = rowids.index(ids[idx])
|
||||
self.assertAlmostEquals(val,
|
||||
json.loads(t_vals[resp_idx])['pctrural'],
|
||||
places=4)
|
||||
|
||||
def test_gwr_predict(self):
|
||||
"""Testing for GWR_Predict"""
|
||||
gwr = GWR(FakeDataProvider(self.data_predict))
|
||||
gwr_resp = gwr.gwr_predict(self.params['subquery'],
|
||||
self.params['dep_var'],
|
||||
self.params['ind_vars'],
|
||||
bw=self.params['bw'],
|
||||
fixed=self.params['fixed'])
|
||||
|
||||
# unpack response
|
||||
coeffs, stand_errs, t_vals, \
|
||||
r_squareds, predicteds, rowid = zip(*gwr_resp)
|
||||
threshold = 0.01
|
||||
|
||||
for i, idx in enumerate(self.idx_ids_of_unknowns):
|
||||
|
||||
known_val = self.predicted_knowns[rowid[i]]
|
||||
predicted_val = predicteds[i]
|
||||
test_val = abs(known_val - predicted_val) / known_val
|
||||
self.assertTrue(test_val < threshold)
|
||||
Reference in New Issue
Block a user