charty 0.1.5.dev → 0.2.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.
@@ -0,0 +1,55 @@
1
+ module Charty
2
+ module TableAdapters
3
+ class ActiveRecordAdapter
4
+ TableAdapters.register(:active_record, self)
5
+
6
+ include Enumerable
7
+
8
+ def self.supported?(data)
9
+ defined?(ActiveRecord::Relation) && data.is_a?(ActiveRecord::Relation)
10
+ end
11
+
12
+ def initialize(data)
13
+ @data = check_type(ActiveRecord::Relation, data, :data)
14
+ @column_names = @data.column_names.freeze
15
+ @columns = nil
16
+ end
17
+
18
+ attr_reader :column_names
19
+
20
+ def [](row, column)
21
+ fetch_records unless @columns
22
+ if row
23
+ @columns[resolve_column_index(column)][row]
24
+ else
25
+ @columns[resolve_column_index(column)]
26
+ end
27
+ end
28
+
29
+ private def resolve_column_index(column)
30
+ case column
31
+ when String, Symbol
32
+ index = column_names.index(column.to_s)
33
+ unless index
34
+ raise IndexError, "invalid column name: #{column.inspect}"
35
+ end
36
+ index
37
+ when Integer
38
+ column
39
+ else
40
+ message = "column must be String or Integer: #{column.inspect}"
41
+ raise ArgumentError, message
42
+ end
43
+ end
44
+
45
+ private def fetch_records
46
+ @columns = @data.pluck(*column_names).transpose
47
+ end
48
+
49
+ private def check_type(type, data, name)
50
+ return data if data.is_a?(type)
51
+ raise TypeError, "#{name} must be a #{type}"
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ module Charty
2
+ module TableAdapters
3
+ class DaruAdapter
4
+ TableAdapters.register(:daru, self)
5
+
6
+ include Enumerable
7
+
8
+ def self.supported?(data)
9
+ defined?(Daru::DataFrame) && data.is_a?(Daru::DataFrame)
10
+ end
11
+
12
+ def initialize(data)
13
+ @data = check_type(Daru::DataFrame, data, :data)
14
+ end
15
+
16
+ def column_names
17
+ @data.vectors.to_a
18
+ end
19
+
20
+ def [](row, column)
21
+ if row
22
+ @data[column][row]
23
+ else
24
+ @data[column]
25
+ end
26
+ end
27
+
28
+ private def check_type(type, data, name)
29
+ return data if data.is_a?(type)
30
+ raise TypeError, "#{name} must be a #{type}"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ module Charty
2
+ module TableAdapters
3
+ class DatasetsAdapter
4
+ TableAdapters.register(:datasets, self)
5
+
6
+ include Enumerable
7
+
8
+ def self.supported?(data)
9
+ defined?(Datasets::Dataset) &&
10
+ data.is_a?(Datasets::Dataset)
11
+ end
12
+
13
+ def initialize(dataset)
14
+ @table = dataset.to_table
15
+ @records = []
16
+ end
17
+
18
+ def column_names
19
+ @table.column_names
20
+ end
21
+
22
+ def each(&block)
23
+ return to_enum(__method__) unless block_given?
24
+
25
+ @table.each_record(&block)
26
+ end
27
+
28
+ # @param [Integer] row Row index
29
+ # @param [Symbol,String,Integer] column Column index
30
+ def [](row, column)
31
+ if row
32
+ record = @table.find_record(row)
33
+ return nil if record.nil?
34
+ record[column]
35
+ else
36
+ @table[column]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,108 @@
1
+ require 'date'
2
+ require 'forwardable'
3
+
4
+ module Charty
5
+ module TableAdapters
6
+ class HashAdapter
7
+ TableAdapters.register(:hash, self)
8
+
9
+ extend Forwardable
10
+ include Enumerable
11
+
12
+ def self.supported?(data)
13
+ case data
14
+ when []
15
+ true
16
+ when Array
17
+ case data[0]
18
+ when Numeric, String, Time, Date
19
+ true
20
+ when Hash
21
+ data.all? {|el| el.is_a? Hash }
22
+ when method(:array?)
23
+ data.all?(&method(:array?))
24
+ end
25
+ when Hash
26
+ true
27
+ end
28
+ end
29
+
30
+ def self.array?(data)
31
+ case data
32
+ when Array,
33
+ ->(x) { defined?(Numo::NArray) && x.is_a?(Numo::NArray) },
34
+ ->(x) { defined?(Daru::Vector) && x.is_a?(Daru::Vector) },
35
+ ->(x) { defined?(NMatrix) && x.is_a?(NMatrix) }
36
+ true
37
+ else
38
+ false
39
+ end
40
+ end
41
+
42
+ def initialize(data, columns: nil)
43
+ case data
44
+ when Hash
45
+ @data = data
46
+ when Array
47
+ case data[0]
48
+ when Numeric, String, Time, Date
49
+ data = data.map {|x| [x] }
50
+ @data = make_data_from_records(data, columns)
51
+ when Hash
52
+ # TODO
53
+ when self.class.method(:array?)
54
+ unsupported_data_format unless data.all?(&self.class.method(:array?))
55
+ @data = make_data_from_records(data, columns)
56
+ else
57
+ unsupported_data_format
58
+ end
59
+ else
60
+ unsupported_data_format
61
+ end
62
+ end
63
+
64
+ def_delegator :@data, :keys, :column_names
65
+
66
+ def [](row, column)
67
+ if row
68
+ @data[column][row]
69
+ else
70
+ @data[column]
71
+ end
72
+ end
73
+
74
+ def each
75
+ i, n = 0, shape[0]
76
+ while i < n
77
+ record = @data.map {|k, v| v[i] }
78
+ yield record
79
+ i += 1
80
+ end
81
+ end
82
+
83
+ private def make_data_from_records(data, columns)
84
+ n_rows = data.length
85
+ n_columns = data.map(&:size).max
86
+ columns = generate_column_names(n_columns, columns)
87
+ columns.map.with_index { |key, j|
88
+ values = n_rows.times.map {|i| data[i][j] }
89
+ [key, values]
90
+ }.to_h
91
+ end
92
+
93
+ private def generate_column_names(n_columns, columns)
94
+ # FIXME: this is the same as NArrayAdapter#generate_column_names
95
+ columns ||= []
96
+ if columns.length >= n_columns
97
+ columns[0, n_columns]
98
+ else
99
+ columns + columns.length.upto(n_columns - 1).map {|i| "X#{i}" }
100
+ end
101
+ end
102
+
103
+ private def unsupported_data_format
104
+ raise ArgumentError, "Unsupported data format"
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,57 @@
1
+ module Charty
2
+ module TableAdapters
3
+ class NArrayAdapter
4
+ TableAdapters.register(:narray, self)
5
+
6
+ def self.supported?(data)
7
+ defined?(Numo::NArray) && data.is_a?(Numo::NArray) && data.ndim <= 2
8
+ end
9
+
10
+ def initialize(data, columns: nil)
11
+ case data.ndim
12
+ when 1
13
+ data = data.reshape(data.length, 1)
14
+ when 2
15
+ # do nothing
16
+ else
17
+ raise ArgumentError, "Unsupported data format"
18
+ end
19
+ @data = data
20
+ @column_names = generate_column_names(data.shape[1], columns)
21
+ end
22
+
23
+ attr_reader :column_names
24
+
25
+ def [](row, column)
26
+ if row
27
+ @data[row, resolve_column_index(column)]
28
+ else
29
+ @data[true, resolve_column_index(column)]
30
+ end
31
+ end
32
+
33
+ private def resolve_column_index(column)
34
+ case column
35
+ when String, Symbol
36
+ index = column_names.index(column.to_s)
37
+ return index if index
38
+ raise IndexError, "invalid column name: #{column}"
39
+ when Integer
40
+ column
41
+ else
42
+ message = "column must be String or Integer: #{column.inspect}"
43
+ raise ArgumentError, message
44
+ end
45
+ end
46
+
47
+ private def generate_column_names(n_columns, columns)
48
+ columns ||= []
49
+ if columns.length >= n_columns
50
+ columns[0, n_columns]
51
+ else
52
+ columns + columns.length.upto(n_columns - 1).map {|i| "X#{i}" }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ module Charty
2
+ module TableAdapters
3
+ class NMatrixAdapter
4
+ TableAdapters.register(:nmatrix, self)
5
+
6
+ def self.supported?(data)
7
+ defined?(NMatrix) && data.is_a?(NMatrix) && data.shape.length <= 2
8
+ end
9
+
10
+ def initialize(data, columns: nil)
11
+ case data.shape.length
12
+ when 1
13
+ data = data.reshape(data.size, 1)
14
+ when 2
15
+ # do nothing
16
+ else
17
+ raise ArgumentError, "Unsupported data format"
18
+ end
19
+ @data = data
20
+ @column_names = generate_column_names(data.shape[1], columns)
21
+ end
22
+
23
+ attr_reader :column_names
24
+
25
+ def [](row, column)
26
+ if row
27
+ @data[row, resolve_column_index(column)]
28
+ else
29
+ @data[:*, resolve_column_index(column)].reshape([@data.shape[0]])
30
+ end
31
+ end
32
+
33
+ private def resolve_column_index(column)
34
+ case column
35
+ when String, Symbol
36
+ index = column_names.index(column.to_s)
37
+ return index if index
38
+ raise IndexError, "invalid column name: #{column}"
39
+ when Integer
40
+ column
41
+ else
42
+ message = "column must be String or Integer: #{column.inspect}"
43
+ raise ArgumentError, message
44
+ end
45
+ end
46
+
47
+ private def generate_column_names(n_columns, columns)
48
+ columns ||= []
49
+ if columns.length >= n_columns
50
+ columns[0, n_columns]
51
+ else
52
+ columns + columns.length.upto(n_columns - 1).map {|i| "X#{i}" }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,5 +1,5 @@
1
1
  module Charty
