charty 0.1.5.dev → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +71 -0
  3. data/.github/workflows/nmatrix.yml +67 -0
  4. data/.github/workflows/pycall.yml +86 -0
  5. data/Dockerfile.dev +9 -1
  6. data/Gemfile +18 -0
  7. data/README.md +176 -9
  8. data/Rakefile +4 -5
  9. data/charty.gemspec +10 -1
  10. data/examples/Gemfile +1 -0
  11. data/examples/active_record.ipynb +1 -1
  12. data/examples/daru.ipynb +1 -1
  13. data/examples/iris_dataset.ipynb +1 -1
  14. data/examples/nmatrix.ipynb +1 -1
  15. data/examples/{numo-narray.ipynb → numo_narray.ipynb} +1 -1
  16. data/examples/palette.rb +71 -0
  17. data/examples/sample.png +0 -0
  18. data/examples/sample_bokeh.ipynb +156 -0
  19. data/examples/sample_google_chart.ipynb +229 -68
  20. data/examples/sample_images/bar_bokeh.html +85 -0
  21. data/examples/sample_images/barh_bokeh.html +85 -0
  22. data/examples/sample_images/box_plot_bokeh.html +85 -0
  23. data/examples/sample_images/curve_bokeh.html +85 -0
  24. data/examples/sample_images/curve_with_function_bokeh.html +85 -0
  25. data/examples/sample_images/hist_gruff.png +0 -0
  26. data/examples/sample_images/scatter_bokeh.html +85 -0
  27. data/examples/sample_pyplot.ipynb +40 -38
  28. data/images/penguins_body_mass_g_flipper_length_mm_scatter_plot.png +0 -0
  29. data/images/penguins_body_mass_g_flipper_length_mm_species_scatter_plot.png +0 -0
  30. data/images/penguins_body_mass_g_flipper_length_mm_species_sex_scatter_plot.png +0 -0
  31. data/images/penguins_species_body_mass_g_bar_plot_h.png +0 -0
  32. data/images/penguins_species_body_mass_g_bar_plot_v.png +0 -0
  33. data/images/penguins_species_body_mass_g_box_plot_h.png +0 -0
  34. data/images/penguins_species_body_mass_g_box_plot_v.png +0 -0
  35. data/images/penguins_species_body_mass_g_sex_bar_plot_v.png +0 -0
  36. data/images/penguins_species_body_mass_g_sex_box_plot_v.png +0 -0
  37. data/lib/charty.rb +14 -1
  38. data/lib/charty/backend_methods.rb +8 -0
  39. data/lib/charty/backends.rb +80 -0
  40. data/lib/charty/backends/bokeh.rb +32 -26
  41. data/lib/charty/backends/google_charts.rb +267 -0
  42. data/lib/charty/backends/gruff.rb +102 -83
  43. data/lib/charty/backends/plotly.rb +685 -0
  44. data/lib/charty/backends/pyplot.rb +586 -92
  45. data/lib/charty/backends/rubyplot.rb +82 -74
  46. data/lib/charty/backends/unicode_plot.rb +79 -0
  47. data/lib/charty/index.rb +213 -0
  48. data/lib/charty/linspace.rb +1 -1
  49. data/lib/charty/missing_value_support.rb +14 -0
  50. data/lib/charty/plot_methods.rb +184 -0
  51. data/lib/charty/plotter.rb +48 -40
  52. data/lib/charty/plotters.rb +11 -0
  53. data/lib/charty/plotters/abstract_plotter.rb +183 -0
  54. data/lib/charty/plotters/bar_plotter.rb +201 -0
  55. data/lib/charty/plotters/box_plotter.rb +79 -0
  56. data/lib/charty/plotters/categorical_plotter.rb +380 -0
  57. data/lib/charty/plotters/count_plotter.rb +7 -0
  58. data/lib/charty/plotters/estimation_support.rb +84 -0
  59. data/lib/charty/plotters/random_support.rb +25 -0
  60. data/lib/charty/plotters/relational_plotter.rb +518 -0
  61. data/lib/charty/plotters/scatter_plotter.rb +104 -0
  62. data/lib/charty/plotters/vector_plotter.rb +6 -0
  63. data/lib/charty/statistics.rb +114 -0
  64. data/lib/charty/table.rb +80 -3
  65. data/lib/charty/table_adapters.rb +25 -0
  66. data/lib/charty/table_adapters/active_record_adapter.rb +63 -0
  67. data/lib/charty/table_adapters/base_adapter.rb +69 -0
  68. data/lib/charty/table_adapters/daru_adapter.rb +70 -0
  69. data/lib/charty/table_adapters/datasets_adapter.rb +49 -0
  70. data/lib/charty/table_adapters/hash_adapter.rb +224 -0
  71. data/lib/charty/table_adapters/narray_adapter.rb +76 -0
  72. data/lib/charty/table_adapters/nmatrix_adapter.rb +67 -0
  73. data/lib/charty/table_adapters/pandas_adapter.rb +81 -0
  74. data/lib/charty/util.rb +20 -0
  75. data/lib/charty/vector.rb +69 -0
  76. data/lib/charty/vector_adapters.rb +183 -0
  77. data/lib/charty/vector_adapters/array_adapter.rb +109 -0
  78. data/lib/charty/vector_adapters/daru_adapter.rb +171 -0
  79. data/lib/charty/vector_adapters/narray_adapter.rb +187 -0
  80. data/lib/charty/vector_adapters/nmatrix_adapter.rb +37 -0
  81. data/lib/charty/vector_adapters/numpy_adapter.rb +168 -0
  82. data/lib/charty/vector_adapters/pandas_adapter.rb +200 -0
  83. data/lib/charty/version.rb +1 -1
  84. metadata +179 -10
  85. data/.travis.yml +0 -11
  86. data/lib/charty/backends/google_chart.rb +0 -167
  87. data/lib/charty/plotter_adapter.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3042ae173ae222d23df24223a8ee26487449738db74b1624a7a476ca55f6c57d
