charty 0.2.4 → 0.2.5
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 +4 -4
- data/README.md +63 -15
- data/charty.gemspec +3 -0
- data/lib/charty.rb +1 -0
- data/lib/charty/backends/bokeh.rb +2 -2
- data/lib/charty/backends/google_charts.rb +1 -1
- data/lib/charty/backends/gruff.rb +1 -1
- data/lib/charty/backends/plotly.rb +149 -13
- data/lib/charty/backends/pyplot.rb +8 -4
- data/lib/charty/backends/rubyplot.rb +1 -1
- data/lib/charty/plotter.rb +2 -2
- data/lib/charty/plotters/abstract_plotter.rb +29 -2
- data/lib/charty/plotters/bar_plotter.rb +1 -16
- data/lib/charty/plotters/box_plotter.rb +1 -16
- data/lib/charty/plotters/scatter_plotter.rb +2 -13
- data/lib/charty/table_adapters/hash_adapter.rb +1 -1
- data/lib/charty/util.rb +20 -0
- data/lib/charty/version.rb +1 -1
- metadata +45 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cf18b5e31bf29099d3d9386b8b022e38013bba339c129a0292af39983e2bccb
|
4
|
+
data.tar.gz: 4eb934400a4fc7c60354bf7f7f31e33d4be8cdbdeafb1d47762264d94c8c5a2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33f5c4ea51ea77a66538e62e43222aaa4f77942b526461ef881cd0ff092eb17a16830937eab032995361a1e7b9e0063e79f682b75fa1c0011644410f02c23b11
|
7
|
+
data.tar.gz: cd0c31ae974c4efc6192dc0fa74c93db41cdacac6e5a82cfded9ca1b4285e706c925641df483020d620f22e3aed5fae7263d2364ac0cfb5df35bbf4fc72ad034
|
data/README.md
CHANGED
@@ -69,6 +69,63 @@ require "datasets"
|
|
69
69
|
penguins = Datasets::Penguins.new
|
70
70
|
```
|
71
71
|
|
72
|
+
#### A basic workflow
|
73
|
+
|
74
|
+
The following code shows a basic workflow of the visualization with Charty.
|
75
|
+
|
76
|
+
First you need to load the Charty library.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
require "charty"
|
80
|
+
```
|
81
|
+
|
82
|
+
Next you msut have a dataset you want to visualize. Here, we use the penguins dataset provided in red-datasets library.
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
require "datasets"
|
86
|
+
penguins = Datasets::Penguins.new
|
87
|
+
```
|
88
|
+
|
89
|
+
Next you need to create a plotter object by a plotting method. Here, we use `scatter_plot` method to show the relationship
|
90
|
+
among `body_mass_g`, `flipper_length_mm`, and `species` columns in the penguins dataset.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
plot = Charty.scatter_plot(data: penguins, x: :body_mass_g, y: :flipper_length_mm, color: :species)
|
94
|
+
```
|
95
|
+
|
96
|
+
If you want to render and save this plotter object into an HTML file by plotly backend, you can do it like below.
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
Charty::Backends.use(:plotly) # select plotly backend
|
100
|
+
plot.save("scatter.html") # save the plot as an HTML file
|
101
|
+
```
|
102
|
+
|
103
|
+
If you want to save the plotter into a PNG file, you can do it by specifying a output filename with `.png` extension.
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
plot.save("scatter.png")
|
107
|
+
```
|
108
|
+
|
109
|
+
#### Jupyter Notebook
|
110
|
+
|
111
|
+
If you use Charty on Jupyter Notebook with IRuby kerenl (a.k.a. IRuby notebook),
|
112
|
+
you can render the plot just evaluate a plotter object. For example, the code below shows a scatter plot figure in
|
113
|
+
the output area.
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
Charty::Backends.use(:plotly)
|
117
|
+
|
118
|
+
Charty.scatter_plot(data: penguins, x: :body_mass_g, y: :flipper_length_mm, color: :species)
|
119
|
+
```
|
120
|
+
|
121
|
+
Note that if you want to use the pyplot backend, you need to activate the integration between the pyplot backend and IRuby.
|
122
|
+
You can activate the integration by the following two lines.
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
Charty::Backends.use(:pyplot)
|
126
|
+
Charty::Backends::Pyplot.activate_iruby_integration
|
127
|
+
```
|
128
|
+
|
72
129
|
#### Bar plot
|
73
130
|
|
74
131
|
Charty's statistical bar plot shows the relationship between a categorical variable and estimated means of a numeric variable.
|
@@ -80,8 +137,7 @@ Instead, when we specify the categorical variable as y-axis, the plot draws a ho
|
|
80
137
|
The following code shows the relationship between species and the mean body masses of penguins in a vertical bar chart.
|
81
138
|
|
82
139
|
```ruby
|
83
|
-
Charty
|
84
|
-
Charty.bar_plot(data: penguins, x: :species, y: :body_mass_g).render
|
140
|
+
Charty.bar_plot(data: penguins, x: :species, y: :body_mass_g)
|
85
141
|
```
|
86
142
|
|
87
143
|