2
- VERSION = "0.1.5-dev"
2
+ VERSION = "0.2.0"
3
3
 
4
4
  module Version
5
5
  numbers, TAG = VERSION.split("-")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: charty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5.dev
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - youchan
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2019-07-09 00:00:00.000000000 Z
13
+ date: 2019-09-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -54,6 +54,90 @@ dependencies:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: numo-narray
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: nmatrix
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: red-datasets
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 0.0.9
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 0.0.9
99
+ - !ruby/object:Gem::Dependency
100
+ name: daru
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ - !ruby/object:Gem::Dependency
114
+ name: activerecord
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: sqlite3
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
57
141
  - !ruby/object:Gem::Dependency
58
142
  name: matplotlib
59
143
  requirement: !ruby/object:Gem::Requirement
@@ -94,23 +178,30 @@ files:
94
178
  - examples/iris_dataset.ipynb
95
179
  - examples/nmatrix.ipynb
96
180
  - examples/numo-narray.ipynb
181
+ - examples/sample_bokeh.ipynb
97
182
  - examples/sample_google_chart.ipynb
98
183
  - examples/sample_gruff.ipynb
184
+ - examples/sample_images/bar_bokeh.html
99
185
  - examples/sample_images/bar_gruff.png
100
186
  - examples/sample_images/bar_pyplot.png
