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 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