charty 0.2.8 → 0.2.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c245a8324486b73226c85162c602997c5b8e4f41c6fc03d731cd7c8c0e0c763
4
- data.tar.gz: 720f08fdcf14ac5da11eace6f684d002c694de1d1b062fa9b954da4a286ae810
3
+ metadata.gz: 37ead1e86203bd6580125f4ed97039c6b512e9ae3037a0bc386743ee436f184c
4
+ data.tar.gz: a94e66292a866acde67c0cfc51bd8eebd5840af68e2d4112caafce80bdd37ed2
5
5
  SHA512:
6
- metadata.gz: 253bf7b26d3ee72fe604afb4cdf50de412aa956171dc6671c33a158e2252597f71005fbbccb0f879f11688327339bf569f653f15eef6ac30faa4c0173765d607
7
- data.tar.gz: b3cbfbd190a145c41db3d3fec8050f9ec4b9ddc12d978fb2c96a3a825409b708c8c0d6f14456ed0bf17f2c8150999ec063a1898d97b37c3e984a88645adc0d4b
6
+ metadata.gz: b518be17e0ae85405285fe22022bc698d0c080e08a0682f055ae70c97655ed313038e6e2899b7c961bd73c0afe1b6b0c25bdb2085bd3a66dddd57d3e6245df55
7
+ data.tar.gz: 0bc460c78d178b098c65ab8737efddac0a8484abd920282d185533b72396f0abad62ea247be9e8af4286a70b7a4dc2069e88ff1675ba446af65b5c67edfb59d8
data/charty.gemspec CHANGED
@@ -42,4 +42,5 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency "activerecord"
43
43
  spec.add_development_dependency "sqlite3"
44
44
  spec.add_development_dependency "iruby", ">= 0.7.0"
45
+ spec.add_development_dependency "csv"
45
46
  end
@@ -569,30 +569,35 @@ module Charty
569
569
  probability: "probability".freeze
570
570
  }.freeze
571
571
 
572
- def univariate_histogram(data, name, variable_name, stat,
573
- bin_start, bin_end, bin_size, alpha,
574
- color, color_mapper)
575
- orientation = case variable_name
576
- when :x
577
- :v
578
- else
579
- :h
580
- end
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: "histogram",
588
+ type: :bar,
583
589
  name: name.to_s,
584
- variable_name => data.to_a,
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
@@ -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
- # TODO: bin_range
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
- # TODO: common_bins
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
- histograms = {}
134
- each_subset([:color], processed: true) do |sub_vars, sub_data|
135
- key = sub_vars.to_a
136
- observations = sub_data[data_variable].drop_na.to_a
137
- hist = if bins != :auto
138
- Statistics.histogram(observations, bins)
139
- else
140
- Statistics.histogram(observations)
141
- end
142
- histograms[key] = hist
143
- end
144
-
145
- bin_start, bin_end, bin_size = nil
146
- histograms.each do |_, hist|
147
- s, e = hist.edge.minmax
148
- z = (e - s).to_f / (hist.edge.length - 1)
149
- bin_start = [bin_start, s].compact.min
150
- bin_end = [bin_end, e].compact.max
151
- bin_size = [bin_size, z].compact.min
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
- backend.univariate_histogram(observations, name, data_variable, stat,
165
- bin_start, bin_end, bin_size, alpha,
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
@@ -1,5 +1,5 @@
1
1
  module Charty
2
- VERSION = "0.2.8"
2
+ VERSION = "0.2.9"
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.2.8
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-22 00:00:00.000000000 Z
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