charty 0.2.7 → 0.2.11
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/charty.gemspec +1 -0
- data/examples/bar_plot.rb +19 -0
- data/examples/box_plot.rb +17 -0
- data/examples/scatter_plot.rb +17 -0
- data/images/penguins_body_mass_g_flipper_length_mm_species_scatter_plot.png +0 -0
- data/images/penguins_body_mass_g_flipper_length_mm_species_sex_scatter_plot.png +0 -0
- data/images/penguins_species_body_mass_g_bar_plot_h.png +0 -0
- data/images/penguins_species_body_mass_g_bar_plot_v.png +0 -0
- data/images/penguins_species_body_mass_g_box_plot_h.png +0 -0
- data/images/penguins_species_body_mass_g_box_plot_v.png +0 -0
- data/images/penguins_species_body_mass_g_sex_bar_plot_v.png +0 -0
- data/images/penguins_species_body_mass_g_sex_box_plot_v.png +0 -0
- data/lib/charty/backends/plotly.rb +53 -22
- data/lib/charty/backends/plotly_helpers/notebook_renderer.rb +4 -1
- data/lib/charty/backends/pyplot.rb +73 -0
- data/lib/charty/backends/unicode_plot.rb +16 -11
- data/lib/charty/index.rb +9 -0
- data/lib/charty/plot_methods.rb +46 -10
- data/lib/charty/plotters/abstract_plotter.rb +41 -9
- data/lib/charty/plotters/bar_plotter.rb +39 -0
- data/lib/charty/plotters/categorical_plotter.rb +9 -1
- data/lib/charty/plotters/distribution_plotter.rb +44 -7
- data/lib/charty/plotters/histogram_plotter.rb +97 -35
- data/lib/charty/plotters/line_plotter.rb +38 -5
- data/lib/charty/plotters/scatter_plotter.rb +4 -2
- data/lib/charty/statistics.rb +2 -2
- data/lib/charty/table.rb +30 -23
- data/lib/charty/table_adapters/arrow_adapter.rb +53 -0
- data/lib/charty/table_adapters/base_adapter.rb +88 -0
- data/lib/charty/table_adapters/daru_adapter.rb +41 -1
- data/lib/charty/table_adapters/hash_adapter.rb +58 -10
- data/lib/charty/table_adapters/pandas_adapter.rb +49 -1
- data/lib/charty/table_adapters.rb +1 -0
- data/lib/charty/vector.rb +30 -2
- data/lib/charty/vector_adapters/array_adapter.rb +1 -1
- data/lib/charty/vector_adapters/arrow_adapter.rb +156 -0
- data/lib/charty/vector_adapters/daru_adapter.rb +3 -6
- data/lib/charty/vector_adapters/narray_adapter.rb +10 -1
- data/lib/charty/vector_adapters/nmatrix_adapter.rb +1 -5
- data/lib/charty/vector_adapters/numpy_adapter.rb +4 -0
- data/lib/charty/vector_adapters/pandas_adapter.rb +10 -1
- data/lib/charty/vector_adapters/vector_adapter.rb +62 -0
- data/lib/charty/vector_adapters.rb +22 -0
- data/lib/charty/version.rb +1 -1
- metadata +23 -3
@@ -35,6 +35,8 @@ module Charty
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def data=(data)
|
38
|
+
# TODO: Convert a Charty::Vector to a Charty::Table so that
|
39
|
+
# the Charty::Vector is handled as a wide form data
|
38
40
|
@data = case data
|
39
41
|
when nil, Charty::Table
|
40
42
|
data
|
@@ -81,6 +83,24 @@ module Charty
|
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
86
|
+
attr_reader :x_label
|
87
|
+
|
88
|
+
def x_label=(val)
|
89
|
+
@x_label = check_string(val, :x_label, allow_nil: true)
|
90
|
+
end
|
91
|
+
|
92
|
+
attr_reader :y_label
|
93
|
+
|
94
|
+
def y_label=(val)
|
95
|
+
@y_label = check_string(val, :y_label, allow_nil: true)
|
96
|
+
end
|
97
|
+
|
98
|
+
attr_reader :title
|
99
|
+
|
100
|
+
def title=(val)
|
101
|
+
@title = check_string(val, :title, allow_nil: true)
|
102
|
+
end
|
103
|
+
|
84
104
|
private def substitute_options(options)
|
85
105
|
options.each do |key, val|
|
86
106
|
send("#{key}=", val)
|
@@ -138,6 +158,27 @@ module Charty
|
|
138
158
|
end
|
139
159
|
end
|
140
160
|
|
161
|
+
private def check_string(value, name, allow_nil: false)
|
162
|
+
case value
|
163
|
+
when Symbol
|
164
|
+
value.to_s
|
165
|
+
else
|
166
|
+
if allow_nil && value.nil?
|
167
|
+
nil
|
168
|
+
else
|
169
|
+
orig_value = value
|
170
|
+
value = String.try_convert(value)
|
171
|
+
if value.nil?
|
172
|
+
raise ArgumentError,
|
173
|
+
"`#{name}` must be convertible to String: %p" % orig_value,
|
174
|
+
caller
|
175
|
+
else
|
176
|
+
value
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
141
182
|
private def variable_type(vector, boolean_type=:numeric)
|
142
183
|
if vector.numeric?
|
143
184
|
:numeric
|
@@ -181,15 +222,6 @@ module Charty
|
|
181
222
|
data = processed ? processed_data : plot_data
|
182
223
|
data = data.drop_na if drop_na
|
183
224
|
|
184
|
-
levels = var_levels.dup
|
185
|
-
|
186
|
-
([:x, :y] & grouping_vars).each do |axis|
|
187
|
-
levels[axis] = plot_data[axis].categorical_order()
|
188
|
-
if processed
|
189
|
-
# TODO: perform inverse conversion of axis scaling here
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
225
|
if not grouping_vars.empty?
|
194
226
|
grouped = data.group_by(grouping_vars, sort: false)
|
195
227
|
grouped.each_group do |group_key, group_data|
|
@@ -42,6 +42,12 @@ module Charty
|
|
42
42
|
@cap_size = check_number(cap_size, :cap_size, allow_nil: true)
|
43
43
|
end
|
44
44
|
|
45
|
+
attr_reader :log
|
46
|
+
|
47
|
+
def log=(val)
|
48
|
+
@log = check_boolean(val, :log)
|
49
|
+
end
|
50
|
+
|
45
51
|
private def render_plot(backend, **)
|
46
52
|
draw_bars(backend)
|
47
53
|
annotate_axes(backend)
|
@@ -81,6 +87,39 @@ module Charty
|
|
81
87
|
end
|
82
88
|
end
|
83
89
|
|
90
|
+
private def annotate_axes(backend)
|
91
|
+
super
|
92
|
+
|
93
|
+
if self.log
|
94
|
+
min_value, max_value = @estimations.minmax
|
95
|
+
if @plot_colors
|
96
|
+
unless @conf_int.empty?
|
97
|
+
min_value = [min_value, @conf_int[0]].min
|
98
|
+
max_value = [max_value, @conf_int[1]].max
|
99
|
+
end
|
100
|
+
else
|
101
|
+
ci_min = Util.filter_map(@conf_int) { |ci| ci[0] unless ci.empty? }
|
102
|
+
ci_max = Util.filter_map(@conf_int) { |ci| ci[1] unless ci.empty? }
|
103
|
+
min_value = [min_value, ci_min.min].min unless ci_min.empty?
|
104
|
+
max_value = [max_value, ci_max.max].max unless ci_max.empty?
|
105
|
+
end
|
106
|
+
if min_value > 1
|
107
|
+
min_value = 0
|
108
|
+
else
|
109
|
+
min_value = Math.log10(min_value).floor
|
110
|
+
end
|
111
|
+
max_value = Math.log10(max_value).ceil
|
112
|
+
case self.orient
|
113
|
+
when :v
|
114
|
+
backend.set_yscale(:log)
|
115
|
+
backend.set_ylim(min_value, max_value)
|
116
|
+
else
|
117
|
+
backend.set_xscale(:log)
|
118
|
+
backend.set_xlim(min_value, max_value)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
84
123
|
private def setup_estimations
|
85
124
|
if @color_names.nil?
|
86
125
|
setup_estimations_with_single_color_group
|
@@ -134,6 +134,7 @@ module Charty
|
|
134
134
|
order = @order # TODO: supply order via parameter
|
135
135
|
unless order
|
136
136
|
order = @data.column_names.select do |cn|
|
137
|
+
# TODO: Use Charty::Vector#numeric?
|
137
138
|
@data[cn].all? {|x| Float(x, exception: false) }
|
138
139
|
end
|
139
140
|
end
|
@@ -230,6 +231,7 @@ module Charty
|
|
230
231
|
end
|
231
232
|
return :h
|
232
233
|
end
|
234
|
+
|
233
235
|
case orient
|
234
236
|
when :v
|
235
237
|
if require_numeric && y_type != :numeric
|
@@ -263,7 +265,9 @@ module Charty
|
|
263
265
|
private def group_long_form(vals, groups, group_order)
|
264
266
|
grouped_vals = vals.group_by(groups)
|
265
267
|
|
266
|
-
plot_data = group_order.map
|
268
|
+
plot_data = group_order.map do |g|
|
269
|
+
grouped_vals[g] || Charty::Vector.new([])
|
270
|
+
end
|
267
271
|
|
268
272
|
if vals.respond_to?(:name)
|
269
273
|
value_label = vals.name
|
@@ -347,11 +351,15 @@ module Charty
|
|
347
351
|
end
|
348
352
|
|
349
353
|
private def annotate_axes(backend)
|
354
|
+
backend.set_title(self.title) if self.title
|
355
|
+
|
350
356
|
if orient == :v
|
351
357
|
xlabel, ylabel = @group_label, @value_label
|
352
358
|
else
|
353
359
|
xlabel, ylabel = @value_label, @group_label
|
354
360
|
end
|
361
|
+
xlabel = self.x_label if self.x_label
|
362
|
+
ylabel = self.y_label if self.y_label
|
355
363
|
backend.set_xlabel(xlabel) unless xlabel.nil?
|
356
364
|
backend.set_ylabel(ylabel) unless ylabel.nil?
|
357
365
|
|
@@ -3,7 +3,14 @@ module Charty
|
|
3
3
|
class DistributionPlotter < AbstractPlotter
|
4
4
|
def flat_structure
|
5
5
|
{
|
6
|
-
x:
|
6
|
+
x: :@values
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
def wide_structure
|
11
|
+
{
|
12
|
+
x: :@values,
|
13
|
+
color: :@columns
|
7
14
|
}
|
8
15
|
end
|
9
16
|
|
@@ -14,6 +21,12 @@ module Charty
|
|
14
21
|
setup_variables
|
15
22
|
end
|
16
23
|
|
24
|
+
attr_reader :weights
|
25
|
+
|
26
|
+
def weights=(val)
|
27
|
+
@weights = check_dimension(val, :weights)
|
28
|
+
end
|
29
|
+
|
17
30
|
attr_reader :variables
|
18
31
|
|
19
32
|
attr_reader :color_norm
|
@@ -65,7 +78,6 @@ module Charty
|
|
65
78
|
return
|
66
79
|
end
|
67
80
|
|
68
|
-
# TODO: detect flat data
|
69
81
|
flat = data.is_a?(Charty::Vector)
|
70
82
|
if flat
|
71
83
|
@plot_data = {}
|
@@ -73,10 +85,10 @@ module Charty
|
|
73
85
|
|
74
86
|
[:x, :y].each do |var|
|
75
87
|
case self.flat_structure[var]
|
76
|
-
when
|
88
|
+
when :@index
|
77
89
|
@plot_data[var] = data.index.to_a
|
78
90
|
@variables[var] = data.index.name
|
79
|
-
when
|
91
|
+
when :@values
|
80
92
|
@plot_data[var] = data.to_a
|
81
93
|
@variables[var] = data.name
|
82
94
|
end
|
@@ -84,8 +96,32 @@ module Charty
|
|
84
96
|
|
85
97
|
@plot_data = Charty::Table.new(@plot_data)
|
86
98
|
else
|
87
|
-
|
88
|
-
|
99
|
+
numeric_columns = @data.column_names.select do |cn|
|
100
|
+
@data[cn].numeric?
|
101
|
+
end
|
102
|
+
wide_data = @data[numeric_columns]
|
103
|
+
|
104
|
+
melt_params = {var_name: :@columns, value_name: :@values }
|
105
|
+
if self.wide_structure.include?(:index)
|
106
|
+
melt_params[:id_vars] = :@index
|
107
|
+
end
|
108
|
+
|
109
|
+
@plot_data = wide_data.melt(**melt_params)
|
110
|
+
@variables = {}
|
111
|
+
self.wide_structure.each do |var, attr|
|
112
|
+
@plot_data[var] = @plot_data[attr]
|
113
|
+
|
114
|
+
@variables[var] = case attr
|
115
|
+
when :@columns
|
116
|
+
wide_data.columns.name
|
117
|
+
when :@index
|
118
|
+
wide_data.index.name
|
119
|
+
else
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
@plot_data = @plot_data[self.wide_structure.keys]
|
89
125
|
end
|
90
126
|
end
|
91
127
|
|
@@ -103,10 +139,11 @@ module Charty
|
|
103
139
|
x: self.x,
|
104
140
|
y: self.y,
|
105
141
|
color: self.color,
|
142
|
+
weights: self.weights
|
106
143
|
}.each do |key, val|
|
107
144
|
next if val.nil?
|
108
145
|
|
109
|
-
if data.
|
146
|
+
if data.column?(val)
|
110
147
|
plot_data[key] = data[val]
|
111
148
|
variables[key] = val
|
112
149
|
else
|
@@ -12,16 +12,6 @@ module Charty
|
|
12
12
|
([:x, :y] & self.variables.keys)[0]
|
13
13
|
end
|
14
14
|
|
15
|
-
attr_reader :weights
|
16
|
-
|
17
|
-
def weights=(val)
|
18
|
-
@weights = check_weights(val)
|
19
|
-
end
|
20
|
-
|
21
|
-
private def check_weights(val)
|
22
|
-
raise NotImplementedError, "weights is not supported yet"
|
23
|
-
end
|
24
|
-
|
25
15
|
attr_reader :stat
|
26
16
|
|
27
17
|
def stat=(val)
|
@@ -65,10 +55,44 @@ module Charty
|
|
65
55
|
end
|
66
56
|
|
67
57
|
# TODO: bin_width
|
68
|
-
|
58
|
+
|
59
|
+
attr_reader :bin_range
|
60
|
+
|
61
|
+
def bin_range=(val)
|
62
|
+
@bin_range = check_bin_range(val)
|
63
|
+
end
|
64
|
+
|
65
|
+
private def check_bin_range(val)
|
66
|
+
case val
|
67
|
+
when nil, Range
|
68
|
+
return val
|
69
|
+
when Array
|
70
|
+
if val.length == 2
|
71
|
+
val.each_with_index do |v, i|
|
72
|
+
check_number(v, "bin_range[#{i}]")
|
73
|
+
end
|
74
|
+
return val
|
75
|
+
else
|
76
|
+
amount = val.length < 2 ? "few" : "many"
|
77
|
+
raise ArgumentError,
|
78
|
+
"Too #{amount} items in `bin_range` array (%p for 2)" % val.length
|
79
|
+
end
|
80
|
+
else
|
81
|
+
raise ArgumentError,
|
82
|
+
"Invalid value for `bin_range` " +
|
83
|
+
"(%p for a range or a pair of numbers)" % val
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
69
87
|
# TODO: discrete
|
70
88
|
# TODO: cumulative
|
71
|
-
|
89
|
+
|
90
|
+
attr_reader :common_bins
|
91
|
+
|
92
|
+
def common_bins=(val)
|
93
|
+
@common_bins = check_boolean(val, :common_bins)
|
94
|
+
end
|
95
|
+
|
72
96
|
# TODO: common_norm
|
73
97
|
|
74
98
|
attr_reader :multiple
|
@@ -127,24 +151,52 @@ module Charty
|
|
127
151
|
private def draw_univariate_histogram(backend)
|
128
152
|
map_color(palette: palette, order: color_order, norm: color_norm)
|
129
153
|
|
154
|
+
key_color = self.key_color
|
155
|
+
if key_color.nil? && !self.variables.key?(:color)
|
156
|
+
palette = case self.palette
|
157
|
+
when Palette
|
158
|
+
self.palette
|
159
|
+
when nil
|
160
|
+
Palette.default
|
161
|
+
else
|
162
|
+
Palette[self.palette]
|
163
|
+
end
|
164
|
+
key_color = palette[0]
|
165
|
+
end
|
166
|
+
|
130
167
|
# TODO: calculate histogram here and use bar plot to visualize
|
131
168
|
data_variable = self.univariate_variable
|
132
169
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
170
|
+
if common_bins
|
171
|
+
all_data = processed_data.drop_na
|
172
|
+
all_observations = all_data[data_variable].to_a
|
173
|
+
|
174
|
+
bins = self.bins
|
175
|
+
bins = 10 if self.variables.key?(:color) && bins == :auto
|
176
|
+
|
177
|
+
case bins
|
178
|
+
when Integer
|
179
|
+
case bin_range
|
180
|
+
when Range
|
181
|
+
start = bin_range.begin
|
182
|
+
stop = bin_range.end
|
183
|
+
when Array
|
184
|
+
start, stop = bin_range.minmax
|
185
|
+
end
|
186
|
+
data_range = all_observations.minmax
|
187
|
+
start ||= data_range[0]
|
188
|
+
stop ||= data_range[1]
|
189
|
+
if start == stop
|
190
|
+
start -= 0.5
|
191
|
+
stop += 0.5
|
192
|
+
end
|
193
|
+
common_bin_edges = Linspace.new(start .. stop, bins + 1).map(&:to_f)
|
194
|
+
else
|
195
|
+
params = {}
|
196
|
+
params[:weights] = all_data[:weights].to_a if all_data.column?(:weights)
|
197
|
+
h = Statistics.histogram(all_observations, bins, **params)
|
198
|
+
common_bin_edges = h.edges
|
199
|
+
end
|
148
200
|
end
|
149
201
|
|
150
202
|
if self.variables.key?(:color)
|
@@ -154,27 +206,37 @@ module Charty
|
|
154
206
|
end
|
155
207
|
|
156
208
|
each_subset([:color], processed: true) do |sub_vars, sub_data|
|
157
|
-
name = sub_vars[:color]
|
158
209
|
observations = sub_data[data_variable].drop_na.to_a
|
210
|
+
params = {}
|
211
|
+
params[:weights] = sub_data[:weights].to_a if sub_data.column?(:weights)
|
212
|
+
params[:edges] = common_bin_edges if common_bin_edges
|
213
|
+
hist = Statistics.histogram(observations, bins, **params)
|
159
214
|
|
160
|
-
|
161
|
-
|
162
|
-
name, @color_mapper
|
215
|
+
name = sub_vars[:color]
|
216
|
+
backend.univariate_histogram(hist, name, data_variable, stat,
|
217
|
+
alpha, name, key_color, @color_mapper,
|
218
|
+
multiple, :bars, true, 1r)
|
163
219
|
end
|
164
220
|
end
|
165
221
|
|
166
222
|
private def annotate_axes(backend)
|
223
|
+
backend.set_title(self.title) if self.title
|
224
|
+
|
167
225
|
if univariate?
|
168
|
-
xlabel = self.variables[:x]
|
169
|
-
ylabel = self.variables[:y]
|
226
|
+
xlabel = self.x_label || self.variables[:x]
|
227
|
+
ylabel = self.y_label || self.variables[:y]
|
170
228
|
case self.univariate_variable
|
171
229
|
when :x
|
172
|
-
ylabel
|
230
|
+
ylabel ||= self.stat.to_s.capitalize
|
173
231
|
else
|
174
|
-
xlabel
|
232
|
+
xlabel ||= self.stat.to_s.capitalize
|
175
233
|
end
|
176
234
|
backend.set_ylabel(ylabel) if ylabel
|
177
235
|
backend.set_xlabel(xlabel) if xlabel
|
236
|
+
|
237
|
+
if self.variables.key?(:color)
|
238
|
+
backend.legend(loc: :best, title: self.variables[:color])
|
239
|
+
end
|
178
240
|
end
|
179
241
|
end
|
180
242
|
end
|
@@ -122,7 +122,7 @@ module Charty
|
|
122
122
|
|
123
123
|
include RandomSupport
|
124
124
|
|
125
|
-
attr_reader :sort, :err_style, :err_kws, :error_bar
|
125
|
+
attr_reader :sort, :err_style, :err_kws, :error_bar
|
126
126
|
|
127
127
|
def sort=(val)
|
128
128
|
@sort = check_boolean(val, :sort)
|
@@ -211,17 +211,21 @@ module Charty
|
|
211
211
|
[method, level]
|
212
212
|
end
|
213
213
|
|
214
|
+
attr_reader :x_scale
|
215
|
+
|
214
216
|
def x_scale=(val)
|
215
217
|
@x_scale = check_axis_scale(val, :x)
|
216
218
|
end
|
217
219
|
|
220
|
+
attr_reader :y_scale
|
221
|
+
|
218
222
|
def y_scale=(val)
|
219
223
|
@y_scale = check_axis_scale(val, :y)
|
220
224
|
end
|
221
225
|
|
222
226
|
private def check_axis_scale(val, axis)
|
223
227
|
case val
|
224
|
-
when :linear, "linear", :
|
228
|
+
when :linear, "linear", :log, "log"
|
225
229
|
val.to_sym
|
226
230
|
else
|
227
231
|
raise ArgumentError,
|
@@ -252,6 +256,15 @@ module Charty
|
|
252
256
|
sub_data = sub_data.sort_values(sort_cols)
|
253
257
|
end
|
254
258
|
|
259
|
+
# Perform axis scaling
|
260
|
+
if x_scale != :linear
|
261
|
+
sub_data[:x] = sub_data[:x].scale(x_scale)
|
262
|
+
end
|
263
|
+
if y_scale != :linear
|
264
|
+
sub_data[:y] = sub_data[:y].scale(x_scale)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Perform estimation and error calculation
|
255
268
|
unless estimator.nil?
|
256
269
|
if self.variables.include?(:units)
|
257
270
|
raise "`estimator` is must be nil when specifying `units`"
|
@@ -261,7 +274,22 @@ module Charty
|
|
261
274
|
sub_data = grouped.apply(agg_var, &aggregator.method(:aggregate)).reset_index
|
262
275
|
end
|
263
276
|
|
264
|
-
#
|
277
|
+
# Perform axis inverse scaling
|
278
|
+
if x_scale != :linear
|
279
|
+
sub_data.column_names.each do |cn|
|
280
|
+
if cn.start_with?("x")
|
281
|
+
sub_data[cn] = sub_data[cn].scale_inverse(x_scale)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
if y_scale != :linear
|
287
|
+
sub_data.column_names.each do |cn|
|
288
|
+
if cn.start_with?("y")
|
289
|
+
sub_data[cn] = sub_data[cn].scale_inverse(x_scale)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
265
293
|
|
266
294
|
unit_grouping = if self.variables.include?(:units)
|
267
295
|
sub_data.group_by(:units).each_group
|
@@ -290,10 +318,15 @@ module Charty
|
|
290
318
|
end
|
291
319
|
|
292
320
|
private def annotate_axes(backend)
|
293
|
-
|
294
|
-
|
321
|
+
backend.set_title(self.title) if self.title
|
322
|
+
|
323
|
+
xlabel = self.x_label || self.variables[:x]
|
324
|
+
ylabel = self.y_label || self.variables[:y]
|
295
325
|
backend.set_xlabel(xlabel) unless xlabel.nil?
|
296
326
|
backend.set_ylabel(ylabel) unless ylabel.nil?
|
327
|
+
|
328
|
+
backend.set_xscale(x_scale)
|
329
|
+
backend.set_yscale(y_scale)
|
297
330
|
end
|
298
331
|
end
|
299
332
|
end
|