|
@@ -89,8 +145,7 @@ Charty.bar_plot(data: penguins, x: :species, y: :body_mass_g).render
|
|
89
145
|
Exchanging x and y axes alternates the orientation of the resulting chart.
|
90
146
|
|
91
147
|
```ruby
|
92
|
-
Charty
|
93
|
-
Charty.bar_plot(data: penguins, x: :body_mass_g, y: :species).render
|
148
|
+
Charty.bar_plot(data: penguins, x: :body_mass_g, y: :species)
|
94
149
|
```
|
95
150
|
|
96
151
|

|
@@ -98,8 +153,7 @@ Charty.bar_plot(data: penguins, x: :body_mass_g, y: :species).render
|
|
98
153
|
Adding color axis introduces color grouping in the bar plot.
|
99
154
|
|
100
155
|
```ruby
|
101
|
-
Charty
|
102
|
-
Charty.bar_plot(data: penguins, x: :species, y: :body_mass_g, color: :sex).render
|
156
|
+
Charty.bar_plot(data: penguins, x: :species, y: :body_mass_g, color: :sex)
|
103
157
|
```
|
104
158
|
|
105
159
|

|
@@ -116,8 +170,7 @@ Instead, when we specify the categorical variable as y-axis, the plot draws a ho
|
|
116
170
|
The following code draws a vertical box plot to show distributions of penguins' body mass per species.
|
117
171
|
|
118
172
|
```ruby
|
119
|
-
Charty
|
120
|
-
Charty.box_plot(data: penguins, x: :species, y: :body_mass_g).render
|
173
|
+
Charty.box_plot(data: penguins, x: :species, y: :body_mass_g)
|
121
174
|
```
|
122
175
|
|
123
176
|

|
@@ -125,8 +178,7 @@ Charty.box_plot(data: penguins, x: :species, y: :body_mass_g).render
|
|
125
178
|
As `bar_plot` above, exchanging x and y axes alternates the orientation of the resulting chart.
|
126
179
|
|
127
180
|
```ruby
|
128
|
-
Charty
|
129
|
-
Charty.box_plot(data: penguins, x: :body_mass_g, y: :species).render
|
181
|
+
Charty.box_plot(data: penguins, x: :body_mass_g, y: :species)
|
130
182
|
```
|
131
183
|
|
132
184
|

|
@@ -134,8 +186,7 @@ Charty.box_plot(data: penguins, x: :body_mass_g, y: :species).render
|
|
134
186
|
Adding color axis introduces color grouping in the box plot.
|
135
187
|
|
136
188
|
```ruby
|
137
|
-
Charty
|
138
|
-
Charty.box_plot(data: penguins, x: :species, y: :body_mass_g, color: :sex).render
|
189
|
+
Charty.box_plot(data: penguins, x: :species, y: :body_mass_g, color: :sex)
|
139
190
|
```
|
140
191
|
|
141
192
|

