carray 3.0.3 → 3.0.4
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 +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/lib/carray/frame/reshape.rb
CHANGED
|
@@ -62,23 +62,25 @@ class CAFrame
|
|
|
62
62
|
# unknown reduction or a multi-dimensional value column with it, or when
|
|
63
63
|
# two output columns would share a name.
|
|
64
64
|
def pivot(index:, columns:, values:, aggregate: nil)
|
|
65
|
-
plan = pivot_plan(index
|
|
65
|
+
plan = pivot_plan(column_key(index, "pivot"), column_key(columns, "pivot"), aggregate, "pivot")
|
|
66
66
|
labels = Array.new(plan[:nc]) { |j| plan[:clab][j].to_s }
|
|
67
|
-
|
|
67
|
+
if labels.include?("") && !values.is_a?(Array)
|
|
68
|
+
raise ArgumentError,
|
|
69
|
+
"pivot: a value of columns: #{columns.inspect} is the empty string, " \
|
|
70
|
+
"which cannot name a column; recode it first"
|
|
71
|
+
end
|
|
72
|
+
value_names = values.is_a?(Array) ? column_keys(values, "pivot") : nil
|
|
68
73
|
names =
|
|
69
74
|
if value_names
|
|
70
75
|
value_names.flat_map { |v| labels.map { |l| "#{v}_#{l}" } }
|
|
71
76
|
else
|
|
72
77
|
labels
|
|
73
78
|
end
|
|
74
|
-
|
|
75
|
-
unless dup.empty?
|
|
76
|
-
raise ArgumentError, "pivot: output columns would share the names #{dup.inspect}"
|
|
77
|
-
end
|
|
79
|
+
CAFrame.__send__(:refuse_repeated_names, names, "pivot", "the output columns would name")
|
|
78
80
|
|
|
79
81
|
source = plan[:source].reshape(plan[:nr], plan[:nc])
|
|
80
82
|
cols = {}
|
|
81
|
-
(value_names || [values
|
|
83
|
+
(value_names || [column_key(values, "pivot")]).each_with_index do |value, k|
|
|
82
84
|
val = pivot_value(plan, value)
|
|
83
85
|
plan[:nc].times do |j|
|
|
84
86
|
cols[names[k * plan[:nc] + j]] = project_rows(val, source[nil, j])
|
|
@@ -108,8 +110,8 @@ class CAFrame
|
|
|
108
110
|
# and the axis-1 key values; the grid is new, not a view of +self+.
|
|
109
111
|
# @raise [ArgumentError] as {#pivot}.
|
|
110
112
|
def pivot_grid(index:, columns:, values:, aggregate: nil)
|
|
111
|
-
plan = pivot_plan(index
|
|
112
|
-
val = pivot_value(plan, values
|
|
113
|
+
plan = pivot_plan(column_key(index, "pivot_grid"), column_key(columns, "pivot_grid"), aggregate, "pivot_grid")
|
|
114
|
+
val = pivot_value(plan, column_key(values, "pivot_grid"))
|
|
113
115
|
grid = project_rows(val, plan[:source]).reshape(plan[:nr], plan[:nc], *val.shape[1..])
|
|
114
116
|
[grid, plan[:rlab], plan[:clab]]
|
|
115
117
|
end
|
|
@@ -118,12 +120,14 @@ class CAFrame
|
|
|
118
120
|
# in order (nil beside numbers, numbers beside strings) are refused,
|
|
119
121
|
# naming the key.
|
|
120
122
|
private def pivot_sorted_keys(key, kw, name, verb)
|
|
121
|
-
key
|
|
123
|
+
# The keys label rows or columns, so they show the key column's
|
|
124
|
+
# attributes, as a group index does.
|
|
125
|
+
CAFrame.__send__(:key_labels, key, key.unique(sort: true))
|
|
122
126
|
rescue ArgumentError => e
|
|
123
|
-
|
|
127
|
+
why = e.message[/\A[^:]+: (comparison of .+ failed)\z/, 1] or raise
|
|
124
128
|
raise ArgumentError,
|
|
125
129
|
"#{verb}: #{kw}: #{name.inspect} holds values that cannot be put in order " \
|
|
126
|
-
"(#{
|
|
130
|
+
"(#{why}); its keys are sorted to make the " \
|
|
127
131
|
"#{kw == "index" ? "rows" : "columns"}"
|
|
128
132
|
end
|
|
129
133
|
|
|
@@ -131,13 +135,9 @@ class CAFrame
|
|
|
131
135
|
# sorted keys and, for each of the nr * nc cells, the address of the row
|
|
132
136
|
# (or with +aggregate:+, of the reduced pair) that fills it.
|
|
133
137
|
private def pivot_plan(index, columns, aggregate, verb)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
next if key.ndim == 1
|
|
138
|
-
raise ArgumentError,
|
|
139
|
-
"#{verb}: #{kw}: #{name.inspect} has shape #{key.shape.inspect}, not one value per row"
|
|
140
|
-
end
|
|
138
|
+
CAFrame.__send__(:refuse_repeated_names, [index, columns], verb, "index: and columns: name")
|
|
139
|
+
rkey = key_column(index, verb)
|
|
140
|
+
ckey = key_column(columns, verb)
|
|
141
141
|
rlab = pivot_sorted_keys(rkey, "index", index, verb)
|
|
142
142
|
clab = pivot_sorted_keys(ckey, "columns", columns, verb)
|
|
143
143
|
nr = rlab.elements
|
|
@@ -145,6 +145,8 @@ class CAFrame
|
|
|
145
145
|
|
|
146
146
|
r = rkey.locate_addr(rlab)
|
|
147
147
|
c = ckey.locate_addr(clab)
|
|
148
|
+
rlab = pivot_key_kind(rkey, rlab)
|
|
149
|
+
clab = pivot_key_kind(ckey, clab)
|
|
148
150
|
placed = r.is_not_masked & c.is_not_masked
|
|
149
151
|
cell = r[placed] * nc + c[placed]
|
|
150
152
|
source = CArray.int64(nr * nc)
|
|
@@ -160,6 +162,7 @@ class CAFrame
|
|
|
160
162
|
source[CA_INT64(pairs.labels)] = CArray.int64(pairs.labels.size).seq
|
|
161
163
|
else
|
|
162
164
|
if cell.nunique != cell.elements
|
|
165
|
+
# names-check: two rows for one cell of the grid
|
|
163
166
|
first = cell.to_a.tally.find { |_, count| count > 1 }.first
|
|
164
167
|
raise ArgumentError,
|
|
165
168
|
"pivot: more than one row for #{index}=#{rlab[first / nc].inspect}, " \
|
|
@@ -170,6 +173,15 @@ class CAFrame
|
|
|
170
173
|
plan
|
|
171
174
|
end
|
|
172
175
|
|
|
176
|
+
# The distinct values of a categorical key come back as its label values;
|
|
177
|
+
# the keys that label the result are a categorical again, with the key's
|
|
178
|
+
# labels, as a group index keeps a categorical key.
|
|
179
|
+
private def pivot_key_kind(key, sorted)
|
|
180
|
+
return sorted unless key.is_a?(CACategorical)
|
|
181
|
+
CAFrame.__send__(:key_labels, key,
|
|
182
|
+
sorted.to_type(:object).categorize(labels: key.labels))
|
|
183
|
+
end
|
|
184
|
+
|
|
173
185
|
# The column the plan's addresses point into: the value column itself, or
|
|
174
186
|
# with +aggregate:+ one reduced value per occupied pair.
|
|
175
187
|
private def pivot_value(plan, name)
|
|
@@ -189,8 +201,8 @@ class CAFrame
|
|
|
189
201
|
|
|
190
202
|
# Gather a wide frame into a long one. The +value_columns+ are stacked one
|
|
191
203
|
# after another into a single +value_name+ column, a +var_name+ column says
|
|
192
|
-
# which of them each row came from, and every +id+ column
|
|
193
|
-
# value column.
|
|
204
|
+
# which of them each row came from (a text column), and every +id+ column
|
|
205
|
+
# repeats once per value column.
|
|
194
206
|
#
|
|
195
207
|
# wide.melt(id: "time") # time / variable / value
|
|
196
208
|
#
|
|
@@ -212,9 +224,9 @@ class CAFrame
|
|
|
212
224
|
# @raise [ArgumentError] when there is nothing to melt, or the value
|
|
213
225
|
# columns differ in data type.
|
|
214
226
|
def melt(id: [], value_columns: nil, var_name: "variable", value_name: "value")
|
|
215
|
-
ids = Array(id)
|
|
227
|
+
ids = column_keys(Array(id), "melt")
|
|
216
228
|
ids.each { |name| self[name] }
|
|
217
|
-
vars = (value_columns || column_names - ids)
|
|
229
|
+
vars = column_keys(value_columns || column_names - ids, "melt")
|
|
218
230
|
raise ArgumentError, "melt: no columns to melt" if vars.empty?
|
|
219
231
|
overlap = vars & ids
|
|
220
232
|
unless overlap.empty?
|
|
@@ -240,12 +252,13 @@ class CAFrame
|
|
|
240
252
|
out[@axis_name] = CArray.meld(Array.new(k, @index)) if @index
|
|
241
253
|
ids.each { |name| out[name] = CArray.meld(Array.new(k, self[name])) }
|
|
242
254
|
[var_name, value_name].each do |name|
|
|
255
|
+
column_name_arg(name, "melt")
|
|
243
256
|
if out.key?(name)
|
|
244
257
|
raise ArgumentError, "melt: #{name.inspect} is already an id column"
|
|
245
258
|
end
|
|
246
259
|
end
|
|
247
260
|
n = nrow
|
|
248
|
-
out[var_name] = CArray.
|
|
261
|
+
out[var_name] = CArray.string(Array.new(n * k) { |i| vars[i / n] })
|
|
249
262
|
out[value_name] = CArray.meld(pieces)
|
|
250
263
|
CAFrame.new(out)
|
|
251
264
|
end
|
|
@@ -291,8 +304,9 @@ class CAFrame
|
|
|
291
304
|
# @param on [String, nil] the column whose values line the rows up.
|
|
292
305
|
# @return [CAFrame] one row per group, indexed by the group labels.
|
|
293
306
|
def stack_rows(by:, on: nil)
|
|
294
|
-
keys = (by.is_a?(Array) ? by : [by]).map { |k| k.is_a?(Symbol) ? k
|
|
307
|
+
keys = (by.is_a?(Array) ? by : [by]).map { |k| k.is_a?(Symbol) ? column_key(k, "stack_rows") : k }
|
|
295
308
|
raise ArgumentError, "stack_rows: by: names no key" if keys.empty?
|
|
309
|
+
CAFrame.__send__(:refuse_repeated_names, keys.grep(String), "stack_rows", "by: names")
|
|
296
310
|
frame = @index ? CAFrame.new({ @axis_name => @index }.merge(@columns)) : self
|
|
297
311
|
keys.each { |k| frame.__send__(:key_column, k, "stack_rows") }
|
|
298
312
|
# With nothing but the key there is no column to stack, and the result
|
|
@@ -322,6 +336,7 @@ class CAFrame
|
|
|
322
336
|
"stack_rows: every row has to belong to a group; " \
|
|
323
337
|
"the key has no value for #{frame.nrow - stacked} of #{frame.nrow} rows"
|
|
324
338
|
end
|
|
339
|
+
# names-check: equal sizes, not names
|
|
325
340
|
unless sizes.uniq.size <= 1
|
|
326
341
|
# One group of each size, so the message says where to look.
|
|
327
342
|
examples = sizes.each_with_index.uniq { |n, _| n }.map do |n, g|
|
|
@@ -354,10 +369,7 @@ class CAFrame
|
|
|
354
369
|
if keys.include?(on)
|
|
355
370
|
raise ArgumentError, "stack_rows: #{on.inspect} is a key; on: names another column"
|
|
356
371
|
end
|
|
357
|
-
place = frame
|
|
358
|
-
unless place.ndim == 1
|
|
359
|
-
raise ArgumentError, "stack_rows: on: #{on.inspect} has shape #{place.shape.inspect}, not one value per row"
|
|
360
|
-
end
|
|
372
|
+
place = frame.__send__(:key_column, on, "stack_rows")
|
|
361
373
|
grouped = frame.group_by(*keys)
|
|
362
374
|
bounds = grouped.__send__(:group_bounds).to_a
|
|
363
375
|
groups = bounds.size - 1
|
|
@@ -423,6 +435,7 @@ class CAFrame
|
|
|
423
435
|
raise ArgumentError, "unstack_rows: the frame has no N-D column to unstack"
|
|
424
436
|
end
|
|
425
437
|
lengths = stacked.transform_values { |c| c.shape[1] }
|
|
438
|
+
# names-check: equal lengths, not names
|
|
426
439
|
unless lengths.values.uniq.size == 1
|
|
427
440
|
raise ArgumentError,
|
|
428
441
|
"unstack_rows: the N-D columns differ in length along their first axis #{lengths}"
|
|
@@ -439,10 +452,4 @@ class CAFrame
|
|
|
439
452
|
CAFrame.new(cols, axis_name: @axis_name, index: @index && @index[repeat])
|
|
440
453
|
end
|
|
441
454
|
|
|
442
|
-
# A column, or the index when +name+ is the row axis name (pivot and resample
|
|
443
|
-
# keys may be either).
|
|
444
|
-
private def column_or_index(name)
|
|
445
|
-
return @index if @index && !@columns.key?(name) && @axis_name == name
|
|
446
|
-
self[name]
|
|
447
|
-
end
|
|
448
455
|
end
|
data/lib/carray/frame/sort.rb
CHANGED
|
@@ -40,8 +40,9 @@ class CAFrame
|
|
|
40
40
|
validate_sort_order(order)
|
|
41
41
|
named = specs.map do |spec|
|
|
42
42
|
name, dir = parse_sort_key_spec(spec, order)
|
|
43
|
-
[name
|
|
43
|
+
[column_key(name, "sort_by_key"), key_column(column_key(name, "sort_by_key"), "sort_by_key"), dir]
|
|
44
44
|
end
|
|
45
|
+
CAFrame.__send__(:refuse_repeated_names, named.map(&:first), "sort_by_key")
|
|
45
46
|
keys = named.map do |name, col, dir|
|
|
46
47
|
dir == :desc ? col.order(descending: true, method: :dense) : col
|
|
47
48
|
end
|
|
@@ -55,8 +56,11 @@ class CAFrame
|
|
|
55
56
|
# The core names the conversion as an array method; in a frame it is
|
|
56
57
|
# written with sort_by.
|
|
57
58
|
reason = "#{reason.split(";").first}; sort by its values with " \
|
|
58
|
-
"sort_by { |f| f[#{name.inspect}].to_type(:object) }
|
|
59
|
-
|
|
59
|
+
"sort_by { |f| f[#{name.inspect}].to_type(:object) }"
|
|
60
|
+
if (storage = col.__send__(:face_storage_method))
|
|
61
|
+
reason += ", or by its storage with " \
|
|
62
|
+
"sort_by { |f| f[#{name.inspect}].#{storage} }"
|
|
63
|
+
end
|
|
60
64
|
end
|
|
61
65
|
raise e.class, "sort_by_key: the column #{name.inspect} cannot be sorted: #{reason}"
|
|
62
66
|
end
|
|
@@ -118,20 +122,4 @@ class CAFrame
|
|
|
118
122
|
raise ArgumentError, "sort order must be :asc or :desc, got #{dir.inspect}"
|
|
119
123
|
end
|
|
120
124
|
|
|
121
|
-
private def sort_key_column(name)
|
|
122
|
-
key = name.to_s
|
|
123
|
-
col = if @columns.key?(key)
|
|
124
|
-
@columns[key]
|
|
125
|
-
elsif @index && @axis_name == key
|
|
126
|
-
@index
|
|
127
|
-
else
|
|
128
|
-
raise KeyError, "no column #{key.inspect}"
|
|
129
|
-
end
|
|
130
|
-
unless col.ndim == 1
|
|
131
|
-
raise ArgumentError,
|
|
132
|
-
"sort_by_key: key column #{key.inspect} is #{col.ndim}-D; " \
|
|
133
|
-
"sort by a scalar (1-D) column"
|
|
134
|
-
end
|
|
135
|
-
col
|
|
136
|
-
end
|
|
137
125
|
end
|