daru 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +99 -0
- data/.rubocop_todo.yml +44 -0
- data/.travis.yml +3 -1
- data/CONTRIBUTING.md +5 -1
- data/History.md +43 -0
- data/README.md +3 -4
- data/benchmarks/duplicating.rb +45 -0
- data/benchmarks/group_by.rb +7 -7
- data/benchmarks/joining.rb +52 -0
- data/benchmarks/sorting.rb +9 -2
- data/benchmarks/statistics.rb +39 -0
- data/daru.gemspec +4 -4
- data/lib/daru.rb +9 -9
- data/lib/daru/accessors/array_wrapper.rb +15 -11
- data/lib/daru/accessors/dataframe_by_row.rb +1 -1
- data/lib/daru/accessors/gsl_wrapper.rb +30 -19
- data/lib/daru/accessors/mdarray_wrapper.rb +1 -3
- data/lib/daru/accessors/nmatrix_wrapper.rb +15 -15
- data/lib/daru/core/group_by.rb +69 -16
- data/lib/daru/core/merge.rb +135 -151
- data/lib/daru/core/query.rb +9 -30
- data/lib/daru/dataframe.rb +476 -439
- data/lib/daru/date_time/index.rb +150 -137
- data/lib/daru/date_time/offsets.rb +45 -41
- data/lib/daru/extensions/rserve.rb +4 -4
- data/lib/daru/index.rb +88 -64
- data/lib/daru/io/io.rb +33 -34
- data/lib/daru/io/sql_data_source.rb +11 -11
- data/lib/daru/maths/arithmetic/dataframe.rb +19 -19
- data/lib/daru/maths/arithmetic/vector.rb +9 -14
- data/lib/daru/maths/statistics/dataframe.rb +89 -61
- data/lib/daru/maths/statistics/vector.rb +226 -97
- data/lib/daru/monkeys.rb +23 -30
- data/lib/daru/plotting/dataframe.rb +27 -28
- data/lib/daru/plotting/vector.rb +12 -13
- data/lib/daru/vector.rb +221 -330
- data/lib/daru/version.rb +2 -2
- data/spec/core/group_by_spec.rb +16 -0
- data/spec/core/merge_spec.rb +30 -14
- data/spec/dataframe_spec.rb +268 -14
- data/spec/index_spec.rb +23 -5
- data/spec/io/io_spec.rb +37 -16
- data/spec/math/statistics/dataframe_spec.rb +40 -8
- data/spec/math/statistics/vector_spec.rb +135 -10
- data/spec/monkeys_spec.rb +3 -3
- data/spec/vector_spec.rb +157 -25
- metadata +41 -21
@@ -1,4 +1,6 @@
|
|
1
1
|
module Daru
|
2
|
+
# rubocop:disable Style/OpMethod
|
3
|
+
|
2
4
|
# Generic class for generating date offsets.
|
3
5
|
class DateOffset
|
4
6
|
# A Daru::DateOffset object is created by a passing certain options
|
@@ -15,7 +17,7 @@ module Daru
|
|
15
17
|
# * :weeks - Create a weeks offset
|
16
18
|
# * :months - Create a months offset
|
17
19
|
# * :years - Create a years offset
|
18
|
-
#
|
20
|
+
#
|
19
21
|
# Additionaly, passing the `:n` option will apply the offset that many times.
|
20
22
|
#
|
21
23
|
# @example Usage of DateOffset
|
@@ -23,7 +25,7 @@ module Daru
|
|
23
25
|
# offset = Daru::DateOffset.new(weeks: 3)
|
24
26
|
# offset + DateTime.new(2012,5,3)
|
25
27
|
# #=> #<DateTime: 2012-05-24T00:00:00+00:00 ((2456072j,0s,0n),+0s,2299161j)>
|
26
|
-
#
|
28
|
+
#
|
27
29
|
# # Create an offset of 5 hours
|
28
30
|
# offset = Daru::DateOffset.new(hours: 5)
|
29
31
|
# offset + DateTime.new(2015,3,3,23,5,1)
|
@@ -37,22 +39,22 @@ module Daru
|
|
37
39
|
n = opts[:n] || 1
|
38
40
|
|
39
41
|
@offset =
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
42
|
+
case
|
43
|
+
when opts[:secs]
|
44
|
+
Offsets::Second.new(n*opts[:secs])
|
45
|
+
when opts[:mins]
|
46
|
+
Offsets::Minute.new(n*opts[:mins])
|
47
|
+
when opts[:hours]
|
48
|
+
Offsets::Hour.new(n*opts[:hours])
|
49
|
+
when opts[:days]
|
50
|
+
Offsets::Day.new(n*opts[:days])
|
51
|
+
when opts[:weeks]
|
52
|
+
Offsets::Day.new(7*n*opts[:weeks])
|
53
|
+
when opts[:months]
|
54
|
+
Offsets::Month.new(n*opts[:months])
|
55
|
+
when opts[:years]
|
56
|
+
Offsets::Year.new(n*opts[:years])
|
57
|
+
end
|
56
58
|
end
|
57
59
|
|
58
60
|
# Offset a DateTime forward.
|
@@ -93,7 +95,7 @@ module Daru
|
|
93
95
|
end
|
94
96
|
|
95
97
|
# Create a seconds offset
|
96
|
-
#
|
98
|
+
#
|
97
99
|
# @param n [Integer] The number of times an offset should be applied.
|
98
100
|
# @example Create a Seconds offset
|
99
101
|
# offset = Daru::Offsets::Second.new(5)
|
@@ -110,7 +112,7 @@ module Daru
|
|
110
112
|
end
|
111
113
|
|
112
114
|
# Create a minutes offset
|
113
|
-
#
|
115
|
+
#
|
114
116
|
# @param n [Integer] The number of times an offset should be applied.
|
115
117
|
# @example Create a Minutes offset
|
116
118
|
# offset = Daru::Offsets::Minute.new(8)
|
@@ -127,7 +129,7 @@ module Daru
|
|
127
129
|
end
|
128
130
|
|
129
131
|
# Create an hours offset
|
130
|
-
#
|
132
|
+
#
|
131
133
|
# @param n [Integer] The number of times an offset should be applied.
|
132
134
|
# @example Create a Hour offset
|
133
135
|
# offset = Daru::Offsets::Hour.new(8)
|
@@ -137,14 +139,14 @@ module Daru
|
|
137
139
|
def multiplier
|
138
140
|
0.041666666666666664
|
139
141
|
end
|
140
|
-
|
142
|
+
|
141
143
|
def freq_string
|
142
144
|
(@n == 1 ? '' : @n.to_s) + 'H'
|
143
145
|
end
|
144
146
|
end
|
145
147
|
|
146
148
|
# Create an days offset
|
147
|
-
#
|
149
|
+
#
|
148
150
|
# @param n [Integer] The number of times an offset should be applied.
|
149
151
|
# @example Create a Day offset
|
150
152
|
# offset = Daru::Offsets::Day.new(2)
|
@@ -161,7 +163,7 @@ module Daru
|
|
161
163
|
end
|
162
164
|
|
163
165
|
# Create an months offset
|
164
|
-
#
|
166
|
+
#
|
165
167
|
# @param n [Integer] The number of times an offset should be applied.
|
166
168
|
# @example Create a Month offset
|
167
169
|
# offset = Daru::Offsets::Month.new(5)
|
@@ -182,7 +184,7 @@ module Daru
|
|
182
184
|
end
|
183
185
|
|
184
186
|
# Create a years offset
|
185
|
-
#
|
187
|
+
#
|
186
188
|
# @param n [Integer] The number of times an offset should be applied.
|
187
189
|
# @example Create a Year offset
|
188
190
|
# offset = Daru::Offsets::Year.new(2)
|
@@ -239,7 +241,7 @@ module Daru
|
|
239
241
|
end
|
240
242
|
|
241
243
|
# Create a month begin offset
|
242
|
-
#
|
244
|
+
#
|
243
245
|
# @param n [Integer] The number of times an offset should be applied.
|
244
246
|
# @example Create a MonthBegin offset
|
245
247
|
# offset = Daru::Offsets::MonthBegin.new(2)
|
@@ -251,14 +253,14 @@ module Daru
|
|
251
253
|
end
|
252
254
|
|
253
255
|
def freq_string
|
254
|
-
(@n == 1 ? '' : @n.to_s) +
|
256
|
+
(@n == 1 ? '' : @n.to_s) + 'MB'
|
255
257
|
end
|
256
258
|
|
257
259
|
def + date_time
|
258
260
|
@n.times do
|
259
261
|
days_in_month = Daru::MONTH_DAYS[date_time.month]
|
260
|
-
days_in_month += 1 if date_time.leap?
|
261
|
-
date_time
|
262
|
+
days_in_month += 1 if date_time.leap? && date_time.month == 2
|
263
|
+
date_time += (days_in_month - date_time.day + 1)
|
262
264
|
end
|
263
265
|
|
264
266
|
date_time
|
@@ -267,7 +269,7 @@ module Daru
|
|
267
269
|
def - date_time
|
268
270
|
@n.times do
|
269
271
|
date_time = date_time << 1 if on_offset?(date_time)
|
270
|
-
date_time = DateTime.new(date_time.year, date_time.month, 1,
|
272
|
+
date_time = DateTime.new(date_time.year, date_time.month, 1,
|
271
273
|
date_time.hour, date_time.min, date_time.sec)
|
272
274
|
end
|
273
275
|
|
@@ -280,7 +282,7 @@ module Daru
|
|
280
282
|
end
|
281
283
|
|
282
284
|
# Create a month end offset
|
283
|
-
#
|
285
|
+
#
|
284
286
|
# @param n [Integer] The number of times an offset should be applied.
|
285
287
|
# @example Create a MonthEnd offset
|
286
288
|
# offset = Daru::Offsets::MonthEnd.new
|
@@ -296,24 +298,24 @@ module Daru
|
|
296
298
|
end
|
297
299
|
|
298
300
|
def + date_time
|
299
|
-
@n.times do
|
301
|
+
@n.times do
|
300
302
|
date_time = date_time >> 1 if on_offset?(date_time)
|
301
303
|
days_in_month = Daru::MONTH_DAYS[date_time.month]
|
302
|
-
days_in_month += 1 if date_time.leap?
|
304
|
+
days_in_month += 1 if date_time.leap? && date_time.month == 2
|
303
305
|
|
304
|
-
date_time
|
306
|
+
date_time += (days_in_month - date_time.day)
|
305
307
|
end
|
306
308
|
|
307
309
|
date_time
|
308
310
|
end
|
309
311
|
|
310
312
|
def - date_time
|
311
|
-
@n.times do
|
313
|
+
@n.times do
|
312
314
|
date_time = date_time << 1
|
313
315
|
days_in_month = Daru::MONTH_DAYS[date_time.month]
|
314
|
-
days_in_month += 1 if date_time.leap?
|
316
|
+
days_in_month += 1 if date_time.leap? && date_time.month == 2
|
315
317
|
|
316
|
-
date_time
|
318
|
+
date_time += (days_in_month - date_time.day)
|
317
319
|
end
|
318
320
|
|
319
321
|
date_time
|
@@ -325,7 +327,7 @@ module Daru
|
|
325
327
|
end
|
326
328
|
|
327
329
|
# Create a year begin offset
|
328
|
-
#
|
330
|
+
#
|
329
331
|
# @param n [Integer] The number of times an offset should be applied.
|
330
332
|
# @example Create a YearBegin offset
|
331
333
|
# offset = Daru::Offsets::YearBegin.new(3)
|
@@ -347,7 +349,7 @@ module Daru
|
|
347
349
|
|
348
350
|
def - date_time
|
349
351
|
if on_offset?(date_time)
|
350
|
-
DateTime.new(date_time.year - @n, 1, 1,
|
352
|
+
DateTime.new(date_time.year - @n, 1, 1,
|
351
353
|
date_time.hour,date_time.min, date_time.sec)
|
352
354
|
else
|
353
355
|
DateTime.new(date_time.year - (@n-1), 1, 1)
|
@@ -360,7 +362,7 @@ module Daru
|
|
360
362
|
end
|
361
363
|
|
362
364
|
# Create a year end offset
|
363
|
-
#
|
365
|
+
#
|
364
366
|
# @param n [Integer] The number of times an offset should be applied.
|
365
367
|
# @example Create a YearEnd offset
|
366
368
|
# offset = Daru::Offsets::YearEnd.new
|
@@ -394,4 +396,6 @@ module Daru
|
|
394
396
|
end
|
395
397
|
end
|
396
398
|
end
|
397
|
-
|
399
|
+
|
400
|
+
# rubocop:enable Style/OpMethod
|
401
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Daru
|
4
4
|
class DataFrame
|
5
|
-
def to_REXP
|
5
|
+
def to_REXP # rubocop:disable Style/MethodName
|
6
6
|
names = @vectors.to_a
|
7
7
|
data = names.map do |f|
|
8
8
|
Rserve::REXP::Wrapper.wrap(self[f].to_a)
|
@@ -14,8 +14,8 @@ module Daru
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class Vector
|
17
|
-
def to_REXP
|
18
|
-
Rserve::REXP::Wrapper.wrap(
|
17
|
+
def to_REXP # rubocop:disable Style/MethodName
|
18
|
+
Rserve::REXP::Wrapper.wrap(to_a)
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
data/lib/daru/index.rb
CHANGED
@@ -3,14 +3,14 @@ module Daru
|
|
3
3
|
include Enumerable
|
4
4
|
# It so happens that over riding the .new method in a super class also
|
5
5
|
# tampers with the default .new method for class that inherit from the
|
6
|
-
# super class (Index in this case). Thus we first alias the original
|
7
|
-
# new method (from Object) to __new__ when the Index class is evaluated,
|
6
|
+
# super class (Index in this case). Thus we first alias the original
|
7
|
+
# new method (from Object) to __new__ when the Index class is evaluated,
|
8
8
|
# and then we use an inherited hook such that the old new method (from
|
9
9
|
# Object) is once again the default .new for the subclass.
|
10
10
|
# Refer http://blog.sidu.in/2007/12/rubys-new-as-factory.html
|
11
11
|
class << self
|
12
12
|
alias :__new__ :new
|
13
|
-
|
13
|
+
|
14
14
|
def inherited subclass
|
15
15
|
class << subclass
|
16
16
|
alias :new :__new__
|
@@ -23,19 +23,14 @@ module Daru
|
|
23
23
|
def self.new *args, &block
|
24
24
|
source = args[0]
|
25
25
|
|
26
|
-
|
27
|
-
if source and source[0].is_a?(Array)
|
26
|
+
if source.respond_to?(:first) && source.first.is_a?(Array)
|
28
27
|
Daru::MultiIndex.from_tuples source
|
29
|
-
elsif source
|
30
|
-
|
28
|
+
elsif source && source.is_a?(Array) && !source.empty? &&
|
29
|
+
source.all? { |e| e.is_a?(DateTime) }
|
31
30
|
Daru::DateTimeIndex.new(source, freq: :infer)
|
32
31
|
else
|
33
|
-
i
|
34
|
-
i.send :initialize, *args, &block
|
35
|
-
i
|
32
|
+
allocate.tap { |i| i.send :initialize, *args, &block }
|
36
33
|
end
|
37
|
-
|
38
|
-
idx
|
39
34
|
end
|
40
35
|
|
41
36
|
def each(&block)
|
@@ -50,41 +45,54 @@ module Daru
|
|
50
45
|
attr_reader :relation_hash, :size
|
51
46
|
|
52
47
|
def initialize index
|
53
|
-
index =
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
48
|
+
index =
|
49
|
+
case index
|
50
|
+
when nil
|
51
|
+
[]
|
52
|
+
when Integer
|
53
|
+
index.times.to_a
|
54
|
+
when Enumerable
|
55
|
+
index.to_a
|
56
|
+
else
|
57
|
+
raise ArgumentError,
|
58
|
+
"Cannot create index from #{index.class} #{index.inspect}"
|
59
|
+
end
|
61
60
|
|
62
|
-
@relation_hash.freeze
|
61
|
+
@relation_hash = index.each_with_index.to_h.freeze
|
63
62
|
@keys = @relation_hash.keys
|
64
63
|
@size = @relation_hash.size
|
65
64
|
end
|
66
65
|
|
67
66
|
def ==(other)
|
68
|
-
return false if self.class != other.class
|
67
|
+
return false if self.class != other.class || other.size != @size
|
69
68
|
|
70
|
-
@relation_hash.keys
|
71
|
-
|
69
|
+
@relation_hash.keys == other.to_a &&
|
70
|
+
@relation_hash.values == other.relation_hash.values
|
72
71
|
end
|
73
72
|
|
74
73
|
def [](*key)
|
75
74
|
loc = key[0]
|
76
75
|
|
77
|
-
case
|
76
|
+
case
|
78
77
|
when loc.is_a?(Range)
|
79
78
|
first = loc.first
|
80
79
|
last = loc.last
|
81
80
|
|
82
81
|
slice first, last
|
83
82
|
when key.size > 1
|
84
|
-
|
83
|
+
if include? key[0]
|
84
|
+
Daru::Index.new key.map { |k| k }
|
85
|
+
else
|
86
|
+
# Assume the user is specifing values for index not keys
|
87
|
+
# Return index object having keys corresponding to values provided
|
88
|
+
Daru::Index.new key.map { |k| key k }
|
89
|
+
end
|
85
90
|
else
|
86
91
|
v = @relation_hash[loc]
|
87
|
-
|
92
|
+
unless v
|
93
|
+
return loc if loc.is_a?(Numeric) && loc < size
|
94
|
+
raise IndexError, "Specified index #{loc.inspect} does not exist"
|
95
|
+
end
|
88
96
|
v
|
89
97
|
end
|
90
98
|
end
|
@@ -92,9 +100,8 @@ module Daru
|
|
92
100
|
def slice *args
|
93
101
|
start = args[0]
|
94
102
|
en = args[1]
|
95
|
-
indexes = []
|
96
103
|
|
97
|
-
if start.is_a?(Integer)
|
104
|
+
if start.is_a?(Integer) && en.is_a?(Integer)
|
98
105
|
Index.new @keys[start..en]
|
99
106
|
else
|
100
107
|
start_idx = @relation_hash[start]
|
@@ -111,7 +118,6 @@ module Daru
|
|
111
118
|
|
112
119
|
# Produce a new index from the set intersection of two indexes
|
113
120
|
def & other
|
114
|
-
|
115
121
|
end
|
116
122
|
|
117
123
|
def to_a
|
@@ -123,7 +129,7 @@ module Daru
|
|
123
129
|
end
|
124
130
|
|
125
131
|
def include? index
|
126
|
-
@relation_hash.
|
132
|
+
@relation_hash.key? index
|
127
133
|
end
|
128
134
|
|
129
135
|
def empty?
|
@@ -134,8 +140,8 @@ module Daru
|
|
134
140
|
Daru::Index.new @relation_hash.keys
|
135
141
|
end
|
136
142
|
|
137
|
-
def _dump
|
138
|
-
Marshal.dump(
|
143
|
+
def _dump(*)
|
144
|
+
Marshal.dump(relation_hash: @relation_hash)
|
139
145
|
end
|
140
146
|
|
141
147
|
def self._load data
|
@@ -143,13 +149,21 @@ module Daru
|
|
143
149
|
|
144
150
|
Daru::Index.new(h[:relation_hash].keys)
|
145
151
|
end
|
152
|
+
|
153
|
+
# Provide an Index for sub vector produced
|
154
|
+
#
|
155
|
+
# @param input_indexes [Array] the input by user to index the vector
|
156
|
+
# @return [Object] the Index object for sub vector produced
|
157
|
+
def conform(*)
|
158
|
+
self
|
159
|
+
end
|
146
160
|
end # class Index
|
147
161
|
|
148
162
|
class MultiIndex < Index
|
149
163
|
include Enumerable
|
150
164
|
|
151
165
|
def each(&block)
|
152
|
-
to_a.each(&block)
|
166
|
+
to_a.each(&block)
|
153
167
|
end
|
154
168
|
|
155
169
|
def map(&block)
|
@@ -159,28 +173,27 @@ module Daru
|
|
159
173
|
attr_reader :labels
|
160
174
|
|
161
175
|
def levels
|
162
|
-
@levels.map
|
176
|
+
@levels.map(&:keys)
|
163
177
|
end
|
164
178
|
|
165
179
|
def initialize opts={}
|
166
180
|
labels = opts[:labels]
|
167
181
|
levels = opts[:levels]
|
168
182
|
|
169
|
-
raise ArgumentError,
|
170
|
-
"Must specify both labels and levels" unless labels and levels
|
171
183
|
raise ArgumentError,
|
172
|
-
|
184
|
+
'Must specify both labels and levels' unless labels && levels
|
185
|
+
raise ArgumentError,
|
186
|
+
'Labels and levels should be same size' if labels.size != levels.size
|
173
187
|
raise ArgumentError,
|
174
|
-
|
188
|
+
'Incorrect labels and levels' if incorrect_fields?(labels, levels)
|
175
189
|
|
176
190
|
@labels = labels
|
177
|
-
@levels = levels.map { |e| Hash[e.map.with_index.to_a]}
|
191
|
+
@levels = levels.map { |e| Hash[e.map.with_index.to_a] }
|
178
192
|
end
|
179
193
|
|
180
|
-
def incorrect_fields?
|
181
|
-
|
194
|
+
def incorrect_fields?(_labels, levels)
|
195
|
+
levels[0].size # FIXME: without this call everything fails
|
182
196
|
|
183
|
-
correct = labels.all? { |e| e.size == max_level }
|
184
197
|
correct = levels.all? { |e| e.uniq.size == e.size }
|
185
198
|
|
186
199
|
!correct
|
@@ -189,7 +202,7 @@ module Daru
|
|
189
202
|
private :incorrect_fields?
|
190
203
|
|
191
204
|
def self.from_arrays arrays
|
192
|
-
levels = arrays.map { |e| e.uniq.sort_by
|
205
|
+
levels = arrays.map { |e| e.uniq.sort_by(&:to_s) }
|
193
206
|
labels = []
|
194
207
|
|
195
208
|
arrays.each_with_index do |arry, level_index|
|
@@ -214,12 +227,17 @@ module Daru
|
|
214
227
|
case
|
215
228
|
when key[0].is_a?(Range) then retrieve_from_range(key[0])
|
216
229
|
when (key[0].is_a?(Integer) and key.size == 1) then try_retrieve_from_integer(key[0])
|
217
|
-
else
|
230
|
+
else
|
231
|
+
begin
|
232
|
+
retrieve_from_tuples key
|
233
|
+
rescue NoMethodError
|
234
|
+
raise IndexError, "Specified index #{key.inspect} do not exist"
|
235
|
+
end
|
218
236
|
end
|
219
237
|
end
|
220
238
|
|
221
239
|
def try_retrieve_from_integer int
|
222
|
-
return retrieve_from_tuples([int]) if @levels[0].
|
240
|
+
return retrieve_from_tuples([int]) if @levels[0].key?(int)
|
223
241
|
int
|
224
242
|
end
|
225
243
|
|
@@ -232,12 +250,13 @@ module Daru
|
|
232
250
|
|
233
251
|
key.each_with_index do |k, depth|
|
234
252
|
level_index = @levels[depth][k]
|
253
|
+
raise IndexError, "Specified index #{key.inspect} do not exist" if level_index.nil?
|
235
254
|
label = @labels[depth]
|
236
255
|
chosen = find_all_indexes label, level_index, chosen
|
237
256
|
end
|
238
257
|
|
239
|
-
return chosen[0] if chosen.size == 1
|
240
|
-
|
258
|
+
return chosen[0] if chosen.size == 1 && key.size == @levels.size
|
259
|
+
multi_index_from_multiple_selections(chosen)
|
241
260
|
end
|
242
261
|
|
243
262
|
def multi_index_from_multiple_selections chosen
|
@@ -246,14 +265,11 @@ module Daru
|
|
246
265
|
|
247
266
|
def find_all_indexes label, level_index, chosen
|
248
267
|
if chosen.empty?
|
249
|
-
label.each_with_index
|
250
|
-
|
251
|
-
end
|
268
|
+
label.each_with_index
|
269
|
+
.select { |lbl, _| lbl == level_index }.map(&:last)
|
252
270
|
else
|
253
271
|
chosen.keep_if { |c| label[c] == level_index }
|
254
272
|
end
|
255
|
-
|
256
|
-
chosen
|
257
273
|
end
|
258
274
|
|
259
275
|
private :find_all_indexes, :multi_index_from_multiple_selections,
|
@@ -263,11 +279,10 @@ module Daru
|
|
263
279
|
raise ArgumentError,
|
264
280
|
"Key #{index} is too large" if index >= @labels[0].size
|
265
281
|
|
266
|
-
level_indexes =
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
end
|
282
|
+
level_indexes =
|
283
|
+
@labels.each_with_object([]) do |label, memo|
|
284
|
+
memo << label[index]
|
285
|
+
end
|
271
286
|
|
272
287
|
tuple = []
|
273
288
|
level_indexes.each_with_index do |level_index, i|
|
@@ -294,7 +309,7 @@ module Daru
|
|
294
309
|
end
|
295
310
|
|
296
311
|
def empty?
|
297
|
-
@labels.flatten.empty? and @levels.all?
|
312
|
+
@labels.flatten.empty? and @levels.all?(&:empty?)
|
298
313
|
end
|
299
314
|
|
300
315
|
def include? tuple
|
@@ -314,9 +329,9 @@ module Daru
|
|
314
329
|
end
|
315
330
|
|
316
331
|
def == other
|
317
|
-
self.class == other.class
|
318
|
-
|
319
|
-
|
332
|
+
self.class == other.class &&
|
333
|
+
labels == other.labels &&
|
334
|
+
levels == other.levels
|
320
335
|
end
|
321
336
|
|
322
337
|
def to_a
|
@@ -328,7 +343,16 @@ module Daru
|
|
328
343
|
end
|
329
344
|
|
330
345
|
def inspect
|
331
|
-
"Daru::MultiIndex:#{
|
346
|
+
"Daru::MultiIndex:#{object_id} (levels: #{levels}\nlabels: #{labels})"
|
347
|
+
end
|
348
|
+
|
349
|
+
# Provide a MultiIndex for sub vector produced
|
350
|
+
#
|
351
|
+
# @param input_indexes [Array] the input by user to index the vector
|
352
|
+
# @return [Object] the MultiIndex object for sub vector produced
|
353
|
+
def conform input_indexes
|
354
|
+
return self if input_indexes[0].is_a? Range
|
355
|
+
drop_left_level input_indexes.size
|
332
356
|
end
|
333
357
|
end
|
334
|
-
end
|
358
|
+
end
|