|
@@ -145,7 +196,6 @@ Charty.box_plot(data: penguins, x: :species, y: :body_mass_g, color: :sex).rende
|
|
145
196
|
Charty's scatter plot shows the relationship between two numeric variables.
|
146
197
|
|
147
198
|
```ruby
|
148
|
-
Charty::Backends.use(:pyplot)
|
149
199
|
Charty.scatter_plot(data: penguins, x: :body_mass_g, y: flipper_length_mm)
|
150
200
|
```
|
151
201
|
|
@@ -156,7 +206,6 @@ The following example specifies `:species` variable in the color axis.
|
|
156
206
|
It shows the different species by the different colors.
|
157
207
|
|
158
208
|
```ruby
|
159
|
-
Charty::Backends.use(:pyplot)
|
160
209
|
Charty.scatter_plot(data: penguins, x: :body_mass_g, y: flipper_length_mm, color: :species)
|
161
210
|
```
|
162
211
|
|
@@ -166,7 +215,6 @@ Moreover, size and style axes can be specified.
|
|
166
215
|
The following example specifies `:sex` variable in the style axis.
|
167
216
|
|
168
217
|
```ruby
|
169
|
-
Charty::Backends.use(:pyplot)
|
170
218
|
Charty.scatter_plot(data: penguins, x: :body_mass_g, y: flipper_length_mm, color: :species, style: :sex)
|
171
219
|
```
|
172
220
|
|
data/charty.gemspec
CHANGED
@@ -34,6 +34,9 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "test-unit"
|
35
35
|
spec.add_development_dependency "red-datasets", ">= 0.0.9"
|
36
36
|
spec.add_development_dependency "daru"
|
37
|
+
spec.add_development_dependency "matrix" # need for daru on Ruby > 3.0
|
37
38
|
spec.add_development_dependency "activerecord"
|
38
39
|
spec.add_development_dependency "sqlite3"
|
40
|
+
spec.add_development_dependency "playwright-ruby-client"
|
41
|
+
spec.add_development_dependency "iruby"
|
39
42
|
end
|
data/lib/charty.rb
CHANGED
@@ -17,13 +17,13 @@ module Charty
|
|
17
17
|
@series = series
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def old_style_render(context, filename)
|
21
21
|
plot = plot(context)
|
22
22
|
save(plot, context, filename)
|
23
23
|
PyCall.import_module('bokeh.io').show(plot)
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
26
|
+
def old_style_save(plot, context, filename)
|
27
27
|
if filename
|
28
28
|
PyCall.import_module('bokeh.io').save(plot, filename)
|
29
29
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "json"
|
2
2
|
require "securerandom"
|
3
|
+
require "tmpdir"
|
3
4
|
|
4
5
|
module Charty
|
5
6
|
module Backends
|
@@ -36,7 +37,7 @@ module Charty
|
|
36
37
|
@series = series
|
37
38
|
end
|
38
39
|
|
39
|
-
def
|
40
|
+
def old_style_render(context, filename)
|
40
41
|
plot(nil, context)
|
41
42
|
end
|
42
43
|
|
@@ -447,7 +448,34 @@ module Charty
|
|
447
448
|
# TODO: Handle loc
|
448
449
|
end
|
449
450
|
|
450
|
-
def save(filename, title: nil)
|
451
|
+
def save(filename, format: nil, title: nil, width: 700, height: 500, **kwargs)
|
452
|
+
format = detect_format(filename) if format.nil?
|
453
|
+
|
454
|
+
case format
|
455
|
+
when nil, :html, "text/html"
|
456
|
+
save_html(filename, title: title, **kwargs)
|
457
|
+
when :png, "png", "image/png",
|
458
|
+
:jpeg, "jpeg", "image/jpeg"
|
459
|
+
render_image(format, filename: filename, notebook: false, title: title, width: width, height: height, **kwargs)
|
460
|
+
end
|
461
|
+
nil
|
462
|
+
end
|
463
|
+
|
464
|
+
private def detect_format(filename)
|
465
|
+
case File.extname(filename).downcase
|
466
|
+
when ".htm", ".html"
|
467
|
+
:html
|
468
|
+
when ".png"
|
469
|
+
:png
|
470
|
+
when ".jpg", ".jpeg"
|
471
|
+
:jpeg
|
472
|
+
else
|
473
|
+
raise ArgumentError,
|
474
|
+
"Unable to infer file type from filename: %p" % filename
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
private def save_html(filename, title:, element_id: nil)
|
451
479
|
html = <<~HTML
|
452
480
|
<!DOCTYPE html>
|
453
481
|
<html>
|
@@ -464,30 +492,50 @@ module Charty
|
|
464
492
|
</body>
|
465
493
|
</html>
|
466
494
|
HTML
|
495
|
+
|
496
|
+
element_id = SecureRandom.uuid if element_id.nil?
|
497
|
+
|
467
498
|
html %= {
|
468
499
|
title: title || default_html_title,
|
469
|
-
id:
|
500
|
+
id: element_id,
|
470
501
|
data: JSON.dump(@traces),
|
471
502
|
layout: JSON.dump(@layout)
|
472
503
|
}
|
473
504
|
File.write(filename, html)
|
474
|
-
nil
|
475
505
|
end
|
476
506
|
|
477
507
|
private def default_html_title
|
478
508
|
"Charty plot"
|
479
509
|
end
|
480
510
|
|
481
|
-
def
|
482
|
-
|
483
|
-
|
484
|
-
|
511
|
+
def render(element_id: nil, format: nil, notebook: false)
|
512
|
+
case format
|
513
|
+
when :html, "html"
|
514
|
+
format = "text/html"
|
515
|
+
when :png, "png"
|
516
|
+
format = "image/png"
|
517
|
+
when :jpeg, "jpeg"
|
518
|
+
format = "image/jpeg"
|
485
519
|
end
|
486
520
|
|
487
|
-
|
521
|
+
case format
|
522
|
+
when "text/html", nil
|
523
|
+
# render html after this case cause
|
524
|
+
when "image/png", "image/jpeg"
|
525
|
+
image_data = render_image(format, element_id: element_id, notebook: false)
|
526
|
+
if notebook
|
527
|
+
return [format, image_data]
|
528
|
+
else
|
529
|
+
return image_data
|
530
|
+
end
|
531
|
+
else
|
532
|
+
raise ArgumentError,
|
533
|
+
"Unsupported mime type to render: %p" % format
|
534
|
+
end
|
488
535
|
|
536
|
+
# TODO: size should be customizable
|
489
537
|
html = <<~HTML
|
490
|
-
<div id="%{id}" style="width: 100%%; height:
|
538
|
+
<div id="%{id}" style="width: 100%%; height:525px;"></div>
|
491
539
|
<script type="text/javascript">
|
492
540
|
requirejs(["plotly"], function (Plotly) {
|
493
541
|
Plotly.newPlot("%{id}", %{data}, %{layout});
|
@@ -495,13 +543,46 @@ module Charty
|
|
495
543
|
</script>
|
496
544
|
HTML
|
497
545
|
|
546
|
+
element_id = SecureRandom.uuid if element_id.nil?
|
547
|
+
|
498
548
|
html %= {
|
499
|
-
id:
|
549
|
+
id: element_id,
|
500
550
|
data: JSON.dump(@traces),
|
501
551
|
layout: JSON.dump(@layout)
|
502
552
|
}
|
503
|
-
|
504
|
-
|
553
|
+
|
554
|
+
if notebook
|
555
|
+
IRubyOutput.prepare
|
556
|
+
["text/html", html]
|
557
|
+
else
|
558
|
+
html
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
private def render_image(format=nil, filename: nil, element_id: nil, notebook: false,
|
563
|
+
title: nil, width: nil, height: nil)
|
564
|
+
format = "image/png" if format.nil?
|
565
|
+
case format
|
566
|
+
when :png, "png", :jpeg, "jpeg"
|
567
|
+
image_type = format.to_s
|
568
|
+
when "image/png", "image/jpeg"
|
569
|
+
image_type = format.split("/").last
|
570
|
+
else
|
571
|
+
raise ArgumentError,
|
572
|
+
"Unsupported mime type to render image: %p" % format
|
573
|
+
end
|
574
|
+
|
575
|
+
height = 525 if height.nil?
|
576
|
+
width = (height * Math.sqrt(2)).to_i if width.nil?
|
577
|
+
title = "Charty plot" if title.nil?
|
578
|
+
|
579
|
+
element_id = SecureRandom.uuid if element_id.nil?
|
580
|
+
element_id = "charty-plotly-#{element_id}"
|
581
|
+
Dir.mktmpdir do |tmpdir|
|
582
|
+
html_filename = File.join(tmpdir, "%s.html" % element_id)
|
583
|
+
save_html(html_filename, title: title, element_id: element_id)
|
584
|
+
return self.class.render_image(html_filename, filename, image_type, element_id, width, height)
|
585
|
+
end
|
505
586
|
end
|
506
587
|
|
507
588
|
module IRubyOutput
|
@@ -544,6 +625,61 @@ module Charty
|
|
544
625
|
END
|
545
626
|
end
|
546
627
|
end
|
628
|
+
|
629
|
+
@playwright_fiber = nil
|
630
|
+
|
631
|
+
def self.ensure_playwright
|
632
|
+
if @playwright_fiber.nil?
|
633
|
+
begin
|
634
|
+
require "playwright"
|
635
|
+
rescue LoadError
|
636
|
+
$stderr.puts "ERROR: You need to install playwright and playwright-ruby-client before using Plotly renderer"
|
637
|
+
raise
|
638
|
+
end
|
639
|
+
|
640
|
+
@playwright_fiber = Fiber.new do
|
641
|
+
playwright_cli_executable_path = ENV.fetch("PLAYWRIGHT_CLI_EXECUTABLE_PATH", "npx playwright")
|
642
|
+
Playwright.create(playwright_cli_executable_path: playwright_cli_executable_path) do |playwright|
|
643
|
+
playwright.chromium.launch(headless: true) do |browser|
|
644
|
+
request = Fiber.yield
|
645
|
+
loop do
|
646
|
+
result = nil
|
647
|
+
case request.shift
|
648
|
+
when :finish
|
649
|
+
break
|
650
|
+
when :render
|
651
|
+
input, output, format, element_id, width, height = request
|
652
|
+
|
653
|
+
page = browser.new_page
|
654
|
+
page.set_viewport_size(width: width, height: height)
|
655
|
+
page.goto("file://#{input}")
|
656
|
+
element = page.query_selector("\##{element_id}")
|
657
|
+
|
658
|
+
kwargs = {type: format}
|
659
|
+
kwargs[:path] = output unless output.nil?
|
660
|
+
result = element.screenshot(**kwargs)
|
661
|
+
end
|
662
|
+
request = Fiber.yield(result)
|
663
|
+
end
|
664
|
+
end
|
665
|
+
end
|
666
|
+
end
|
667
|
+
@playwright_fiber.resume
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
def self.terminate_playwright
|
672
|
+
return if @playwright_fiber.nil?
|
673
|
+
|
674
|
+
@playwright_fiber.resume([:finish])
|
675
|
+
end
|
676
|
+
|
677
|
+
at_exit { terminate_playwright }
|
678
|
+
|
679
|
+
def self.render_image(input, output, format, element_id, width, height)
|
680
|
+
ensure_playwright if @playwright_fiber.nil?
|
681
|
+
@playwright_fiber.resume([:render, input, output, format.to_s, element_id, width, height])
|
682
|
+
end
|
547
683
|
end
|
548
684
|
end
|
549
685
|
end
|
@@ -41,7 +41,7 @@ module Charty
|
|
41
41
|
@pyplot.show
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
44
|
+
def old_style_render(context, filename)
|
45
45
|
plot(@pyplot, context)
|
46
46
|
if filename
|
47
47
|
FileUtils.mkdir_p(File.dirname(filename))
|
@@ -50,7 +50,7 @@ module Charty
|
|
50
50
|
@pyplot.show
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
53
|
+
def old_style_save(context, filename, finish: true)
|
54
54
|
plot(context)
|
55
55
|
if filename
|
56
56
|
FileUtils.mkdir_p(File.dirname(filename))
|
@@ -374,7 +374,7 @@ module Charty
|
|
374
374
|
brief_ticks = RELATIONAL_PLOT_LEGEND_BRIEF_TICKS
|
375
375
|
verbosity = :auto if verbosity == true
|
376
376
|
|
377
|
-
legend_titles = [:color, :size, :style]
|
377
|
+
legend_titles = Util.filter_map([:color, :size, :style]) {|v| variables[v] }
|
378
378
|
legend_title = legend_titles.pop if legend_titles.length == 1
|
379
379
|
|
380
380
|
legend_kwargs = {}
|
@@ -484,7 +484,7 @@ module Charty
|
|
484
484
|
legend_kwargs.each do |key, kw|
|
485
485
|
_, label = key
|
486
486
|
kw[:color] ||= ".2"
|
487
|
-
use_kw =
|
487
|
+
use_kw = Util.filter_map(legend_attributes) {|attr|
|
488
488
|
[attr, kw[attr]] if kw.key?(attr)
|
489
489
|
}.to_h
|
490
490
|
use_kw[:visible] = kw[:visible] if kw.key?(:visible)
|
@@ -592,6 +592,10 @@ module Charty
|
|
592
592
|
@pyplot.gca.legend(loc: loc, title: title)
|
593
593
|
end
|
594
594
|
|
595
|
+
def render(notebook: false)
|
596
|
+
show
|
597
|
+
end
|
598
|
+
|
595
599
|
def show
|
596
600
|
@pyplot.show
|
597
601
|
end
|
data/lib/charty/plotter.rb
CHANGED
@@ -237,11 +237,11 @@ module Charty
|
|
237
237
|
end
|
238
238
|
|
239
239
|
def render(filename=nil)
|
240
|
-
@backend.
|
240
|
+
@backend.old_style_render(self, filename)
|
241
241
|
end
|
242
242
|
|
243
243
|
def save(filename=nil, **kw)
|
244
|
-
@backend.
|
244
|
+
@backend.old_style_save(self, filename, **kw)
|
245
245
|
end
|
246
246
|
|
247
247
|
def apply(backend)
|
@@ -14,6 +14,10 @@ module Charty
|
|
14
14
|
attr_reader :data, :x, :y, :color
|
15
15
|
attr_reader :color_order, :key_color, :palette
|
16
16
|
|
17
|
+
def inspect
|
18
|
+
"#<#{self.class}:0x%016x>" % self.object_id
|
19
|
+
end
|
20
|
+
|
17
21
|
def data=(data)
|
18
22
|
@data = case data
|
19
23
|
when nil, Charty::Table
|
@@ -147,9 +151,32 @@ module Charty
|
|
147
151
|
ary
|
148
152
|
end
|
149
153
|
|
154
|
+
def save(filename, **kwargs)
|
155
|
+
backend = Backends.current
|
156
|
+
backend.begin_figure
|
157
|
+
render_plot(backend, **kwargs)
|
158
|
+
backend.save(filename, **kwargs)
|
159
|
+
end
|
160
|
+
|
161
|
+
def render(notebook: false, **kwargs)
|
162
|
+
backend = Backends.current
|
163
|
+
backend.begin_figure
|
164
|
+
render_plot(backend, notebook: notebook, **kwargs)
|
165
|
+
backend.render(notebook: notebook, **kwargs)
|
166
|
+
end
|
167
|
+
|
168
|
+
private def render_plot(*, **)
|
169
|
+
raise NotImplementedError,
|
170
|
+
"subclass must implement #{__method__}"
|
171
|
+
end
|
172
|
+
|
150
173
|
def to_iruby
|
151
|
-
|
152
|
-
|
174
|
+
render(notebook: iruby_notebook?)
|
175
|
+
end
|
176
|
+
|
177
|
+
private def iruby_notebook?
|
178
|
+
return false unless defined?(IRuby)
|
179
|
+
true # TODO: Check the server is notebook or not
|
153
180
|
end
|
154
181
|
end
|
155
182
|
end
|
@@ -42,25 +42,10 @@ module Charty
|
|
42
42
|
@cap_size = check_number(cap_size, :cap_size, allow_nil: true)
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
46
|
-
backend = Backends.current
|
47
|
-
backend.begin_figure
|
45
|
+
private def render_plot(backend, **)
|
48
46
|
draw_bars(backend)
|
49
47
|
annotate_axes(backend)
|
50
48
|
backend.invert_yaxis if orient == :h
|
51
|
-
backend.show
|
52
|
-
end
|
53
|
-
|
54
|
-
# TODO:
|
55
|
-
# - Should infer mime type from file's extname
|
56
|
-
# - Should check backend's supported mime type before begin_figure
|
57
|
-
def save(filename, **opts)
|
58
|
-
backend = Backends.current
|
59
|
-
backend.begin_figure
|
60
|
-
draw_bars(backend)
|
61
|
-
annotate_axes(backend)
|
62
|
-
backend.invert_yaxis if orient == :h
|
63
|
-
backend.save(filename, **opts)
|
64
49
|
end
|
65
50
|
|
66
51
|
private def draw_bars(backend)
|
@@ -27,25 +27,10 @@ module Charty
|
|
27
27
|
@whisker = check_number(val, :whisker, allow_nil: true)
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
backend = Backends.current
|
32
|
-
backend.begin_figure
|
30
|
+
private def render_plot(backend, **)
|
33
31
|
draw_box_plot(backend)
|
34
32
|
annotate_axes(backend)
|
35
33
|
backend.invert_yaxis if orient == :h
|
36
|
-
backend.show
|
37
|
-
end
|
38
|
-
|
39
|
-
# TODO:
|
40
|
-
# - Should infer mime type from file's extname
|
41
|
-
# - Should check backend's supported mime type before begin_figure
|
42
|
-
def save(filename, **opts)
|
43
|
-
backend = Backends.current
|
44
|
-
backend.begin_figure
|
45
|
-
draw_box_plot(backend)
|
46
|
-
annotate_axes(backend)
|
47
|
-
backend.invert_yaxis if orient == :h
|
48
|
-
backend.save(filename, **opts)
|
49
34
|
end
|
50
35
|
|
51
36
|
private def draw_box_plot(backend)
|
@@ -47,20 +47,9 @@ module Charty
|
|
47
47
|
@line_width = check_color(val, :edge_color, allow_nil: true)
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
backend = Backends.current
|
52
|
-
backend.begin_figure
|
50
|
+
private def render_plot(backend, **)
|
53
51
|
draw_points(backend)
|
54
52
|
annotate_axes(backend)
|
55
|
-
backend.show
|
56
|
-
end
|
57
|
-
|
58
|
-
def save(filename, **opts)
|
59
|
-
backend = Backends.current
|
60
|
-
backend.begin_figure
|
61
|
-
draw_points(backend)
|
62
|
-
annotate_axes(backend)
|
63
|
-
backend.save(filename, **opts)
|
64
53
|
end
|
65
54
|
|
66
55
|
private def draw_points(backend)
|
@@ -105,7 +94,7 @@ module Charty
|
|
105
94
|
verbosity = legend
|
106
95
|
verbosity = :auto if verbosity == true
|
107
96
|
|
108
|
-
titles = [:color, :size, :style]
|
97
|
+
titles = Util.filter_map([:color, :size, :style]) do |v|
|
109
98
|
variables[v] if variables.key?(v)
|
110
99
|
end
|
111
100
|
legend_title = titles.length == 1 ? titles[0] : ""
|
@@ -88,7 +88,7 @@ module Charty
|
|
88
88
|
|
89
89
|
private def check_data(arrays, columns, index)
|
90
90
|
# NOTE: After Ruby 2.7, we can write the following code by filter_map:
|
91
|
-
# indexes =
|
91
|
+
# indexes = Util.filter_map(arrays) {|ary| ary.index if ary.is_a?(Charty::Vector) }
|
92
92
|
indexes = []
|
93
93
|
arrays.each do |array|
|
94
94
|
index = case array
|
data/lib/charty/util.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Charty
|
2
|
+
module Util
|
3
|
+
if [].respond_to?(:filter_map)
|
4
|
+
module_function def filter_map(enum, &block)
|
5
|
+
enum.filter_map(&block)
|
6
|
+
end
|
7
|
+
else
|
8
|
+
module_function def filter_map(enum, &block)
|
9
|
+
enum.inject([]) do |acc, x|
|
10
|
+
y = block.call(x)
|
11
|
+
if y
|
12
|
+
acc.push(y)
|
13
|
+
else
|
14
|
+
acc
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/charty/version.rb
CHANGED
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.2.
|
4
|
+
version: 0.2.5
|
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: 2021-05-
|
13
|
+
date: 2021-05-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: red-colors
|
@@ -110,6 +110,20 @@ dependencies:
|
|
110
110
|
- - ">="
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: '0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: matrix
|
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'
|
113
127
|
- !ruby/object:Gem::Dependency
|
114
128
|
name: activerecord
|
115
129
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,6 +152,34 @@ dependencies:
|
|
138
152
|
- - ">="
|
139
153
|
- !ruby/object:Gem::Version
|
140
154
|
version: '0'
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: playwright-ruby-client
|
157
|
+
requirement: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
type: :development
|
163
|
+
prerelease: false
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
name: iruby
|
171
|
+
requirement: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
type: :development
|
177
|
+
prerelease: false
|
178
|
+
version_requirements: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0'
|
141
183
|
description: Visualizing your data in a simple way.
|
142
184
|
email:
|
143
185
|
- youchan01@gmail.com
|
@@ -248,6 +290,7 @@ files:
|
|
248
290
|
- lib/charty/table_adapters/narray_adapter.rb
|
249
291
|
- lib/charty/table_adapters/nmatrix_adapter.rb
|
250
292
|
- lib/charty/table_adapters/pandas_adapter.rb
|
293
|
+
- lib/charty/util.rb
|
251
294
|
- lib/charty/vector.rb
|
252
295
|
- lib/charty/vector_adapters.rb
|
253
296
|
- lib/charty/vector_adapters/array_adapter.rb
|