101
187
  - examples/sample_images/bar_rubyplot.png
188
+ - examples/sample_images/barh_bokeh.html
102
189
  - examples/sample_images/barh_gruff.png
103
190
  - examples/sample_images/barh_pyplot.png
191
+ - examples/sample_images/box_plot_bokeh.html
104
192
  - examples/sample_images/box_plot_pyplot.png
105
193
  - examples/sample_images/bubble_pyplot.png
106
194
  - examples/sample_images/bubble_rubyplot.png
195
+ - examples/sample_images/curve_bokeh.html
107
196
  - examples/sample_images/curve_gruff.png
108
197
  - examples/sample_images/curve_pyplot.png
109
198
  - examples/sample_images/curve_rubyplot.png
199
+ - examples/sample_images/curve_with_function_bokeh.html
110
200
  - examples/sample_images/curve_with_function_pyplot.png
111
201
  - examples/sample_images/curve_with_function_rubyplot.png
112
202
  - examples/sample_images/error_bar_pyplot.png
113
203
  - examples/sample_images/hist_pyplot.png
204
+ - examples/sample_images/scatter_bokeh.html
114
205
  - examples/sample_images/scatter_gruff.png
115
206
  - examples/sample_images/scatter_pyplot.png
116
207
  - examples/sample_images/scatter_rubyplot.png
@@ -120,16 +211,24 @@ files:
120
211
  - examples/sample_rubyplot.ipynb
121
212
  - images/design_concept.png
122
213
  - lib/charty.rb
214
+ - lib/charty/backends.rb
123
215
  - lib/charty/backends/bokeh.rb
124
216
  - lib/charty/backends/google_chart.rb
125
217
  - lib/charty/backends/gruff.rb
218
+ - lib/charty/backends/plotly.rb
126
219
  - lib/charty/backends/pyplot.rb
127
220
  - lib/charty/backends/rubyplot.rb
128
221
  - lib/charty/layout.rb
129
222
  - lib/charty/linspace.rb
130
223
  - lib/charty/plotter.rb
131
- - lib/charty/plotter_adapter.rb
132
224
  - lib/charty/table.rb
225
+ - lib/charty/table_adapters.rb
226
+ - lib/charty/table_adapters/active_record_adapter.rb
227
+ - lib/charty/table_adapters/daru_adapter.rb
228
+ - lib/charty/table_adapters/datasets_adapter.rb
229
+ - lib/charty/table_adapters/hash_adapter.rb
230
+ - lib/charty/table_adapters/narray_adapter.rb
231
+ - lib/charty/table_adapters/nmatrix_adapter.rb
133
232
  - lib/charty/version.rb
134
233
  homepage: https://github.com/red-data-tools/charty
135
234
  licenses:
@@ -146,9 +245,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
245
  version: '0'
147
246
  required_rubygems_version: !ruby/object:Gem::Requirement
148
247
  requirements:
149
- - - ">"
248
+ - - ">="
150
249
  - !ruby/object:Gem::Version
151
- version: 1.3.1
250
+ version: '0'
152
251
  requirements: []
153
252
  rubygems_version: 3.0.3
154
253
  signing_key: