loganb-kder 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/kder/bandwidth.rb +13 -0
- data/lib/kder/kde.rb +86 -0
- data/lib/kder/version.rb +3 -0
- data/lib/kder.rb +1 -0
- data/lib/util/enum_extensions.rb +19 -0
- data/lib/util/statistics.rb +10 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cde53f25f8badc44aef6aaf29bcb0d255940fd73
|
4
|
+
data.tar.gz: 3568e1d009ba8bc7fac4a610a3d0882349818bbd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b44e25490f96342d66f9c70ba8e3386372380dc086e5beda9ad0f0e6784b095b9f50042ef28442a2e14f7b5427737527aa7336269c3945df5079e41f594b8137
|
7
|
+
data.tar.gz: 112de7099a77c778a60d25468abf1890c7990db6f086771aa80b7cd4206b3313c397f948d8f1f92526460e9695d998e07f304173df509a359da32352e3a272ad
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../util/enum_extensions'
|
2
|
+
module Bandwidth
|
3
|
+
class << self
|
4
|
+
def silverman(input_arr, std_deviation = input_arr.standard_deviation)
|
5
|
+
bandwidth = ((4 * std_deviation ** 5)/(3 * input_arr.size))**(1.0/5)
|
6
|
+
end
|
7
|
+
alias_method :estimate, :silverman
|
8
|
+
alias_method :nrd0, :silverman
|
9
|
+
|
10
|
+
#def mean_integrated_squared_error(a,b,c,d)
|
11
|
+
#end
|
12
|
+
end
|
13
|
+
end
|
data/lib/kder/kde.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
class Kder
|
4
|
+
require_relative 'bandwidth'
|
5
|
+
require_relative '../util/statistics'
|
6
|
+
|
7
|
+
Sigmas = 2.5
|
8
|
+
MeshCount = 2e3
|
9
|
+
MinimumThresholdValue = 1e-2
|
10
|
+
MinimumStepSize = 1e-3
|
11
|
+
DifferenceThreshold = 1e-3
|
12
|
+
class << self
|
13
|
+
##
|
14
|
+
# :singleton-method: kde
|
15
|
+
# Accepts a single member array plus optional additional information
|
16
|
+
# Returns a two member array, [x_vals,y_vals] representing the kde
|
17
|
+
def kde(arr, bw = nil, opts = {sigmas: Sigmas, sampling_density: MeshCount, threshold: MinimumThresholdValue, minimum_delta: DifferenceThreshold})
|
18
|
+
unless bw # is nil
|
19
|
+
bw = Bandwidth.silverman(arr)
|
20
|
+
end
|
21
|
+
bw = bw == 0 ? 0.1 : bw
|
22
|
+
# Initialization steps
|
23
|
+
range = bw*opts[:sigmas]
|
24
|
+
min = arr.min - range
|
25
|
+
max = arr.max + range
|
26
|
+
step_size = (max-min)/(opts[:sampling_density].to_f)
|
27
|
+
step_size = step_size < MinimumStepSize ? MinimumStepSize : step_size
|
28
|
+
arr.sort!
|
29
|
+
# initialize the range variables
|
30
|
+
ranges = (min..max).step(step_size).to_a
|
31
|
+
output = [[min,0]]
|
32
|
+
old_intensity = 0
|
33
|
+
# Step through the range
|
34
|
+
ranges[1..-1].map.with_index do |mid, i|
|
35
|
+
high_end = mid + range
|
36
|
+
lower_end = mid - range
|
37
|
+
selection_range = (lower_end..high_end)
|
38
|
+
included = arr.select {|a| selection_range.include?(a)}
|
39
|
+
intensity = included.map {|a| Kder::Statistics.custom_pdf(a-mid, bw) }.inject(:+) || 0
|
40
|
+
unless intensity < opts[:threshold] or (intensity - old_intensity).abs < opts[:minimum_delta]
|
41
|
+
output << [mid, intensity ]
|
42
|
+
old_intensity = intensity
|
43
|
+
end
|
44
|
+
end
|
45
|
+
output << [max,0]
|
46
|
+
output.compact.transpose
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# :singleton-method: kdevec
|
51
|
+
# Works just like kdevec, but arr is a list of 2-D points of sample value and magnitude. Is this valid math? ¯\_(ツ)_/¯
|
52
|
+
#
|
53
|
+
def kdevec(arr, bw = nil, opts = {}.freeze)
|
54
|
+
opts = {sigmas: Sigmas, sampling_density: MeshCount, threshold: MinimumThresholdValue, minimum_delta: DifferenceThreshold}.merge(opts)
|
55
|
+
raise "bandwidth must be specified for now" unless bw
|
56
|
+
|
57
|
+
values = arr.sort_by { |v| v[0] }
|
58
|
+
|
59
|
+
# Initialization steps
|
60
|
+
range = bw*opts[:sigmas]
|
61
|
+
min = values.first[0] - range
|
62
|
+
max = values.last[0] + range
|
63
|
+
step_size = (max-min)/(opts[:sampling_density].to_f)
|
64
|
+
step_size = step_size < MinimumStepSize ? MinimumStepSize : step_size
|
65
|
+
|
66
|
+
# initialize the range variables
|
67
|
+
ranges = (min..max).step(step_size).to_a
|
68
|
+
output = [[min,0]]
|
69
|
+
old_intensity = 0
|
70
|
+
# Step through the range
|
71
|
+
ranges[1..-1].map.with_index do |mid, i|
|
72
|
+
high_end = mid + range
|
73
|
+
lower_end = mid - range
|
74
|
+
selection_range = (lower_end..high_end)
|
75
|
+
included = values.select {|v| selection_range.include?(v[0])}
|
76
|
+
intensity = included.map {|v| v[1] * Kder::Statistics.custom_pdf(v[0]-mid, bw) }.inject(:+) || 0
|
77
|
+
unless intensity < opts[:threshold] or (intensity - old_intensity).abs < opts[:minimum_delta]
|
78
|
+
output << [mid, intensity ]
|
79
|
+
old_intensity = intensity
|
80
|
+
end
|
81
|
+
end
|
82
|
+
output << [max,0]
|
83
|
+
output.compact.transpose
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/kder/version.rb
ADDED
data/lib/kder.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'kder/kde'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Enumerable
|
2
|
+
# Thanks StackOverflow users!
|
3
|
+
# http://stackoverflow.com/questions/7749568/how-can-i-do-standard-deviation-in-ruby
|
4
|
+
def sum
|
5
|
+
self.inject(:+)
|
6
|
+
end
|
7
|
+
def mean
|
8
|
+
self.sum/self.length.to_f
|
9
|
+
end
|
10
|
+
alias average mean
|
11
|
+
def sample_variance
|
12
|
+
m = self.mean
|
13
|
+
sum = self.inject(0){|accum, i| accum + (i-m)**2}
|
14
|
+
sum/(self.length - 1).to_f
|
15
|
+
end
|
16
|
+
def standard_deviation
|
17
|
+
Math.sqrt(self.sample_variance)
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: loganb-kder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Taylor
|
8
|
+
- Logan Bowers
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2017-11-15 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A KDE implementation in Ruby.
|
15
|
+
email:
|
16
|
+
- ryanmt@byu.net
|
17
|
+
- logan@datacurrent.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/kder.rb
|
23
|
+
- lib/kder/bandwidth.rb
|
24
|
+
- lib/kder/kde.rb
|
25
|
+
- lib/kder/version.rb
|
26
|
+
- lib/util/enum_extensions.rb
|
27
|
+
- lib/util/statistics.rb
|
28
|
+
homepage: https://github.com/loganb/KDER
|
29
|
+
licenses: []
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.5.2
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: Kernel Density Estimation, and an associated bandwidth estimator, rudimentary
|
51
|
+
at best, but a decent first approximation for backend preparing of KDE plots for
|
52
|
+
plotting in JS libraries, or for whatever you would like to use it.
|
53
|
+
test_files: []
|