spatial_stats 1.0.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e79499aff738642d7e50a0255239de6627e68b3e1553f8aa6fa21364c3b5acb
4
- data.tar.gz: 26a98ee5cb279af10e2cc324663e06ddfc7217eb6a6adc3d4052cc6469b5b6be
3
+ metadata.gz: 6d7d2e6e57d8059f55f1bb9128f670ae02da382005a80111410a4c72c69ce04b
4
+ data.tar.gz: df3018cdf87fd2d5d19cb788855252497466bfd383cb13a078c8f91693a4b2c7
5
5
  SHA512:
6
- metadata.gz: a184a7e6561ec950ecc97e08840c8e88ba7bb20567d140036c34e0552a0e11a339885094fa5380e59f1a7ebe4eee0cb371368e6a7384531c7704e9894c8c1948
7
- data.tar.gz: cd971928ff328e8daca3b0176b01903bdc98d7fcf1109cdbf9937dd84ff737d2d8072b7437e21dc0c2f26c73738c7c7f30c9a7bdca30b5cfd655ef5f3f760df1
6
+ metadata.gz: e95cf8d912d4f6a606871f8f78484157f2aa234ce500f343ec0a7a722b6b470c6e89f733d6e103d27f2d9bd133882aa22af88a0ff67fc62b1358c6df38b7dab5
7
+ data.tar.gz: 53738b1d1cdc77a840eea583baaa26a77f3b50ab8b540822f3da20b8c88801de2666a22944d244b2bd896b3edae0b2d49ea068c1f6507ba38c4170cefa2a42cb
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
+ ![Spatial Stats](/assets/ruby.svg)
2
+
1
3
  [![Build Status](https://travis-ci.com/keithdoggett/spatial_stats.svg?branch=master)](https://travis-ci.com/keithdoggett/spatial_stats)
2
4
 
3
- ![Spatial Stats](/assets/ruby.svg)
5
+ [Docs](https://keithdoggett.github.io/spatial_stats)
4
6
 
5
7
  # SpatialStats
6
8
 
7
- SpatialStats is an ActiveRecord plugin that utilizes PostGIS and Ruby to compute weights/statistics of spatial data sets in Rails Apps.
9
+ SpatialStats is an ActiveRecord/Rails plugin that utilizes PostGIS to compute weights/statistics of spatial data sets in Rails Apps.
8
10
 
9
11
  ## Installation
10
12
 
@@ -327,7 +329,9 @@ Summaries of milestones for v1.x and v2.0. These lists are subject to change. If
327
329
  - Add support for .gal/.swm file imports
328
330
  - Add support for Rate variables
329
331
  - Add support for Bayes smoothing
332
+ - ~Add support for Bonferroni Bounds and FDR~
330
333
  4. General
334
+ - ~Add new stat constructors that only rely on a weights matrix and data vector~
331
335
  - Point Pattern Analysis Module
332
336
  - Regression Module
333
337
 
@@ -336,6 +340,11 @@ Summaries of milestones for v1.x and v2.0. These lists are subject to change. If
336
340
  - Break gem into core `spatial_stats` that will not include queries module and `spatial_stats-activerecord`. This will remove the dependency on rails for the core gem.
337
341
  - Create `spatial_stats-import/geojson/shp` gem that will allow importing files and generating a `WeightsMatrix`. Will likely rely on `RGeo` or another spatial lib.
338
342
 
343
+ ### Other TODOs
344
+
345
+ - Update Docs to show `from_observation` when version is bumped
346
+ - Refactor `MultivariateGeary` so that it can be used without `activerecord` by adding `from_observations` and supporting methods.
347
+
339
348
  ## License
340
349
 
341
350
  The gem is available as open source under the terms of the [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause).
@@ -22,9 +22,17 @@ size_t csr_matrix_memsize(const void *ptr)
22
22
  return sizeof(*csr);
23
23
  }
24
24
 
25
+ const rb_data_type_t csr_matrix_type = {
26
+ "SpatialStats::Weights::CSRMatrix",
27
+ {NULL, csr_matrix_free, csr_matrix_memsize},
28
+ 0,
29
+ 0,
30
+ RUBY_TYPED_FREE_IMMEDIATELY
31
+ };
32
+
25
33
  VALUE csr_matrix_alloc(VALUE self)
26
34
  {
27
- csr_matrix *csr = malloc(sizeof(csr_matrix));
35
+ csr_matrix *csr = ALLOC(csr_matrix);
28
36
  return TypedData_Wrap_Struct(self, &csr_matrix_type, csr);
29
37
  }
30
38
 
@@ -64,7 +72,7 @@ void mat_to_sparse(csr_matrix *csr, VALUE data, VALUE keys, VALUE num_rows)
64
72
  // if it is, add array len to nnz
65
73
  row = rb_hash_aref(data, key);
66
74
  Check_Type(row, T_ARRAY);
67
- nnz += rb_array_len(row);
75
+ nnz += (int)RARRAY_LEN(row); // Explicit cast to int
68
76
  }
69
77
 
70
78
  values = malloc(sizeof(double) * nnz);
@@ -82,7 +90,7 @@ void mat_to_sparse(csr_matrix *csr, VALUE data, VALUE keys, VALUE num_rows)
82
90
 
83
91
  key = rb_ary_entry(keys, i);
84
92
  row = rb_hash_aref(data, key);
85
- m = rb_array_len(row);
93
+ m = (int)RARRAY_LEN(row); // Explicit cast to int
86
94
 
87
95
  for (j = 0; j < m; j++)
88
96
  {
@@ -140,7 +148,7 @@ VALUE csr_matrix_initialize(VALUE self, VALUE data, VALUE num_rows)
140
148
  keys = rb_funcall(data, rb_intern("keys"), 0);
141
149
 
142
150
  // check dimensions are correct
143
- if (NUM2INT(num_rows) != rb_array_len(keys))
151
+ if (NUM2INT(num_rows) != (int)RARRAY_LEN(keys)) // Explicit cast to int
144
152
  {
145
153
  rb_raise(rb_eArgError, "n_rows != keys.size, check your dimensions");
146
154
  }
@@ -249,7 +257,7 @@ VALUE csr_matrix_mulvec(VALUE self, VALUE vec)
249
257
 
250
258
  TypedData_Get_Struct(self, csr_matrix, &csr_matrix_type, csr);
251
259
 
252
- if (rb_array_len(vec) != csr->n)
260
+ if (RARRAY_LEN(vec) != csr->n)
253
261
  {
254
262
  rb_raise(rb_eArgError, "Dimension Mismatch CSRMatrix.n != vec.size");
255
263
  }
@@ -294,7 +302,7 @@ VALUE csr_matrix_dot_row(VALUE self, VALUE vec, VALUE row)
294
302
 
295
303
  TypedData_Get_Struct(self, csr_matrix, &csr_matrix_type, csr);
296
304
 
297
- if (rb_array_len(vec) != csr->n)
305
+ if (RARRAY_LEN(vec) != csr->n)
298
306
  {
299
307
  rb_raise(rb_eArgError, "Dimension Mismatch CSRMatrix.n != vec.size");
300
308
  }
@@ -14,13 +14,7 @@ typedef struct csr_matrix
14
14
  void csr_matrix_free(void *mat);
15
15
  size_t csr_matrix_memsize(const void *ptr);
16
16
 
17
- // ruby VALUE for csr_matrix
18
- static const rb_data_type_t csr_matrix_type = {
19
- "SpatialStats::Weights::CSRMatrix",
20
- {NULL, csr_matrix_free, csr_matrix_memsize},
21
- 0,
22
- 0,
23
- RUBY_TYPED_FREE_IMMEDIATELY};
17
+ extern const rb_data_type_t csr_matrix_type;
24
18
 
25
19
  void mat_to_sparse(csr_matrix *csr, VALUE data, VALUE keys, VALUE num_rows);
26
20
  VALUE csr_matrix_alloc(VALUE self);
@@ -15,7 +15,7 @@ void Init_spatial_stats()
15
15
  {
16
16
  VALUE spatial_stats_mod = rb_define_module("SpatialStats");
17
17
  VALUE weights_mod = rb_define_module_under(spatial_stats_mod, "Weights");
18
- VALUE csr_matrix_class = rb_define_class_under(weights_mod, "CSRMatrix", rb_cData);
18
+ VALUE csr_matrix_class = rb_define_class_under(weights_mod, "CSRMatrix", rb_cObject);
19
19
 
20
20
  rb_define_alloc_func(csr_matrix_class, csr_matrix_alloc);
21
21
  rb_define_method(csr_matrix_class, "initialize", csr_matrix_initialize, 2);
@@ -22,6 +22,23 @@ module SpatialStats
22
22
  @weights = weights.standardize
23
23
  end
24
24
 
25
+ ##
26
+ # A new instance of BivariateMoran, from vector and weights.
27
+ #
28
+ # @param [Array] x observations of dataset
29
+ # @param [WeightsMatrix] weights to define relationships between observations
30
+ #
31
+ # @return [BivariateMoran]
32
+ def self.from_observations(x, y, weights)
33
+ n = weights.n
34
+ raise ArgumentError, 'Data size != weights.n' if x.size != n || y.size != n
35
+
36
+ instance = new(nil, nil, nil, weights.standardize)
37
+ instance.x = x
38
+ instance.y = y
39
+ instance
40
+ end
41
+
25
42
  ##
26
43
  # Computes the global spatial correlation of x against spatially lagged
27
44
  # y.
@@ -15,6 +15,21 @@ module SpatialStats
15
15
  end
16
16
  attr_accessor :scope, :field, :weights
17
17
 
18
+ ##
19
+ # A new instance of Stat, from vector and weights.
20
+ #
21
+ # @param [Array] x observations of dataset
22
+ # @param [WeightsMatrix] weights to define relationships between observations
23
+ #
24
+ # @return [Stat]
25
+ def self.from_observations(x, weights)
26
+ raise ArgumentError, 'Data size != weights.n' if x.size != weights.n
27
+
28
+ instance = new(nil, nil, weights.standardize)
29
+ instance.x = x
30
+ instance
31
+ end
32
+
18
33
  def stat
19
34
  raise NotImplementedError, 'method stat not defined'
20
35
  end
@@ -23,6 +23,24 @@ module SpatialStats
23
23
  end
24
24
  attr_accessor :scope, :x_field, :y_field, :weights
25
25
 
26
+ ##
27
+ # A new instance of BivariateMoran, from vector and weights.
28
+ #
29
+ # @param [Array] x observations of dataset
30
+ # @param [Array] y observations of dataset
31
+ # @param [WeightsMatrix] weights to define relationships between observations
32
+ #
33
+ # @return [BivariateMoran]
34
+ def self.from_observations(x, y, weights)
35
+ n = weights.n
36
+ raise ArgumentError, 'Data size != weights.n' if x.size != n || y.size != n
37
+
38
+ instance = new(nil, nil, nil, weights.standardize)
39
+ instance.x = x
40
+ instance.y = y
41
+ instance
42
+ end
43
+
26
44
  ##
27
45
  # Computes the local indicator of spatial correlation for
28
46
  # x against lagged y.
@@ -16,6 +16,21 @@ module SpatialStats
16
16
  end
17
17
  attr_accessor :scope, :field, :weights
18
18
 
19
+ ##
20
+ # A new instance of Stat, from vector and weights.
21
+ #
22
+ # @param [Array] x observations of dataset
23
+ # @param [WeightsMatrix] weights to define relationships between observations
24
+ #
25
+ # @return [Stat]
26
+ def self.from_observations(x, weights)
27
+ raise ArgumentError, 'Data size != weights.n' if x.size != weights.n
28
+
29
+ instance = new(nil, nil, weights.standardize)
30
+ instance.x = x
31
+ instance
32
+ end
33
+
19
34
  def stat
20
35
  raise NotImplementedError, 'method stat not defined'
21
36
  end
Binary file
@@ -6,5 +6,30 @@ module SpatialStats
6
6
  ##
7
7
  # The Utils module contains various utilities used in the gem.
8
8
  module Utils
9
+ ##
10
+ # Compute the false discovery rate (FDR) of a set of p-values given
11
+ # an alpha value.
12
+ #
13
+ # If there is no FDR available in the dataset, the Bonferroni Bound is
14
+ # returned instead.
15
+ #
16
+ # @param [Array] pvals from an mc test
17
+ # @param [Float] alpha value for the fdr
18
+ #
19
+ # @returns [Float] either the FDR or Bonferroni Bound
20
+ def self.fdr(pvals, alpha)
21
+ n = pvals.size
22
+ b_bound = alpha / n
23
+ pvals.sort!
24
+
25
+ p_val = b_bound
26
+ (0..n - 1).each do |i|
27
+ p_fdr = (i + 1) * b_bound
28
+ break unless pvals[i] <= p_fdr
29
+
30
+ p_val = p_fdr
31
+ end
32
+ p_val
33
+ end
9
34
  end
10
35
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SpatialStats
4
- VERSION = '1.0.3'
4
+ VERSION = '2.0.0'
5
5
  end
@@ -21,6 +21,16 @@ module SpatialStats
21
21
  end
22
22
  attr_accessor :keys, :weights, :n
23
23
 
24
+ ##
25
+ # Equality operator
26
+ #
27
+ # @param [WeightsMatrix] other WeightsMatrix
28
+ #
29
+ # @return [TrueClass, FalseClass] equality result
30
+ def ==(other)
31
+ weights == other.weights
32
+ end
33
+
24
34
  ##
25
35
  # Compute the n x n Numo::Narray of the weights hash.
26
36
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spatial_stats
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keith Doggett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-22 00:00:00.000000000 Z
11
+ date: 2024-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -28,28 +28,28 @@ dependencies:
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 6.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 6.0.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activerecord-postgis-adapter
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: 6.0.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 6.0.0
55
55
  - !ruby/object:Gem::Dependency
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 1.8.3
61
+ version: 2.0.2
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 1.8.3
68
+ version: 2.0.2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pg
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -112,14 +112,14 @@ dependencies:
112
112
  name: tzinfo
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: 1.2.6
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: 1.2.6
125
125
  description: An ActiveRecord/PostGIS extension that provides statistical methods to
@@ -182,14 +182,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
182
182
  requirements:
183
183
  - - ">="
184
184
  - !ruby/object:Gem::Version
185
- version: 2.3.0
185
+ version: 3.1.0
186
186
  required_rubygems_version: !ruby/object:Gem::Requirement
187
187
  requirements:
188
188
  - - ">="
189
189
  - !ruby/object:Gem::Version
190
190
  version: '0'
191
191
  requirements: []
192
- rubygems_version: 3.0.3
192
+ rubygems_version: 3.5.3
193
193
  signing_key:
194
194
  specification_version: 4
195
195
  summary: An ActiveRecord/PostGIS extension that provides statistical methods to spatial