Class: CAGroupIterator
- Inherits:
-
Object
- Object
- CAGroupIterator
- Defined in:
- lib/carray/axis_group.rb
Overview
Let the C [] type gate (ext/ca_group_iter.c) recognise these classes without
a kind_of on every index. Registered once on first load of this file, which
happens either eagerly (a axis_group / AxisGroup call) or lazily from the C
gate itself the first time it meets a fixlen-surface CArray index (see
ca_argv_has_group). CACategorical is the classifier, so it must be defined
before the register call.
CAGroupIterator (C-defined in ext/ca_group_iter.c) — the reduction dispatcher
returned by the [] group gate. Its scatterable reductions (sum / prod / mean
/ min / max / variance / stddev / variancep / stddevp / count /
count_not_masked / all / any) bind in C to one driver; the rest of the common
iterator surface that composes cheaply from those is added here.
Instance Method Summary collapse
-
#count_masked(**kw) ⇒ Object
Per-group count of value-masked cells = elements - count_not_masked.
-
#cumcount(axis: :group) ⇒ CArray
Per-group 1-based within-group ordinal (int64), source-shaped: the first member of a group is 1, the next 2, ...
-
#cummax(axis: :group) ⇒ CArray
Per-group inclusive running maximum, source-shaped, in the source dtype (extrema do not grow magnitude, so the dtype is preserved).
-
#cummin(axis: :group) ⇒ CArray
Per-group inclusive running minimum, source-shaped, in the source dtype.
-
#cumprod(axis: :group) ⇒ CArray
Per-group inclusive running product (float64), source-shaped.
-
#cumsum(axis: :group) ⇒ CArray
Per-group inclusive running sum (float64), source-shaped.
-
#each({ |members| ... }) ⇒ Object
Yields each group's members (a CArray).
-
#elements(**kw) ⇒ Object
Per-group classified cell count (mask-independent) = count on the mask-stripped value, so every classified cell is counted regardless of the value mask (unlike count / count_not_masked, which count present cells).
-
#map(data_type: nil) ⇒ CArray
Group-wise element-wise transform back to a source-shaped array.
- #max_index ⇒ Object
-
#median ⇒ CArray
Per-group median (float64), any grouping.
- #min_index ⇒ Object
-
#minmax(**kw) ⇒ Object
Per-group [min, max] pair (matching CArray#minmax).
-
#percentile(*pers) ⇒ CArray+
Per-group percentile(s) (float64), any grouping.
-
#quantile ⇒ Array<CArray>
Per-group five-number summary
[min, Q1, median, Q3, max], any grouping. - #reduce(*args, data_type: nil, &block) ⇒ Object
-
#sort_addr ⇒ CArray
Per-group sorted flat source addresses (group-major).
-
#wmean(weights, **kw) ⇒ Object
Weighted mean = Sum(v*w) / Sum(w), both over the combined present-set.
-
#wsum(weights, **kw) ⇒ Object
Weighted sum: group-sum of value*weight.
Instance Method Details
#count_masked(**kw) ⇒ Object
Per-group count of value-masked cells = elements - count_not_masked.
320 321 322 |
# File 'lib/carray/axis_group.rb', line 320 def count_masked (**kw) elements(**kw) - count_not_masked(**kw) end |
#cumcount(axis: :group) ⇒ CArray
427 428 429 |
# File 'lib/carray/axis_group.rb', line 427 def cumcount (**kw) scan_op(:cumcount, kw) end |
#cummax(axis: :group) ⇒ CArray
409 410 411 |
# File 'lib/carray/axis_group.rb', line 409 def cummax (**kw) scan_op(:cummax, kw) end |
#cummin(axis: :group) ⇒ CArray
417 418 419 |
# File 'lib/carray/axis_group.rb', line 417 def cummin (**kw) scan_op(:cummin, kw) end |
#cumprod(axis: :group) ⇒ CArray
399 400 401 |
# File 'lib/carray/axis_group.rb', line 399 def cumprod (**kw) scan_op(:cumprod, kw) end |
#cumsum(axis: :group) ⇒ CArray
391 392 393 |
# File 'lib/carray/axis_group.rb', line 391 def cumsum (**kw) scan_op(:cumsum, kw) end |
#each({ |members| ... }) ⇒ Object
490 491 492 493 494 495 496 |
# File 'lib/carray/axis_group.rb', line 490 def each (&block) ccat, _kd, gslots, bslots, gaxes = composite_layout return value.group_by_category(ccat).each(&block) if bslots.empty? return to_enum(:each) unless block each_band_block(ccat, gslots, bslots, gaxes) { |_vi, _oi, _co, gi| gi.each(&block) } self end |
#elements(**kw) ⇒ Object
Per-group classified cell count (mask-independent) = count on the mask-stripped value, so every classified cell is counted regardless of the value mask (unlike count / count_not_masked, which count present cells).
315 316 317 |
# File 'lib/carray/axis_group.rb', line 315 def elements (**kw) self.class.__build__(value.value, spec).count(**kw) end |
#map(data_type: nil) ⇒ CArray
503 504 505 506 507 508 509 510 511 512 513 |
# File 'lib/carray/axis_group.rb', line 503 def map (data_type: nil, &block) raise LocalJumpError, "no block given (yield)" unless block ccat, _kd, gslots, bslots, gaxes = composite_layout return value.group_by_category(ccat).map(data_type: data_type, &block) if bslots.empty? dt = data_type || value.data_type out = CArray.new(dt, value.shape) each_band_block(ccat, gslots, bslots, gaxes) do |val_idx, _oi, _co, gi| out[*val_idx] = gi.map(data_type: dt, &block) end out end |
#max_index ⇒ Object
344 345 346 347 348 349 |
# File 'lib/carray/axis_group.rb', line 344 def max_index (*) raise NotImplementedError, "CAGroupIterator has no max_index: a group preserves source order, so " \ "a within-group index is weak; use max_addr for the winner's flat " \ "source address (it indexes back into the original array)." end |
#median ⇒ CArray
454 455 456 |
# File 'lib/carray/axis_group.rb', line 454 def median (**kw) order_stat(:median, [], kw) end |
#min_index ⇒ Object #max_index ⇒ Object
337 338 339 340 341 342 |
# File 'lib/carray/axis_group.rb', line 337 def min_index (*) raise NotImplementedError, "CAGroupIterator has no min_index: a group preserves source order, so " \ "a within-group index is weak; use min_addr for the winner's flat " \ "source address (it indexes back into the original array)." end |
#minmax(**kw) ⇒ Object
Per-group [min, max] pair (matching CArray#minmax).
325 326 327 |
# File 'lib/carray/axis_group.rb', line 325 def minmax (**kw) [min(**kw), max(**kw)] end |
#percentile(*pers) ⇒ CArray+
461 462 463 |
# File 'lib/carray/axis_group.rb', line 461 def percentile (*pers, **kw) order_stat(:percentile, pers, kw) end |
#quantile ⇒ Array<CArray>
468 469 470 |
# File 'lib/carray/axis_group.rb', line 468 def quantile (**kw) order_stat(:quantile, [], kw) end |
#reduce({ |members| ... }) ⇒ Object #reduce(init) ⇒ CArray
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
# File 'lib/carray/axis_group.rb', line 521 def reduce (*args, data_type: nil, &block) raise LocalJumpError, "no block given (yield)" unless block ccat, kdims, gslots, bslots, gaxes = composite_layout if bslots.empty? return value.group_by_category(ccat).reduce(*args, data_type: data_type, &block) .reshape(*kdims) end dt = data_type || CA_OBJECT out_shape = spec..map { |m| m[:kind] == :group ? m[:k] : m[:len] } out = CArray.new(dt, out_shape) each_band_block(ccat, gslots, bslots, gaxes) do |_vi, out_idx, _co, gi| out[*out_idx] = gi.reduce(*args, data_type: dt, &block).reshape(*kdims) end out end |
#sort_addr ⇒ CArray
477 478 479 480 481 482 483 |
# File 'lib/carray/axis_group.rb', line 477 def sort_addr (**kw) has_group, _ = AxisGroup.parse_axis(kw[:axis]) return value.sort_addr unless has_group ccat, _kd, gslots, bslots, gaxes = composite_layout return value.group_by_category(ccat).sort_addr if bslots.empty? composite_band_sort_addr(ccat, gslots, bslots, gaxes) end |
#wmean(weights, **kw) ⇒ Object
Weighted mean = Sum(v*w) / Sum(w), both over the combined present-set. The
value*0 + weights denominator carries the same value|weight mask, so its
group-sum is Sum(w) over exactly the cells value*weight used. An empty group
(no present pair) is UNDEF (matching CArray#wmean); a present group whose
weights sum to zero yields NaN/Inf (core's 0/0).
364 365 366 367 368 369 370 371 372 |
# File 'lib/carray/axis_group.rb', line 364 def wmean (weights, **kw) prod = value * weights num = self.class.__build__(prod, spec).sum(**kw) den = self.class.__build__(value * 0 + weights, spec).sum(**kw) cnt = self.class.__build__(prod, spec).count_not_masked(**kw) out = num / den out[cnt.eq(0)] = UNDEF # no present pair -> masked (empty group) out end |
#wsum(weights, **kw) ⇒ Object
Weighted sum: group-sum of value*weight. weights is a per-cell CArray in
the source layout (same shape as value); the product carries the combined
value|weight mask, so masked cells drop out. Empty group -> 0.0 (identity).
No weighted kernel needed -- it is a plain group-sum of a derived array.
355 356 357 |
# File 'lib/carray/axis_group.rb', line 355 def wsum (weights, **kw) self.class.__build__(value * weights, spec).sum(**kw) end |