time-series 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 578adee8d18e4e1b562993e5e5f23e3559428b62
4
+ data.tar.gz: 5df89148bb67007fccd86f0d973cfe10cadb1711
5
+ SHA512:
6
+ metadata.gz: 4a5aaca0c7de2c0455c8da001f764280198375e2da18676763450593acb878ae2f0185db6d43193b7f74c01cadb164aec83956db4649f1679ebe0fe6d73b57d6
7
+ data.tar.gz: e8962857d566436ec59aca2c38bbfef3391a0d3cb140f8cea4d0ea8f89eafdcb1ecc1fa83fae55b9fad868b3ad1e9b2d54c47fbec26b038daf74fec94cbb56cd
data/.gitignore ADDED
@@ -0,0 +1,29 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Documentation cache and generated files:
13
+ /.yardoc/
14
+ /_yardoc/
15
+ /doc/
16
+ /rdoc/
17
+
18
+ ## Environment normalisation:
19
+ /.bundle/
20
+ /lib/bundler/man/
21
+
22
+ # for a library or gem, you might want to ignore these files since the code is
23
+ # intended to run in multiple environments; otherwise, check them in:
24
+ Gemfile.lock
25
+ .ruby-version
26
+ .ruby-gemset
27
+
28
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
29
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Eric L. Yan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # time-series
2
+
3
+ This library provides a basic data structure that can represent time series data. It is originally designed for the representation of stock market data, but it is suitable (and extensible) for other purposes.
4
+
5
+ It keeps data points in a Hash and requires Ruby version >= 1.9.2, as it turns out in Ruby 1.9, a Hash is also a [doubly-circular linked list](http://www.igvita.com/2009/02/04/ruby-19-internals-ordered-hash/).
@@ -0,0 +1,2 @@
1
+ require 'time_series/time_series'
2
+ require 'time_series/data_point'
@@ -0,0 +1,18 @@
1
+ class DataPoint
2
+ include Comparable
3
+
4
+ attr_reader :timestamp, :data
5
+
6
+ def initialize(timestamp, data)
7
+ timestamp = timestamp.to_time unless timestamp.kind_of? Time
8
+ @timestamp, @data = timestamp, data
9
+ end
10
+
11
+ def <=>(another)
12
+ result = @timestamp <=> another.timestamp
13
+ end
14
+
15
+ def ==(another)
16
+ @timestamp == another.timestamp and @data == another.data
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ class TimeSeries
2
+ include Enumerable
3
+
4
+ attr_reader :data_points
5
+
6
+ def initialize(*args)
7
+ case args.length
8
+ when 1 then data_points = args[0]
9
+ when 2 then data_points = args[0].zip(args[1]).collect { |dp| DataPoint.new(dp[0], dp[1]) }
10
+ else data_points = []
11
+ end
12
+
13
+ @data_points = {}
14
+ self << data_points
15
+ end
16
+
17
+ def <<(*data_points)
18
+ data_points.flatten.each do |data_point|
19
+ @data_points[data_point.timestamp] = data_point
20
+ end
21
+ end
22
+
23
+ def at(*timestamps)
24
+ results = @data_points.values_at(*timestamps)
25
+ results = results[0] if results.length == 1
26
+
27
+ return results
28
+ end
29
+
30
+ def slice(timeframe)
31
+ from, to = timeframe[:from], timeframe[:to]
32
+
33
+ data_points = @data_points.select do |t, data|
34
+ case [!from.nil?, !to.nil?]
35
+ when [true, true] then t >= from and t <= to
36
+ when [true, false] then t >= from
37
+ when [false, true] then t <= to
38
+ end
39
+ end
40
+
41
+ return self.class.new data_points.keys, data_points.values
42
+ end
43
+
44
+ def each(&block)
45
+ Hash[@data_points.sort].values.each(&block)
46
+ end
47
+
48
+ def last(n = 1)
49
+ Hash[@data_points.sort.last(n)].values
50
+ end
51
+
52
+ def length
53
+ @data_points.length
54
+ end
55
+
56
+ def to_a
57
+ Hash[@data_points.sort].values
58
+ end
59
+ end
@@ -0,0 +1 @@
1
+ require 'time_series'
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'date'
3
+
4
+ describe DataPoint do
5
+ let(:data) { { a: 1, b:2, c:3 } }
6
+
7
+ describe "#new" do
8
+ it "takes a Time object" do
9
+ data_point = DataPoint.new(Time.new, data)
10
+ data_point.timestamp.should be_a_kind_of Time
11
+ data_point.data.should eql data
12
+ end
13
+
14
+ it "takes a Date object" do
15
+ data_point = DataPoint.new(Date.today, data)
16
+ data_point.timestamp.should be_a_kind_of Time
17
+ data_point.data.should eql data
18
+ end
19
+ end
20
+
21
+ describe "is comparable" do
22
+ it "Two DataPoints are equal given the same timestamp and data" do
23
+ one = DataPoint.new(Time.at(1000000000), "The first UNIX billennium".gsub('UNIX', 'Unix'))
24
+ another = DataPoint.new(Time.new(2001, 9, 9, 9, 46, 40, '+08:00'), "The first Unix billennium")
25
+ one.should eq another
26
+ end
27
+
28
+ it "DataPoints are compared by its timestamp" do
29
+ first = DataPoint.new(Time.at(1000000000), "The first Unix billennium")
30
+ second = DataPoint.new(Time.at(2000000000), "The second Unix billennium")
31
+ first.should < second
32
+ second.should > first
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe TimeSeries do
4
+ let(:data_points) do
5
+ data_points = {
6
+ Time.at(2000000000) => "The second Unix billennium",
7
+ Time.at(1234567890) => "Let's go party",
8
+ Time.at(1000000000) => "The first Unix billennium",
9
+ Time.at(2147485547) => "Year 2038 problem"
10
+ }
11
+ data_points.keys.zip(data_points.values).collect { |dp| DataPoint.new(dp[0], dp[1]) }
12
+ end
13
+ let(:time_series) { TimeSeries.new(data_points) }
14
+
15
+ describe "#new" do
16
+ it "takes a array of DataPoints" do
17
+ time_series.length.should eql 4
18
+ end
19
+
20
+ it "takes a array of timestamps and a array of data" do
21
+ data_points = time_series.data_points
22
+ time_series = TimeSeries.new(data_points.keys, data_points.values)
23
+ time_series.length.should eql 4
24
+ end
25
+ end
26
+
27
+ describe "#<<" do
28
+ it "adds a new data point" do
29
+ time_series << DataPoint.new(Time.now, "Knock knock")
30
+ time_series.length.should eql 5
31
+ end
32
+
33
+ it "update the existing data point" do
34
+ time_series << DataPoint.new(Time.at(1234567890), 'PARTY TIME!')
35
+ time_series.length.should eql 4
36
+ time_series.at(Time.at(1234567890)).data.should eql 'PARTY TIME!'
37
+ end
38
+ end
39
+
40
+ describe "#at" do
41
+ it "returns data associated with the given timestamp" do
42
+ time_series.at(Time.at(1000000000)).data.should eql "The first Unix billennium"
43
+ end
44
+
45
+ it "returns data in array if two or more timestamps are given" do
46
+ time_series.at(Time.at(1000000000), Time.at(2000000000))
47
+ .collect { |data_point| data_point.data }.should
48
+ eql(["The first Unix billennium", "The second Unix billennium"])
49
+ end
50
+ end
51
+
52
+ describe "#slice" do
53
+ it "returns all data points in the given timeframe" do
54
+ ts = time_series.slice from: Time.at(1000000000), to: Time.at(2000000000)
55
+ ts.length.should eql 3
56
+ ts.at(Time.at 2147485547).should eql nil
57
+ end
58
+
59
+ it "returns all data points after the from time" do
60
+ ts = time_series.slice from: Time.at(2000000000)
61
+ ts.length.should eql 2
62
+ ts.at(Time.at(1000000000), Time.at(1234567890)).should eql [nil, nil]
63
+ end
64
+
65
+ it "returns all data points before the to time" do
66
+ ts = time_series.slice to: Time.at(1234567890)
67
+ ts.length.should eql 2
68
+ ts.at(Time.at(2000000000), Time.at(2147485547)).should eql [nil, nil]
69
+ end
70
+ end
71
+
72
+ describe "is enumerable" do
73
+ it "returns the first data point(s) according to its timestamp" do
74
+ time_series.first(2).collect { |data_point| data_point.data }.should
75
+ eql ["The first Unix billennium", "Let's go party"]
76
+ end
77
+
78
+ it "returns the last data point(s) according to its timestamp" do
79
+ time_series.last(2).collect { |data_point| data_point.data }.should
80
+ eql ["The second Unix billennium", "Year 2038 problem"]
81
+ end
82
+ end
83
+
84
+ describe "#to_a" do
85
+ it "returns a array of sorted DataPoints" do
86
+ time_series.to_a.should be_a_kind_of Array
87
+ time_series.to_a.should eql data_points.sort
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'time-series'
3
+ spec.version = '0.0.0'
4
+ spec.author = 'Eric Yan'
5
+ spec.email = 'long@ericyan.me'
6
+ spec.homepage = 'https://github.com/ericyan/time-series'
7
+ spec.summary = 'A Ruby library for dealing with time series data'
8
+ spec.description = 'This library provides a basic data structure that can represent time series data. Requires Ruby version >= 1.9.2.'
9
+ spec.license = 'MIT'
10
+
11
+ # Starting 1.9.2 hash insert order will be preserved
12
+ spec.required_ruby_version = '>= 1.9.2'
13
+
14
+ spec.add_development_dependency 'rspec'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.test_files = spec.files.grep(%r{^spec/})
18
+
19
+ spec.require_paths = ["lib"]
20
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time-series
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Yan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: This library provides a basic data structure that can represent time
28
+ series data. Requires Ruby version >= 1.9.2.
29
+ email: long@ericyan.me
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - LICENSE
37
+ - README.md
38
+ - lib/time_series.rb
39
+ - lib/time_series/data_point.rb
40
+ - lib/time_series/time_series.rb
41
+ - spec/spec_helper.rb
42
+ - spec/time_series/data_point_spec.rb
43
+ - spec/time_series/time_series_spec.rb
44
+ - time_series.gemspec
45
+ homepage: https://github.com/ericyan/time-series
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - '>='
56
+ - !ruby/object:Gem::Version
57
+ version: 1.9.2
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 2.0.3
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: A Ruby library for dealing with time series data
69
+ test_files:
70
+ - spec/spec_helper.rb
71
+ - spec/time_series/data_point_spec.rb
72
+ - spec/time_series/time_series_spec.rb