charty 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/charty.gemspec +1 -0
- data/lib/charty/backends/plotly.rb +23 -18
- data/lib/charty/backends/pyplot.rb +43 -0
- data/lib/charty/plot_methods.rb +5 -3
- data/lib/charty/plotters/distribution_plotter.rb +7 -0
- data/lib/charty/plotters/histogram_plotter.rb +91 -35
- data/lib/charty/table_adapters/hash_adapter.rb +5 -0
- data/lib/charty/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37ead1e86203bd6580125f4ed97039c6b512e9ae3037a0bc386743ee436f184c
|
4
|
+
data.tar.gz: a94e66292a866acde67c0cfc51bd8eebd5840af68e2d4112caafce80bdd37ed2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b518be17e0ae85405285fe22022bc698d0c080e08a0682f055ae70c97655ed313038e6e2899b7c961bd73c0afe1b6b0c25bdb2085bd3a66dddd57d3e6245df55
|
7
|
+
data.tar.gz: 0bc460c78d178b098c65ab8737efddac0a8484abd920282d185533b72396f0abad62ea247be9e8af4286a70b7a4dc2069e88ff1675ba446af65b5c67edfb59d8
|
data/charty.gemspec
CHANGED
@@ -569,30 +569,35 @@ module Charty
|
|
569
569
|
probability: "probability".freeze
|
570
570
|
}.freeze
|
571
571
|
|
572
|
-
def univariate_histogram(
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
572
|
+
def univariate_histogram(hist, name, variable_name, stat,
|
573
|
+
alpha, color, key_color, color_mapper,
|
574
|
+
_multiple, _element, _fill, _shrink)
|
575
|
+
value_axis = variable_name
|
576
|
+
case value_axis
|
577
|
+
when :x
|
578
|
+
weights_axis = :y
|
579
|
+
orientation = :v
|
580
|
+
else
|
581
|
+
weights_axis = :x
|
582
|
+
orientation = :h
|
583
|
+
end
|
584
|
+
|
585
|
+
mid_points = hist.edges.each_cons(2).map {|a, b| a + (b - a) / 2 }
|
586
|
+
|
581
587
|
trace = {
|
582
|
-
type:
|
588
|
+
type: :bar,
|
583
589
|
name: name.to_s,
|
584
|
-
|
590
|
+
value_axis => mid_points,
|
591
|
+
weights_axis => hist.weights,
|
585
592
|
orientation: orientation,
|
586
|
-
histnorm: PLOTLY_HISTNORM[stat],
|
587
|
-
"#{variable_name}bins": {
|
588
|
-
start: bin_start,
|
589
|
-
end: bin_end,
|
590
|
-
size: bin_size
|
591
|
-
},
|
592
593
|
opacity: alpha
|
593
594
|
}
|
594
595
|
|
595
|
-
if color
|
596
|
+
if color.nil?
|
597
|
+
trace[:marker] = {
|
598
|
+
color: key_color.to_rgb.to_hex_string
|
599
|
+
}
|
600
|
+
else
|
596
601
|
trace[:marker] = {
|
597
602
|
color: color_mapper[color].to_rgb.to_hex_string
|
598
603
|
}
|
@@ -14,6 +14,7 @@ module Charty
|
|
14
14
|
|
15
15
|
def initialize
|
16
16
|
@pyplot = ::Matplotlib::Pyplot
|
17
|
+
@default_edgecolor = Colors["white"].to_rgb
|
17
18
|
@default_line_width = ::Matplotlib.rcParams["lines.linewidth"]
|
18
19
|
@default_marker_size = ::Matplotlib.rcParams["lines.markersize"]
|
19
20
|
end
|
@@ -575,6 +576,47 @@ module Charty
|
|
575
576
|
min + x * (max - min)
|
576
577
|
end
|
577
578
|
|
579
|
+
def univariate_histogram(hist, name, variable_name, stat,
|
580
|
+
alpha, color, key_color, color_mapper,
|
581
|
+
multiple, element, fill, shrink)
|
582
|
+
mid_points = hist.edges.each_cons(2).map {|a, b| a + (b - a) / 2 }
|
583
|
+
orient = variable_name == :x ? :v : :h
|
584
|
+
width = shrink * (hist.edges[1] - hist.edges[0])
|
585
|
+
|
586
|
+
kw = {align: :edge}
|
587
|
+
|
588
|
+
color = if color.nil?
|
589
|
+
key_color.to_rgb
|
590
|
+
else
|
591
|
+
color_mapper[color].to_rgb
|
592
|
+
end
|
593
|
+
|
594
|
+
alpha = 1r unless fill
|
595
|
+
|
596
|
+
if fill
|
597
|
+
kw[:facecolor] = color.to_rgba(alpha: alpha).to_hex_string
|
598
|
+
if multiple == :stack || multiple == :fill || element == :bars
|
599
|
+
kw[:edgecolor] = @default_edgecolor.to_hex_string
|
600
|
+
else
|
601
|
+
kw[:edgecolor] = color.to_hex_string
|
602
|
+
end
|
603
|
+
elsif element == :bars
|
604
|
+
kw.delete(:facecolor)
|
605
|
+
kw[:edgecolor] = color.to_rgba(alpha: alpha).to_hex_string
|
606
|
+
else
|
607
|
+
kw[:color] = color.to_rgba(alpha: alpha).to_hex_string
|
608
|
+
end
|
609
|
+
|
610
|
+
kw[:label] = name unless name.nil?
|
611
|
+
|
612
|
+
ax = @pyplot.gca
|
613
|
+
if orient == :v
|
614
|
+
ax.bar(mid_points, hist.weights, width, **kw)
|
615
|
+
else
|
616
|
+
ax.barh(mid_points, hist.weights, width, **kw)
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
578
620
|
private def locator_to_legend_entries(locator, limits)
|
579
621
|
vmin, vmax = limits
|
580
622
|
dtype = case vmin
|
@@ -686,6 +728,7 @@ module Charty
|
|
686
728
|
params[key] = kwargs[key] if kwargs.key?(key)
|
687
729
|
end
|
688
730
|
@pyplot.savefig(filename, **params)
|
731
|
+
@pyplot.close
|
689
732
|
end
|
690
733
|
|
691
734
|
def show
|
data/lib/charty/plot_methods.rb
CHANGED
@@ -249,17 +249,16 @@ module Charty
|
|
249
249
|
)
|
250
250
|
end
|
251
251
|
|
252
|
-
def hist_plot(data: nil, x: nil, y: nil, color: nil,
|
252
|
+
def hist_plot(data: nil, x: nil, y: nil, color: nil, weights: nil,
|
253
253
|
stat: :count, bins: :auto,
|
254
|
+
bin_range: nil, common_bins: true,
|
254
255
|
key_color: nil, palette: nil, color_order: nil, color_norm: nil,
|
255
256
|
legend: true, **options, &block)
|
256
257
|
# TODO: support following arguments
|
257
258
|
# - wiehgts
|
258
259
|
# - binwidth
|
259
|
-
# - binrange
|
260
260
|
# - discrete
|
261
261
|
# - cumulative
|
262
|
-
# - common_bins
|
263
262
|
# - common_norm
|
264
263
|
# - multiple
|
265
264
|
# - element
|
@@ -278,8 +277,11 @@ module Charty
|
|
278
277
|
Plotters::HistogramPlotter.new(
|
279
278
|
data: data,
|
280
279
|
variables: { x: x, y: y, color: color },
|
280
|
+
weights: weights,
|
281
281
|
stat: stat,
|
282
282
|
bins: bins,
|
283
|
+
bin_range: bin_range,
|
284
|
+
common_bins: common_bins,
|
283
285
|
key_color: key_color,
|
284
286
|
palette: palette,
|
285
287
|
color_order: color_order,
|
@@ -14,6 +14,12 @@ module Charty
|
|
14
14
|
setup_variables
|
15
15
|
end
|
16
16
|
|
17
|
+
attr_reader :weights
|
18
|
+
|
19
|
+
def weights=(val)
|
20
|
+
@weights = check_dimension(val, :weights)
|
21
|
+
end
|
22
|
+
|
17
23
|
attr_reader :variables
|
18
24
|
|
19
25
|
attr_reader :color_norm
|
@@ -103,6 +109,7 @@ module Charty
|
|
103
109
|
x: self.x,
|
104
110
|
y: self.y,
|
105
111
|
color: self.color,
|
112
|
+
weights: self.weights
|
106
113
|
}.each do |key, val|
|
107
114
|
next if val.nil?
|
108
115
|
|
@@ -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,28 +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
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
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
|
152
200
|
end
|
153
201
|
|
154
202
|
if self.variables.key?(:color)
|
@@ -158,12 +206,16 @@ module Charty
|
|
158
206
|
end
|
159
207
|
|
160
208
|
each_subset([:color], processed: true) do |sub_vars, sub_data|
|
161
|
-
name = sub_vars[:color]
|
162
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)
|
163
214
|
|
164
|
-
|
165
|
-
|
166
|
-
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)
|
167
219
|
end
|
168
220
|
end
|
169
221
|
|
@@ -179,6 +231,10 @@ module Charty
|
|
179
231
|
end
|
180
232
|
backend.set_ylabel(ylabel) if ylabel
|
181
233
|
backend.set_xlabel(xlabel) if xlabel
|
234
|
+
|
235
|
+
if self.variables.key?(:color)
|
236
|
+
backend.legend(loc: :best, title: self.variables[:color])
|
237
|
+
end
|
182
238
|
end
|
183
239
|
end
|
184
240
|
end
|
@@ -20,6 +20,8 @@ module Charty
|
|
20
20
|
end
|
21
21
|
when Hash
|
22
22
|
true
|
23
|
+
when ->(x) { defined?(CSV::Table) && x.is_a?(CSV::Table) }
|
24
|
+
true
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
@@ -79,6 +81,9 @@ module Charty
|
|
79
81
|
else
|
80
82
|
unsupported_data_format
|
81
83
|
end
|
84
|
+
when ->(x) { defined?(CSV::Table) && x.is_a?(CSV::Table) }
|
85
|
+
columns ||= data.headers
|
86
|
+
arrays = data.headers.map {|x| data[x] }
|
82
87
|
else
|
83
88
|
unsupported_data_format
|
84
89
|
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.9
|
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-06-
|
13
|
+
date: 2021-06-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: red-colors
|
@@ -208,6 +208,20 @@ dependencies:
|
|
208
208
|
- - ">="
|
209
209
|
- !ruby/object:Gem::Version
|
210
210
|
version: 0.7.0
|
211
|
+
- !ruby/object:Gem::Dependency
|
212
|
+
name: csv
|
213
|
+
requirement: !ruby/object:Gem::Requirement
|
214
|
+
requirements:
|
215
|
+
- - ">="
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: '0'
|
218
|
+
type: :development
|
219
|
+
prerelease: false
|
220
|
+
version_requirements: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - ">="
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: '0'
|
211
225
|
description: Visualizing your data in a simple way.
|
212
226
|
email:
|
213
227
|
- youchan01@gmail.com
|