carray 3.0.1 → 3.0.3
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/CHANGELOG.md +824 -0
- data/README.md +5 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +258 -4
- data/ext/ca_axis_group.c +368 -184
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +90 -41
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +960 -245
- data/ext/ca_kernel_iterator.h +352 -181
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +194 -42
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +5 -4
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +180 -50
- data/ext/ca_obj_face.c +428 -62
- data/ext/ca_obj_face.h +107 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +39 -26
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +235 -55
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +551 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +88 -75
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -123
- data/ext/ca_obj_stride.c +267 -35
- data/ext/ca_obj_string.c +25 -22
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +157 -29
- data/ext/ca_op_ipower.c +25 -13
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_rng_normal.h +42 -0
- data/ext/ca_rng_xoshiro256pp.h +105 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +385 -198
- data/ext/ca_sweep_engine.h +31 -23
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +90 -28
- data/ext/carray_access.c +487 -231
- data/ext/carray_address_basis.c +731 -0
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +49 -17
- data/ext/carray_call_cfunc.c +667 -511
- data/ext/carray_cast.c +1556 -247
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +84 -38
- data/ext/carray_core.c +591 -119
- data/ext/carray_count.c +148 -96
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +604 -291
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +400 -1
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +88 -66
- data/ext/carray_mask.c +705 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +263 -63
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1093 -363
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +582 -204
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +183 -70
- data/ext/carray_sort.c +235 -240
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +103 -118
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1349 -851
- data/ext/ruby_carray.c +17 -2
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +24 -3
- data/lib/carray/autoload_method_extension.rb +18 -0
- data/lib/carray/axis_group.rb +245 -20
- data/lib/carray/basics.rb +95 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +200 -54
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +244 -59
- data/lib/carray/categorical_iterator.rb +391 -757
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +177 -27
- data/lib/carray/construct.rb +40 -0
- data/lib/carray/data_type_extension.rb +3 -0
- data/lib/carray/data_type_limits.rb +91 -0
- data/lib/carray/fixlen_string.rb +1 -1
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +590 -76
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +205 -35
- data/lib/carray/frame/group.rb +199 -40
- data/lib/carray/frame/io.rb +452 -60
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +54 -19
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +726 -56
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +71 -20
- data/lib/carray/iterator.rb +157 -2
- data/lib/carray/lazy.rb +54 -67
- data/lib/carray/mask_gap_fill.rb +66 -50
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/discovery_along.rb +74 -0
- data/lib/carray/methods/factorize.rb +50 -0
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +130 -6
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +235 -21
- data/lib/carray/methods/mask_duplicates.rb +35 -1
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +22 -1
- data/lib/carray/methods/repeat.rb +91 -0
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +52 -3
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +86 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +109 -40
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +9 -4
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +535 -105
- data/lib/carray/window_iterator.rb +259 -82
- data/lib/carray.rb +4 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_block.rb +2 -7
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +11 -4
- data/yard-stubs/carray_access.rb +6 -5
- data/yard-stubs/carray_broadcast.rb +2 -2
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -83
- data/yard-stubs/carray_count.rb +16 -2
- data/yard-stubs/carray_lazy.rb +210 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +1499 -4
- data/yard-stubs/carray_median_percentile.rb +26 -8
- data/yard-stubs/carray_order.rb +43 -82
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +11 -8
- data/yard-stubs/carray_sort.rb +50 -8
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -25837
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14593
- data/ext/carray_kernels_reduce_extreme.c +0 -16948
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32138
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/lib/carray/frame/concat.rb
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
#
|
|
10
10
|
# Both are class methods (symmetric N-ary; no frame is privileged), like
|
|
11
11
|
# +CArray.meld+ / +CArray.concatenate+, not instance verbs.
|
|
12
|
+
#
|
|
13
|
+
# +CAFrame.stack+ and +CAFrame#unstack+ add and take away a layer axis
|
|
14
|
+
# instead of rows.
|
|
12
15
|
|
|
13
16
|
class CAFrame
|
|
14
17
|
# Weld frames along the row axis, view-style. Each output column is
|
|
@@ -28,6 +31,13 @@ class CAFrame
|
|
|
28
31
|
#
|
|
29
32
|
# The index is welded too when every frame has one (their +axis_name+
|
|
30
33
|
# must agree); if none do, the result has no index; a mix raises.
|
|
34
|
+
#
|
|
35
|
+
# A frame with no rows adds no values, so it takes no part in the result
|
|
36
|
+
# past these checks: its column set, its N-D columns' trailing dimensions
|
|
37
|
+
# and its index still have to agree, but the
|
|
38
|
+
# data types are the other frames' (a header-only CSV reads as object
|
|
39
|
+
# columns, which would otherwise refuse or demote the rest). When every
|
|
40
|
+
# frame is empty, the first one stands for them.
|
|
31
41
|
# Column-set mismatch raises — a union-with-UNDEF mode is a possible
|
|
32
42
|
# future opt-in, kept out here to stay explicit (memo §4.2).
|
|
33
43
|
#
|
|
@@ -37,8 +47,11 @@ class CAFrame
|
|
|
37
47
|
frames = frames.flatten
|
|
38
48
|
check_concat_inputs(frames, verb: "meld")
|
|
39
49
|
first = frames.first
|
|
40
|
-
names = first.
|
|
50
|
+
names = first.column_names
|
|
41
51
|
check_column_sets(frames, names, verb: "meld")
|
|
52
|
+
index_pieces(frames, verb: "meld")
|
|
53
|
+
check_trailing_shapes(frames, names, verb: "meld")
|
|
54
|
+
frames = frames_with_rows(frames)
|
|
42
55
|
cols = {}
|
|
43
56
|
names.each do |name|
|
|
44
57
|
cols[name] = CArray.meld(frames.map { |f| f[name] }, axis: 0)
|
|
@@ -54,8 +67,9 @@ class CAFrame
|
|
|
54
67
|
# For a view frame that shares storage with the inputs (strict same data type
|
|
55
68
|
# per column, chain composability preserved) use {CAFrame.meld}.
|
|
56
69
|
#
|
|
57
|
-
# Column matching, index handling,
|
|
58
|
-
# match {CAFrame.meld}
|
|
70
|
+
# Column matching, index handling, column-set / index-mix rules and the
|
|
71
|
+
# treatment of a frame with no rows match {CAFrame.meld}: an empty frame's
|
|
72
|
+
# data types take no part in the common type.
|
|
59
73
|
#
|
|
60
74
|
# CAFrame.concatenate(jan, feb, mar) # eager, independent result
|
|
61
75
|
# CAFrame.concatenate([jan, feb, mar]) # an Array is accepted too
|
|
@@ -63,8 +77,11 @@ class CAFrame
|
|
|
63
77
|
frames = frames.flatten
|
|
64
78
|
check_concat_inputs(frames, verb: "concatenate")
|
|
65
79
|
first = frames.first
|
|
66
|
-
names = first.
|
|
80
|
+
names = first.column_names
|
|
67
81
|
check_column_sets(frames, names, verb: "concatenate")
|
|
82
|
+
index_pieces(frames, verb: "concatenate")
|
|
83
|
+
check_trailing_shapes(frames, names, verb: "concatenate")
|
|
84
|
+
frames = frames_with_rows(frames)
|
|
68
85
|
cols = {}
|
|
69
86
|
names.each do |name|
|
|
70
87
|
cols[name] = CArray.concatenate(frames.map { |f| f[name] })
|
|
@@ -72,6 +89,108 @@ class CAFrame
|
|
|
72
89
|
new(cols, axis_name: first.axis_name, index: concatenate_index(frames))
|
|
73
90
|
end
|
|
74
91
|
|
|
92
|
+
# Stack frames of the same shape as layers. Each output column is
|
|
93
|
+
# +CArray.stack+ of that column across the frames along +axis+, counted in
|
|
94
|
+
# the column's own axes (0 is the row axis, so +axis+ starts at 1): a
|
|
95
|
+
# scalar column of K frames becomes a column of shape (nrow, K). The rows
|
|
96
|
+
# stay as they are, so row verbs work on the stack unchanged and a layer is
|
|
97
|
+
# a column axis -- +s["temp"][nil, k]+ is frame k's column, and
|
|
98
|
+
# +s["temp"].mean(axis: 1)+ reduces across the layers.
|
|
99
|
+
#
|
|
100
|
+
# The result is a view frame: its columns are CAStack views over the
|
|
101
|
+
# frames' columns, and writes reach them. Call +copy+ for an independent
|
|
102
|
+
# frame. The layers carry no labels; keep them alongside (the dates of the
|
|
103
|
+
# files, say) as an array of your own.
|
|
104
|
+
#
|
|
105
|
+
# Every frame must have the same columns, the same number of rows and the
|
|
106
|
+
# same index (by value) under the same axis name, or none; the result
|
|
107
|
+
# takes the first frame's. +unstack+ is the inverse:
|
|
108
|
+
#
|
|
109
|
+
# s = CAFrame.stack(jan1, jan2, jan3) # temp:float64 -> temp:float64[3]
|
|
110
|
+
# CAFrame.stack(*s.unstack(axis: 1)) # the same frame again
|
|
111
|
+
def self.stack(*frames, axis: 1)
|
|
112
|
+
frames = frames.flatten
|
|
113
|
+
check_concat_inputs(frames, verb: "stack")
|
|
114
|
+
check_layer_axis(axis, "stack")
|
|
115
|
+
first = frames.first
|
|
116
|
+
names = first.column_names
|
|
117
|
+
check_column_sets(frames, names, verb: "stack")
|
|
118
|
+
frames.each_with_index do |f, i|
|
|
119
|
+
next if i.zero?
|
|
120
|
+
unless f.nrow == first.nrow
|
|
121
|
+
raise ArgumentError,
|
|
122
|
+
"stack: frame #{i} has #{f.nrow} rows, frame 0 has #{first.nrow}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
indexes, = index_pieces(frames, verb: "stack")
|
|
126
|
+
if indexes && ! indexes.all? { |x| same_index_values?(x, indexes.first) }
|
|
127
|
+
raise ArgumentError, "stack: the frames' indexes differ; stacked rows have to be the same rows"
|
|
128
|
+
end
|
|
129
|
+
cols = {}
|
|
130
|
+
names.each do |name|
|
|
131
|
+
parts = frames.map { |f| f[name] }
|
|
132
|
+
if axis > parts.first.ndim
|
|
133
|
+
raise ArgumentError,
|
|
134
|
+
"stack: axis #{axis} out of range for column #{name.inspect} " \
|
|
135
|
+
"(a #{parts.first.ndim}-D column takes 1 to #{parts.first.ndim})"
|
|
136
|
+
end
|
|
137
|
+
cols[name] = CArray.stack(parts, axis: axis)
|
|
138
|
+
end
|
|
139
|
+
new(cols, axis_name: first.axis_name, index: first.index)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Split the frame along a column axis into an Array of frames, one per
|
|
143
|
+
# position on that axis -- the inverse of {CAFrame.stack}. +axis+ counts
|
|
144
|
+
# the columns' own axes (0 is the row axis, so it starts at 1). Every
|
|
145
|
+
# column must have that axis, and the same length along it: a column
|
|
146
|
+
# without it has no layer to give each frame. Each frame's columns are
|
|
147
|
+
# views of this frame's, and each has this frame's index.
|
|
148
|
+
#
|
|
149
|
+
# s.unstack(axis: 1) # => [frame of layer 0, frame of layer 1, ...]
|
|
150
|
+
def unstack(axis:)
|
|
151
|
+
self.class.send(:check_layer_axis, axis, "unstack")
|
|
152
|
+
if @columns.empty?
|
|
153
|
+
raise ArgumentError, "unstack: the frame has no columns to unstack"
|
|
154
|
+
end
|
|
155
|
+
length = nil
|
|
156
|
+
@columns.each do |name, col|
|
|
157
|
+
unless axis < col.ndim
|
|
158
|
+
raise ArgumentError,
|
|
159
|
+
"unstack: column #{name.inspect} is #{col.ndim}-D and has no axis #{axis}"
|
|
160
|
+
end
|
|
161
|
+
length ||= col.shape[axis]
|
|
162
|
+
unless col.shape[axis] == length
|
|
163
|
+
raise ArgumentError,
|
|
164
|
+
"unstack: column #{name.inspect} has #{col.shape[axis]} along axis #{axis}, " \
|
|
165
|
+
"the others #{length}"
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
(0...length).map do |k|
|
|
169
|
+
cols = @columns.to_h do |name, col|
|
|
170
|
+
idx = [nil] * col.ndim
|
|
171
|
+
idx[axis] = k
|
|
172
|
+
[name, col[*idx]]
|
|
173
|
+
end
|
|
174
|
+
CAFrame.new(cols, axis_name: @axis_name, index: @index)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def self.check_layer_axis(axis, verb)
|
|
179
|
+
unless axis.is_a?(Integer)
|
|
180
|
+
raise TypeError, "#{verb}: axis must be an Integer (got #{axis.inspect})"
|
|
181
|
+
end
|
|
182
|
+
if axis == 0
|
|
183
|
+
raise ArgumentError,
|
|
184
|
+
"#{verb}: axis 0 is the row axis; rows are joined by meld or concatenate"
|
|
185
|
+
end
|
|
186
|
+
if axis < 0
|
|
187
|
+
raise ArgumentError,
|
|
188
|
+
"#{verb}: axis counts a column's axes from 1 (got #{axis}); " \
|
|
189
|
+
"a negative axis would mean a different axis in columns of different ndim"
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
private_class_method :check_layer_axis
|
|
193
|
+
|
|
75
194
|
# ---- shared validators -------------------------------------------------
|
|
76
195
|
|
|
77
196
|
def self.check_concat_inputs(frames, verb:)
|
|
@@ -86,15 +205,47 @@ class CAFrame
|
|
|
86
205
|
expected = names.sort
|
|
87
206
|
frames.each_with_index do |f, i|
|
|
88
207
|
next if i.zero?
|
|
89
|
-
if f.
|
|
208
|
+
if f.column_names.sort != expected
|
|
90
209
|
raise ArgumentError,
|
|
91
|
-
"#{verb}: frame #{i} has columns #{f.
|
|
210
|
+
"#{verb}: frame #{i} has columns #{f.column_names.inspect}, " \
|
|
92
211
|
"expected the same set as #{names.inspect}"
|
|
93
212
|
end
|
|
94
213
|
end
|
|
95
214
|
end
|
|
96
215
|
private_class_method :check_column_sets
|
|
97
216
|
|
|
217
|
+
# A column's trailing dimensions are its shape, not a type the other
|
|
218
|
+
# frames can settle, so a frame with no rows has to agree on them too.
|
|
219
|
+
def self.check_trailing_shapes(frames, names, verb:)
|
|
220
|
+
names.each do |name|
|
|
221
|
+
trailing = frames.first[name].shape[1..]
|
|
222
|
+
frames.each_with_index do |f, i|
|
|
223
|
+
next if i.zero? || f[name].shape[1..] == trailing
|
|
224
|
+
raise ArgumentError,
|
|
225
|
+
"#{verb}: column #{name.inspect} has trailing dimensions " \
|
|
226
|
+
"#{f[name].shape[1..].inspect} in frame #{i}, #{trailing.inspect} in frame 0"
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
private_class_method :check_trailing_shapes
|
|
231
|
+
|
|
232
|
+
# Two indexes hold the same rows when their values agree cell by cell; a
|
|
233
|
+
# NaN label matches a NaN label, and a masked cell a masked cell.
|
|
234
|
+
def self.same_index_values?(a, b)
|
|
235
|
+
return false unless a.shape == b.shape
|
|
236
|
+
a.to_a.zip(b.to_a).all? do |x, y|
|
|
237
|
+
x.equal?(y) || x == y || (x.is_a?(Float) && y.is_a?(Float) && x.nan? && y.nan?)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
private_class_method :same_index_values?
|
|
241
|
+
|
|
242
|
+
# The frames that add rows, or the first frame when none does.
|
|
243
|
+
def self.frames_with_rows(frames)
|
|
244
|
+
with_rows = frames.reject { |f| f.nrow.zero? }
|
|
245
|
+
with_rows.empty? ? [frames.first] : with_rows
|
|
246
|
+
end
|
|
247
|
+
private_class_method :frames_with_rows
|
|
248
|
+
|
|
98
249
|
# ---- index helpers -----------------------------------------------------
|
|
99
250
|
|
|
100
251
|
# Index welded via CArray.meld (view). Every frame must agree: all
|
data/lib/carray/frame/convert.rb
CHANGED
|
@@ -16,21 +16,25 @@ class CAFrame
|
|
|
16
16
|
# column name => value; a scalar cell is a Ruby value, an N-D cell is a Ruby
|
|
17
17
|
# Array, and a masked cell (UNDEF) is +nil+. Normalizing UNDEF -> nil and
|
|
18
18
|
# CArray -> Array (unlike +each_row+, which yields the raw view with UNDEF /
|
|
19
|
-
# CArray slices)
|
|
20
|
-
#
|
|
19
|
+
# CArray slices) makes the result JSON-serializable and lets
|
|
20
|
+
# +from_records(df.to_records)+ give back the column names, the values and
|
|
21
|
+
# the mask. The rest is not in a record: +from_records+ rebuilds each type
|
|
22
|
+
# from the values (an int32 comes back int64, a time column as an object
|
|
23
|
+
# column of its elements), the index comes back as an ordinary first
|
|
24
|
+
# column, and a frame with no rows gives +[]+, which has no column names.
|
|
21
25
|
def to_records
|
|
22
26
|
each_row.map { |row| row.transform_values { |v| record_value(v) } }
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
# Hand the frame over as a CArray with the minimum work (memo §11.9): a
|
|
26
|
-
# 2-D **view** of shape (nrow,
|
|
30
|
+
# 2-D **view** of shape (nrow, ncol), one per column in column
|
|
27
31
|
# order (§12-C). Nothing is materialised — the result is a +CAStack+ over
|
|
28
32
|
# the stored columns, so reads gather from them and writes flow back
|
|
29
33
|
# (§3.6). Call +copy+ on it for an independent, owned matrix; +CArray.tabulate+
|
|
30
34
|
# is the eager sibling that builds one directly.
|
|
31
35
|
#
|
|
32
36
|
# Only same-shape scalar (1-D) columns qualify. An N-D column has no single
|
|
33
|
-
# matrix form and raises —
|
|
37
|
+
# matrix form and raises — take it per column with +df["name"]+. A mixed
|
|
34
38
|
# data type set is promoted to a common type (+result_type+, §12-F) through
|
|
35
39
|
# lazy cast lanes, so the promotion costs no buffer either.
|
|
36
40
|
#
|
|
@@ -48,12 +52,12 @@ class CAFrame
|
|
|
48
52
|
if nd
|
|
49
53
|
raise ArgumentError,
|
|
50
54
|
"to_ca needs all-scalar (1-D) columns; #{nd.first.inspect} is " \
|
|
51
|
-
"#{nd.last.ndim}-D —
|
|
55
|
+
"#{nd.last.ndim}-D — take it per column with df[name]"
|
|
52
56
|
end
|
|
53
57
|
refuse_unshared_columns(cols) if writable
|
|
54
58
|
begin
|
|
55
59
|
CArray.stack(cols, axis: 1)
|
|
56
|
-
rescue ArgumentError,
|
|
60
|
+
rescue ArgumentError, TypeError, CArray::DataTypeError => e
|
|
57
61
|
# The columns have no common type (a text or Face column beside a
|
|
58
62
|
# numeric one). Point at the frame-level verb that gives them one.
|
|
59
63
|
raise e.class,
|
|
@@ -87,7 +91,9 @@ class CAFrame
|
|
|
87
91
|
if UNDEF.equal?(v)
|
|
88
92
|
nil
|
|
89
93
|
elsif v.is_a?(CArray)
|
|
90
|
-
v.to_a
|
|
94
|
+
record_value(v.to_a)
|
|
95
|
+
elsif v.is_a?(Array)
|
|
96
|
+
v.map { |e| record_value(e) }
|
|
91
97
|
else
|
|
92
98
|
v
|
|
93
99
|
end
|