4
- data.tar.gz: 214f33498365cb53a561ef688d9f363682540dda9043c959519cbda88257832a
3
+ metadata.gz: 4cf18b5e31bf29099d3d9386b8b022e38013bba339c129a0292af39983e2bccb
4
+ data.tar.gz: 4eb934400a4fc7c60354bf7f7f31e33d4be8cdbdeafb1d47762264d94c8c5a2a
5
5
  SHA512:
6
- metadata.gz: 30241e82d124030645f9f0d8f550f2e11de8e529ecec1d7a602243f773b55304aceca7e3328ee965082dccec38c1fb81e3790b85257a2bad1344cf23efa81ce5
7
- data.tar.gz: 0e537f9f7e868ddd96c602fb98e14d649a2671ea5edab9245b99e5a8c6e235cb13d70209b3c243fcf2d4503ba5887f28aa37a6a88a3888461103b7f0930f09c6
6
+ metadata.gz: 33f5c4ea51ea77a66538e62e43222aaa4f77942b526461ef881cd0ff092eb17a16830937eab032995361a1e7b9e0063e79f682b75fa1c0011644410f02c23b11
7
+ data.tar.gz: cd0c31ae974c4efc6192dc0fa74c93db41cdacac6e5a82cfded9ca1b4285e706c925641df483020d620f22e3aed5fae7263d2364ac0cfb5df35bbf4fc72ad034
@@ -0,0 +1,71 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ types:
9
+ - opened
10
+ - synchronize
11
+ - reopened
12
+
13
+ jobs:
14
+ test:
15
+ name: ${{ matrix.os }}/${{ matrix.ruby }}
16
+ runs-on: ${{ matrix.os }}
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os:
21
+ - ubuntu-20.04
22
+ - ubuntu-18.04
23
+ ruby:
24
+ - "3.0"
25
+ - 2.7
26
+ - 2.6
27
+ include:
28
+ - { os: ubuntu-20.04 , ruby: head }
29
+
30
+ steps:
31
+ - uses: actions/checkout@v2
32
+
33
+ - name: Set up Ruby
34
+ uses: ruby/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.ruby }}
37
+
38
+ - uses: actions/cache@v2
39
+ if: runner.os == 'Linux'
40
+ with:
41
+ path: ~/.cache/red-datasets
42
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
43
+ restore-keys: ${{ runner.os }}-
44
+
45
+ - uses: actions/cache@v2
46
+ if: |
47
+ runner.os == 'macOS'
48
+ with:
49
+ path: |
50
+ ~/Library/Caches/red-datasets
51
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
52
+ restore-keys: ${{ runner.os }}-
53
+
54
+ - uses: actions/cache@v2
55
+ if: |
56
+ runner.os == 'Windows'
57
+ with:
58
+ path: |
59
+ ~/AppData/red-datasets
60
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
61
+ restore-keys: ${{ runner.os }}-
62
+
63
+ - run: sudo apt install build-essential libsqlite3-dev
64
+
65
+ - run: bundle install --jobs 4 --retry 3 --without "nmatrix python"
66
+
67
+ - run: bundle exec rake
68
+
69
+ - run: rake build
70
+
71
+ - run: gem install --user pkg/*.gem
@@ -0,0 +1,67 @@
1
+ name: CI with NMatrix
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ types:
9
+ - opened
10
+ - synchronize
11
+ - reopened
12
+
13
+ jobs:
14
+ test:
15
+ name: ${{ matrix.os }}/${{ matrix.ruby }}
16
+ runs-on: ${{ matrix.os }}
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os:
21
+ - ubuntu-20.04
22
+ ruby:
23
+ - 2.7
24
+ - 2.6
25
+
26
+ steps:
27
+ - uses: actions/checkout@v2
28
+
29
+ - name: Set up Ruby
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby }}
33
+
34
+ - uses: actions/cache@v2
35
+ if: runner.os == 'Linux'
36
+ with:
37
+ path: ~/.cache/red-datasets
38
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
39
+ restore-keys: ${{ runner.os }}-
40
+
41
+ - uses: actions/cache@v2
42
+ if: |
43
+ runner.os == 'macOS'
44
+ with:
45
+ path: |
46
+ ~/Library/Caches/red-datasets
47
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
48
+ restore-keys: ${{ runner.os }}-
49
+
50
+ - uses: actions/cache@v2
51
+ if: |
52
+ runner.os == 'Windows'
53
+ with:
54
+ path: |
55
+ ~/AppData/red-datasets
56
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
57
+ restore-keys: ${{ runner.os }}-
58
+
59
+ - run: sudo apt install build-essential libsqlite3-dev
60
+
61
+ - run: bundle install --jobs 4 --retry 3 --without "numo python"
62
+
63
+ - run: bundle exec rake
64
+
65
+ - run: rake build
66
+
67
+ - run: gem install --user pkg/*.gem
@@ -0,0 +1,86 @@
1
+ name: CI with matplotlib and pandas
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ types:
9
+ - opened
10
+ - synchronize
11
+ - reopened
12
+
13
+ jobs:
14
+ test:
15
+ name: ${{ matrix.os }}/${{ matrix.ruby }}/${{ matrix.python }}-${{ matrix.python_architecture }}
16
+ runs-on: ${{ matrix.os }}
17
+
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ os:
22
+ - ubuntu-20.04
23
+ - ubuntu-18.04
24
+ ruby:
25
+ - "3.0"
26
+ - 2.7
27
+ - 2.6
28
+ python:
29
+ - 3.x
30
+ - 2.x
31
+ python_architecture:
32
+ - x64
33
+ include:
34
+ - { os: ubuntu-20.04 , ruby: head , python: 3.x , python_architecture: x64 }
35
+
36
+ steps:
37
+ - uses: actions/checkout@v2
38
+
39
+ - name: Setup Ruby
40
+ uses: ruby/setup-ruby@v1
41
+ with:
42
+ ruby-version: ${{ matrix.ruby }}
43
+
44
+ - name: Setup Python
45
+ uses: actions/setup-python@v2
46
+ with:
47
+ python-version: ${{ matrix.python }}
48
+ architecture: ${{ matrix.python_architecture }}
49
+
50
+ - uses: actions/cache@v2
51
+ if: runner.os == 'Linux'
52
+ with:
53
+ path: ~/.cache/red-datasets
54
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
55
+ restore-keys: ${{ runner.os }}-
56
+
57
+ - uses: actions/cache@v2
58
+ if: |
59
+ runner.os == 'macOS'
60
+ with:
61
+ path: |
62
+ ~/Library/Caches/red-datasets
63
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
64
+ restore-keys: ${{ runner.os }}-
65
+
66
+ - uses: actions/cache@v2
67
+ if: |
68
+ runner.os == 'Windows'
69
+ with:
70
+ path: |
71
+ ~/AppData/red-datasets
72
+ key: ${{ runner.os }}-${{ hashFiles('lib/**') }}
73
+ restore-keys: ${{ runner.os }}-
74
+
75
+ - run: sudo apt install build-essential libsqlite3-dev
76
+
77
+ - run: pip install --user matplotlib pandas
78
+
79
+ - run: bundle install --jobs 4 --retry 3 --without "nmatrix numo"
80
+
81
+ - run: python -V
82
+
83
+ - run: bundle exec rake
84
+ env:
85
+ PYTHON: python
86
+ continue-on-error: ${{ matrix.python == '2.x' }}
data/Dockerfile.dev CHANGED
@@ -1,2 +1,10 @@
1
- ARG BASE_IMAGE_TAG=c9ca70040856
1
+ ARG BASE_IMAGE_TAG=e1a22a2
2
2
  FROM rubydata/minimal-notebook:$BASE_IMAGE_TAG
3
+
4
+ USER root
5
+ RUN mkdir -p /charty && \
6
+ chown ${NB_USER}:users /charty
7
+
8
+ USER ${NB_USER}
9
+
10
+ WORKDIR /charty
data/Gemfile CHANGED
@@ -4,3 +4,21 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in charty.gemspec
6
6
  gemspec
7
+
8
+ group :cruby do
9
+ gem "enumerable-statistics"
10
+ end
11
+
12
+ group :nmatrix do
13
+ gem "nmatrix"
14
+ end
15
+
16
+ group :numo do
17
+ gem "numo-narray"
18
+ end
19
+
20
+ group :python do
21
+ gem "matplotlib"
22
+ gem "numpy"
23
+ gem "pandas"
24
+ end
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # Charty - Visualizing your data in Ruby
2
2
 
3
- [![Build Status](https://travis-ci.org/red-data-tools/charty.svg?branch=master)](https://travis-ci.org/red-data-tools/charty)
3
+ ![Build Status](https://github.com/red-data-tools/charty/workflows/CI/badge.svg)
4
+ [![Gem Version](https://badge.fury.io/rb/charty.svg)](https://badge.fury.io/rb/charty)
4
5
  [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/red-data-tools/charty/master?filepath=iris_dataset.ipynb)
6
+ [![Docs](https://img.shields.io/badge/docs-stable-blue.svg)](https://rubydoc.info/gems/charty)
5
7
 
6
8
  Charty is open-source Ruby library for visualizing your data in a simple way.
7
9
  In Charty, you need to write very few lines of code for representing what you want to do.
@@ -32,8 +34,8 @@ $ CONFIGURE_OPTS="--enable-shared" pyenv install 3.x.x
32
34
  ### With Matplotlib
33
35
 
34
36
  ```
35
- sudo gem install charty --pre
36
- sudo gem install matplotlib
37
+ gem install charty --pre
38
+ gem install matplotlib
37
39
  sudo apt install python3-pip
38
40
  sudo python3 -m pip install -U pip matplotlib
39
41
  ```
@@ -43,18 +45,183 @@ sudo python3 -m pip install -U pip matplotlib
43
45
  e.g.
44
46
 
45
47
  ```
46
- $ bundle install
47
- $ docker build -f ./Dockerfile.dev -t charty-dev:0.1 .
48
- $ docker run -it -v ${PWD}:/charty -w /charty charty-dev:0.1 ./bin/console
48
+ $ docker build -f ./Dockerfile.dev -t charty-dev:latest .
49
+ $ docker run --rm -v $(pwd):/charty charty-dev:latest bundle install
50
+ $ docker run --rm -it -v $(pwd):/charty charty-dev:latest ./bin/console
49
51
  irb(main):001:0> Charty::VERSION
50
- => "0.1.4-dev"
52
+ => "0.2.2"
51
53
 
52
54
  # When using jupyter notebook
53
- $ docker run -it -v ${PWD}:/charty -w /charty -p 8888:8888 charty-dev:0.1
55
+ $ docker run --rm -it -v $(pwd):/charty -p 8888:8888 charty-dev:latest
54
56
  ```
55
57
 
56
58
  ## Usage
57
59
 
60
+ ### Statistical plotting interface
61
+
62
+ Charty supports statistical plotting as Python's seaborn.
63
+
64
+ In the following examplles, we use the `penguins` dataset provided in red-datasets.
65
+
66
+ ```ruby
67
+ require "datasets"
68
+
69
+ penguins = Datasets::Penguins.new
70
+ ```
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
+
129
+ #### Bar plot
130
+
131
+ Charty's statistical bar plot shows the relationship between a categorical variable and estimated means of a numeric variable.
132
+ This plot automatically calculates mean estimation and its 95% confidence interval of the numeric variable.
133
+
134
+ When we specify the categorical varaible as x-axis, the plot draws a vertical bar chart.
135
+ Instead, when we specify the categorical variable as y-axis, the plot draws a horizontal bar chart.
136
+
137
+ The following code shows the relationship between species and the mean body masses of penguins in a vertical bar chart.
138
+
139
+ ```ruby
140
+ Charty.bar_plot(data: penguins, x: :species, y: :body_mass_g)
141
+ ```
142
+
143
+ ![](images/penguins_species_body_mass_g_bar_plot_v.png)
144
+
145
+ Exchanging x and y axes alternates the orientation of the resulting chart.
146
+
147
+ ```ruby
148
+ Charty.bar_plot(data: penguins, x: :body_mass_g, y: :species)
149
+ ```
150
+
151
+ ![](images/penguins_species_body_mass_g_bar_plot_h.png)
152
+
153
+ Adding color axis introduces color grouping in the bar plot.
154
+
155
+ ```ruby
156
+ Charty.bar_plot(data: penguins, x: :species, y: :body_mass_g, color: :sex)
157
+ ```
158
+
159
+ ![](images/penguins_species_body_mass_g_sex_bar_plot_v.png)
160
+
161
+ #### Box plot
162
+
163
+ Charty's statistical box plot shows distributions of a numeric variable per categories.
164
+ The distributions are showed by boxes with whiskers that characterized by five-number summary.
165
+ This plot automatically calculates five-number summary the numeric variable per categories.
166
+
167
+ When we specify the categorical varaible as x-axis, the plot draws a vertical box plot chart.
168
+ Instead, when we specify the categorical variable as y-axis, the plot draws a horizontal box plot chart.
169
+
170
+ The following code draws a vertical box plot to show distributions of penguins' body mass per species.
171
+
172
+ ```ruby
173
+ Charty.box_plot(data: penguins, x: :species, y: :body_mass_g)
174
+ ```
175
+
176
+ ![](images/penguins_species_body_mass_g_box_plot_v.png)
177
+
178
+ As `bar_plot` above, exchanging x and y axes alternates the orientation of the resulting chart.
179
+
180
+ ```ruby
181
+ Charty.box_plot(data: penguins, x: :body_mass_g, y: :species)
182
+ ```
183
+
184
+ ![](images/penguins_species_body_mass_g_box_plot_h.png)
185
+
186
+ Adding color axis introduces color grouping in the box plot.
187
+
188
+ ```ruby
189
+ Charty.box_plot(data: penguins, x: :species, y: :body_mass_g, color: :sex)
190
+ ```
191
+
192
+ ![](images/penguins_species_body_mass_g_sex_box_plot_v.png)
193
+
194
+ #### Scatter plot
195
+
196
+ Charty's scatter plot shows the relationship between two numeric variables.
197
+
198
+ ```ruby
199
+ Charty.scatter_plot(data: penguins, x: :body_mass_g, y: flipper_length_mm)
200
+ ```
201
+
202
+ ![](images/penguins_body_mass_g_flipper_length_mm_scatter_plot.png)
203
+
204
+ Adding color axis introduces color grouping in the scatter plot.
205
+ The following example specifies `:species` variable in the color axis.
206
+ It shows the different species by the different colors.
207
+
208
+ ```ruby
209
+ Charty.scatter_plot(data: penguins, x: :body_mass_g, y: flipper_length_mm, color: :species)
210
+ ```
211
+
212
+ ![](images/penguins_body_mass_g_flipper_length_mm_species_scatter_plot.png)
213
+
214
+ Moreover, size and style axes can be specified.
215
+ The following example specifies `:sex` variable in the style axis.
216
+
217
+ ```ruby
218
+ Charty.scatter_plot(data: penguins, x: :body_mass_g, y: flipper_length_mm, color: :species, style: :sex)
219
+ ```
220
+
221
+ ![](images/penguins_body_mass_g_flipper_length_mm_species_sex_scatter_plot.png)
222
+
223
+ ### Old-style plotting interface
224
+
58
225
  ```ruby
59
226
  require 'charty'
60
227
  charty = Charty::Plotter.new(:pyplot)
@@ -354,7 +521,7 @@ hist.render("sample_images/hist_pyplot.png")
354
521
 
355
522
  #### Gruff
356
523
 
357
- Not supported
524
+ ![hist_gruff](https://raw.githubusercontent.com/red-data-tools/charty/master/examples/sample_images/hist_gruff.png)
358
525
 
359
526
  #### Rubyplot
360
527