@@ -3141,6 +3141,285 @@ def indicesofsorted(self, axis=None, ascending=True, kind='quicksort'):
3141
3141
3142
3142
posargsort = renamed_to (indicesofsorted , 'posargsort' )
3143
3143
3144
+ # TODO: implement keys_by
3145
+ # XXX: implement expand=True? Unsure it is necessary now that we have zip_array_*
3146
+ def keys (self , axes = None , ascending = True ):
3147
+ r"""Returns a view on the array labels along axes.
3148
+
3149
+ Parameters
3150
+ ----------
3151
+ axes : int, str or Axis or tuple of them, optional
3152
+ Axis or axes along which to iterate and in which order. Defaults to None (all axes in the order they are
3153
+ in the array).
3154
+ ascending : bool, optional
3155
+ Whether or not to iterate the axes in ascending order (from start to end). Defaults to True.
3156
+
3157
+ Returns
3158
+ -------
3159
+ Sequence
3160
+ An object you can iterate (loop) on and index by position to get the Nth label along axes.
3161
+
3162
+ Examples
3163
+ --------
3164
+ First, define a small helper function to make the following examples more readable.
3165
+
3166
+ >>> def str_key(key):
3167
+ ... return tuple(str(k) for k in key)
3168
+
3169
+ Then create a test array:
3170
+
3171
+ >>> arr = ndtest((2, 2))
3172
+ >>> arr
3173
+ a\b b0 b1
3174
+ a0 0 1
3175
+ a1 2 3
3176
+
3177
+ By default it iterates on all axes, in the order they are in the array.
3178
+
3179
+ >>> for key in arr.keys():
3180
+ ... # print both the actual key object, and a (nicer) string representation
3181
+ ... print(key, "->", str_key(key))
3182
+ (a.i[0], b.i[0]) -> ('a0', 'b0')
3183
+ (a.i[0], b.i[1]) -> ('a0', 'b1')
3184
+ (a.i[1], b.i[0]) -> ('a1', 'b0')
3185
+ (a.i[1], b.i[1]) -> ('a1', 'b1')
3186
+ >>> for key in arr.keys(ascending=False):
3187
+ ... print(str_key(key))
3188
+ ('a1', 'b1')
3189
+ ('a1', 'b0')
3190
+ ('a0', 'b1')
3191
+ ('a0', 'b0')
3192
+
3193
+ but you can specify another axis order:
3194
+
3195
+ >>> for key in arr.keys(('b', 'a')):
3196
+ ... print(str_key(key))
3197
+ ('b0', 'a0')
3198
+ ('b0', 'a1')
3199
+ ('b1', 'a0')
3200
+ ('b1', 'a1')
3201
+
3202
+ One can specify less axes than the array has:
3203
+
3204
+ >>> # iterate on the "b" axis, that is return each label along the "b" axis
3205
+ ... for key in arr.keys('b'):
3206
+ ... print(str_key(key))
3207
+ ('b0',)
3208
+ ('b1',)
3209
+
3210
+ One can also access elements of the key sequence directly, instead of iterating over it. Say we want to
3211
+ retrieve the first and last keys of our array, we could write:
3212
+
3213
+ >>> keys = arr.keys()
3214
+ >>> first_key = keys[0]
3215
+ >>> str_key(first_key)
3216
+ ('a0', 'b0')
3217
+ >>> last_key = keys[-1]
3218
+ >>> str_key(last_key)
3219
+ ('a1', 'b1')
3220
+ """
3221
+ return self .axes .iter_labels (axes , ascending = ascending )
3222
+
3223
+ # TODO: implement values_by
3224
+ def values (self , axes = None , ascending = True , expand = False ):
3225
+ r"""Returns a view on the values of the array along axes.
3226
+
3227
+ Parameters
3228
+ ----------
3229
+ axes : int, str or Axis or tuple of them, optional
3230
+ Axis or axes along which to iterate and in which order. Defaults to None (all axes in the order they are
3231
+ in the array).
3232
+ ascending : bool, optional
3233
+ Whether or not to iterate the axes in ascending order (from start to end). Defaults to True.
3234
+ expand : bool, optional
3235
+ Whether or not to expand array using axes. This allows one to iterate on axes which do not exist in
3236
+ the array, which is useful when iterating on several arrays with different axes. Defaults to False.
3237
+
3238
+ Returns
3239
+ -------
3240
+ Sequence
3241
+ An object you can iterate (loop) on and index by position.
3242
+
3243
+ Examples
3244
+ --------
3245
+ >>> arr = ndtest((2, 2))
3246
+ >>> arr
3247
+ a\b b0 b1
3248
+ a0 0 1
3249
+ a1 2 3
3250
+
3251
+ By default it iterates on all axes, in the order they are in the array.
3252
+
3253
+ >>> for value in arr.values():
3254
+ ... print(value)
3255
+ 0
3256
+ 1
3257
+ 2
3258
+ 3
3259
+ >>> for value in arr.values(ascending=False):
3260
+ ... print(value)
3261
+ 3
3262
+ 2
3263
+ 1
3264
+ 0
3265
+
3266
+ but you can specify another axis order:
3267
+
3268
+ >>> for value in arr.values(('b', 'a')):
3269
+ ... print(value)
3270
+ 0
3271
+ 2
3272
+ 1
3273
+ 3
3274
+
3275
+ When you specify less axes than the array has, you get arrays back:
3276
+
3277
+ >>> # iterate on the "b" axis, that is return the (sub)array for each label along the "b" axis
3278
+ ... for value in arr.values('b'):
3279
+ ... print(value)
3280
+ a a0 a1
3281
+ 0 2
3282
+ a a0 a1
3283
+ 1 3
3284
+ >>> # iterate on the "b" axis, that is return the (sub)array for each label along the "b" axis
3285
+ ... for value in arr.values('b', ascending=False):
3286
+ ... print(value)
3287
+ a a0 a1
3288
+ 1 3
3289
+ a a0 a1
3290
+ 0 2
3291
+ >>> # iterate on the "c" axis, which does not exist in arr, that is return arr for each label along the "c" axis
3292
+ ... for value in arr.values('c=c0,c1', expand=True):
3293
+ ... print(value)
3294
+ a\b b0 b1
3295
+ a0 0 1
3296
+ a1 2 3
3297
+ a\b b0 b1
3298
+ a0 0 1
3299
+ a1 2 3
3300
+
3301
+ One can also access elements of the value sequence directly, instead of iterating over it. Say we want to
3302
+ retrieve the first and last values of our array, we could write:
3303
+
3304
+ >>> values = arr.values()
3305
+ >>> values[0]
3306
+ 0
3307
+ >>> values[-1]
3308
+ 3
3309
+ """
3310
+ if axes is None :
3311
+ combined = np .ravel (self .data )
3312
+ # combined[::-1] *is* indexable
3313
+ return combined if ascending else combined [::- 1 ]
3314
+
3315
+ if not isinstance (axes , (tuple , AxisCollection )):
3316
+ axes = (axes ,)
3317
+
3318
+ def get_axis (a ):
3319
+ if isinstance (a , basestring ):
3320
+ return Axis (a ) if '=' in a else self .axes [a ]
3321
+ elif isinstance (a , int ):
3322
+ return self .axes [a ]
3323
+ else :
3324
+ assert isinstance (a , Axis )
3325
+ return a
3326
+ axes = [get_axis (a ) for a in axes ]
3327
+ array = self .expand (axes , readonly = True ) if expand else self
3328
+ axes = array .axes [axes ]
3329
+ # move axes in front
3330
+ transposed = array .transpose (axes )
3331
+ # combine axes if necessary
3332
+ combined = transposed .combine_axes (axes , wildcard = True ) if len (axes ) > 1 else transposed
3333
+ # trailing .i is to support the case where axis < self.axes (ie the elements of the result are arrays)
3334
+ return combined .i if ascending else combined .i [::- 1 ].i
3335
+
3336
+ # TODO: we currently return a tuple of groups even for 1D arrays, which can be both a bad or a good thing.
3337
+ # if we returned an NDGroup in all cases, it would solve the problem
3338
+ # TODO: implement expand=True
3339
+ def items (self , axes = None , ascending = True ):
3340
+ r"""Returns a (label, value) view of the array along axes.
3341
+
3342
+ Parameters
3343
+ ----------
3344
+ axes : int, str or Axis or tuple of them, optional
3345
+ Axis or axes along which to iterate and in which order. Defaults to None (all axes in the order they are
3346
+ in the array).
3347
+ ascending : bool, optional
3348
+ Whether or not to iterate the axes in ascending order (from start to end). Defaults to True.
3349
+
3350
+ Returns
3351
+ -------
3352
+ Sequence
3353
+ An object you can iterate (loop) on and index by position to get the Nth (label, value) couple along axes.
3354
+
3355
+ Examples
3356
+ --------
3357
+ First, define a small helper function to make the following examples more readable.
3358
+
3359
+ >>> def str_key(key):
3360
+ ... return tuple(str(k) for k in key)
3361
+
3362
+ Then create a test array:
3363
+
3364
+ >>> arr = ndtest((2, 2))
3365
+ >>> arr
3366
+ a\b b0 b1
3367
+ a0 0 1
3368
+ a1 2 3
3369
+
3370
+ By default it iterates on all axes, in the order they are in the array.
3371
+
3372
+ >>> for key, value in arr.items():
3373
+ ... print(str_key(key), "->", value)
3374
+ ('a0', 'b0') -> 0
3375
+ ('a0', 'b1') -> 1
3376
+ ('a1', 'b0') -> 2
3377
+ ('a1', 'b1') -> 3
3378
+ >>> for key, value in arr.items(ascending=False):
3379
+ ... print(str_key(key), "->", value)
3380
+ ('a1', 'b1') -> 3
3381
+ ('a1', 'b0') -> 2
3382
+ ('a0', 'b1') -> 1
3383
+ ('a0', 'b0') -> 0
3384
+
3385
+ but you can specify another axis order:
3386
+
3387
+ >>> for key, value in arr.items(('b', 'a')):
3388
+ ... print(str_key(key), "->", value)
3389
+ ('b0', 'a0') -> 0
3390
+ ('b0', 'a1') -> 2
3391
+ ('b1', 'a0') -> 1
3392
+ ('b1', 'a1') -> 3
3393
+
3394
+ When you specify less axes than the array has, you get arrays back:
3395
+
3396
+ >>> # iterate on the "b" axis, that is return the (sub)array for each label along the "b" axis
3397
+ ... for key, value in arr.items('b'):
3398
+ ... print(str_key(key), value, sep="\n")
3399
+ ('b0',)
3400
+ a a0 a1
3401
+ 0 2
3402
+ ('b1',)
3403
+ a a0 a1
3404
+ 1 3
3405
+
3406
+ One can also access elements of the items sequence directly, instead of iterating over it. Say we want to
3407
+ retrieve the first and last key-value pairs of our array, we could write:
3408
+
3409
+ >>> items = arr.items()
3410
+ >>> first_key, first_value = items[0]
3411
+ >>> str_key(first_key)
3412
+ ('a0', 'b0')
3413
+ >>> first_value
3414
+ 0
3415
+ >>> last_key, last_value = items[-1]
3416
+ >>> str_key(last_key)
3417
+ ('a1', 'b1')
3418
+ >>> last_value
3419
+ 3
3420
+ """
3421
+ return SequenceZip ((self .keys (axes , ascending = ascending ), self .values (axes , ascending = ascending )))
3422
+
3144
3423
def copy (self ):
3145
3424
"""Returns a copy of the array.
3146
3425
"""
@@ -6713,6 +6992,7 @@ def __array__(self, dtype=None):
6713
6992
6714
6993
__array_priority__ = 100
6715
6994
6995
+ # TODO: this should be a thin wrapper around a method in AxisCollection
6716
6996
def set_labels (self , axis = None , labels = None , inplace = False , ** kwargs ):
6717
6997
r"""Replaces the labels of an axis of array.
6718
6998
0 commit comments