0
# Indexing and Selection
1
2
Advanced indexing, selection, and extraction operations including fancy indexing, boolean indexing, and element insertion for flexible array manipulation. CuPy provides comprehensive GPU-accelerated indexing capabilities with NumPy compatibility for complex data selection patterns.
3
4
## Capabilities
5
6
### Basic Indexing and Slicing
7
8
Fundamental array indexing operations for accessing and modifying array elements.
9
10
```python { .api }
11
def take(a, indices, axis=None, out=None, mode='raise'):
12
"""Take elements from array along specified axis.
13
14
Args:
15
a: Input array
16
indices: Indices of elements to take
17
axis: Axis along which to take elements
18
out: Output array
19
mode: How to handle out-of-bounds indices ('raise', 'wrap', 'clip')
20
21
Returns:
22
cupy.ndarray: Selected elements
23
"""
24
25
def take_along_axis(arr, indices, axis):
26
"""Take values from input array by matching 1D index array.
27
28
Args:
29
arr: Input array
30
indices: Indices array with same ndim as arr
31
axis: Axis along which to take values
32
33
Returns:
34
cupy.ndarray: Selected values
35
"""
36
37
def compress(condition, a, axis=None, out=None):
38
"""Select slices along axis using boolean condition.
39
40
Args:
41
condition: Boolean 1-D array selecting slices
42
a: Input array
43
axis: Axis along which to select
44
out: Output array
45
46
Returns:
47
cupy.ndarray: Compressed array
48
"""
49
50
def diagonal(a, offset=0, axis1=0, axis2=1):
51
"""Extract diagonal elements from 2-D array.
52
53
Args:
54
a: Input array (≥2D)
55
offset: Diagonal offset (0 for main diagonal)
56
axis1: First axis for diagonal
57
axis2: Second axis for diagonal
58
59
Returns:
60
cupy.ndarray: Diagonal elements
61
"""
62
63
def diag(v, k=0):
64
"""Extract diagonal or construct diagonal array.
65
66
Args:
67
v: Input array or 1-D array for diagonal construction
68
k: Diagonal offset
69
70
Returns:
71
cupy.ndarray: Diagonal elements or diagonal matrix
72
"""
73
```
74
75
### Advanced Selection
76
77
Sophisticated selection methods for complex data access patterns.
78
79
```python { .api }
80
def choose(a, choices, out=None, mode='raise'):
81
"""Use index array to construct new array from choice arrays.
82
83
Args:
84
a: Index array (integers)
85
choices: Sequence of arrays to choose from
86
out: Output array
87
mode: How to handle out-of-bounds indices
88
89
Returns:
90
cupy.ndarray: Array constructed from choices
91
"""
92
93
def select(condlist, choicelist, default=0):
94
"""Select elements from choicelist based on conditions.
95
96
Args:
97
condlist: List of boolean conditions
98
choicelist: List of arrays/scalars to choose from
99
default: Default value when no condition is True
100
101
Returns:
102
cupy.ndarray: Array with selected elements
103
"""
104
105
def extract(condition, arr):
106
"""Extract elements satisfying condition.
107
108
Args:
109
condition: Boolean array or condition
110
arr: Input array
111
112
Returns:
113
cupy.ndarray: 1-D array of elements where condition is True
114
"""
115
116
def where(condition, x=None, y=None):
117
"""Select elements from x or y based on condition.
118
119
Args:
120
condition: Boolean array condition
121
x: Array/scalar for True elements
122
y: Array/scalar for False elements
123
124
Returns:
125
cupy.ndarray or tuple: Selected elements or indices
126
"""
127
```
128
129
### Index Generation and Utilities
130
131
Functions for generating and manipulating array indices.
132
133
```python { .api }
134
def indices(dimensions, dtype=int, sparse=False):
135
"""Return grid of indices for given dimensions.
136
137
Args:
138
dimensions: Shape of output grid
139
dtype: Data type for indices
140
sparse: Return sparse representation
141
142
Returns:
143
cupy.ndarray: Grid indices array
144
"""
145
146
def ix_(*args):
147
"""Construct open mesh from multiple sequences.
148
149
Args:
150
*args: 1-D sequences for each dimension
151
152
Returns:
153
tuple: Tuple of arrays for open mesh indexing
154
"""
155
156
def ravel_multi_index(multi_index, dims, mode='raise', order='C'):
157
"""Convert multi-dimensional index to flat index.
158
159
Args:
160
multi_index: Tuple of index arrays
161
dims: Shape of array being indexed
162
mode: How to handle out-of-bounds indices
163
order: Memory layout ('C' or 'F')
164
165
Returns:
166
cupy.ndarray: Flat indices
167
"""
168
169
def unravel_index(indices, shape, order='C'):
170
"""Convert flat index to multi-dimensional index.
171
172
Args:
173
indices: Flat index array
174
shape: Shape to unravel into
175
order: Memory layout ('C' or 'F')
176
177
Returns:
178
tuple: Tuple of index arrays
179
"""
180
181
def nonzero(a):
182
"""Return indices of non-zero elements.
183
184
Args:
185
a: Input array
186
187
Returns:
188
tuple: Tuple of index arrays for each dimension
189
"""
190
191
def flatnonzero(a):
192
"""Return indices of non-zero elements in flattened array.
193
194
Args:
195
a: Input array
196
197
Returns:
198
cupy.ndarray: 1-D array of flat indices
199
"""
200
201
def argwhere(a):
202
"""Return indices of non-zero elements grouped by element.
203
204
Args:
205
a: Input array
206
207
Returns:
208
cupy.ndarray: 2-D array where each row is an index
209
"""
210
```
211
212
### Searching and Sorting Indices
213
214
Functions for finding extrema, sorting, and searching within arrays.
215
216
```python { .api }
217
def argmax(a, axis=None, out=None, keepdims=False):
218
"""Indices of maximum values along axis.
219
220
Args:
221
a: Input array
222
axis: Axis for computation
223
out: Output array
224
keepdims: Keep reduced dimensions
225
226
Returns:
227
cupy.ndarray: Indices of maximum elements
228
"""
229
230
def argmin(a, axis=None, out=None, keepdims=False):
231
"""Indices of minimum values along axis.
232
233
Args:
234
a: Input array
235
axis: Axis for computation
236
out: Output array
237
keepdims: Keep reduced dimensions
238
239
Returns:
240
cupy.ndarray: Indices of minimum elements
241
"""
242
243
def nanargmax(a, axis=None, out=None, keepdims=False):
244
"""Indices of maximum values ignoring NaNs.
245
246
Args:
247
a: Input array
248
axis: Axis for computation
249
out: Output array
250
keepdims: Keep reduced dimensions
251
252
Returns:
253
cupy.ndarray: Indices of maximum elements (ignoring NaN)
254
"""
255
256
def nanargmin(a, axis=None, out=None, keepdims=False):
257
"""Indices of minimum values ignoring NaNs.
258
259
Args:
260
a: Input array
261
axis: Axis for computation
262
out: Output array
263
keepdims: Keep reduced dimensions
264
265
Returns:
266
cupy.ndarray: Indices of minimum elements (ignoring NaN)
267
"""
268
269
def argsort(a, axis=-1, kind=None, order=None):
270
"""Indices that would sort array along axis.
271
272
Args:
273
a: Input array
274
axis: Axis to sort along
275
kind: Sorting algorithm (None, 'quicksort', 'mergesort', 'heapsort')
276
order: Field order for structured arrays
277
278
Returns:
279
cupy.ndarray: Array of indices that sort input
280
"""
281
282
def argpartition(a, kth, axis=-1, kind='introselect', order=None):
283
"""Indices that partition array around kth element.
284
285
Args:
286
a: Input array
287
kth: Element index around which to partition
288
axis: Axis to partition along
289
kind: Partitioning algorithm
290
order: Field order for structured arrays
291
292
Returns:
293
cupy.ndarray: Array of partition indices
294
"""
295
296
def searchsorted(a, v, side='left', sorter=None):
297
"""Find indices to insert elements to maintain sorted order.
298
299
Args:
300
a: Input sorted array
301
v: Values to insert
302
side: Insert position ('left' or 'right')
303
sorter: Optional array of indices that sort a
304
305
Returns:
306
cupy.ndarray: Insertion indices
307
"""
308
```
309
310
### Element Insertion and Modification
311
312
Functions for inserting, placing, and modifying array elements.
313
314
```python { .api }
315
def put(a, ind, v, mode='raise'):
316
"""Put values into array at specified indices.
317
318
Args:
319
a: Target array (modified in-place)
320
ind: Target indices
321
v: Values to insert
322
mode: How to handle out-of-bounds indices
323
"""
324
325
def place(arr, mask, vals):
326
"""Place values into array based on boolean mask.
327
328
Args:
329
arr: Target array (modified in-place)
330
mask: Boolean array indicating positions
331
vals: Values to place
332
"""
333
334
def putmask(a, mask, values):
335
"""Put values where mask is True.
336
337
Args:
338
a: Target array (modified in-place)
339
mask: Boolean mask
340
values: Replacement values
341
"""
342
343
def fill_diagonal(a, val, wrap=False):
344
"""Fill main diagonal of array.
345
346
Args:
347
a: Array to modify (≥2D)
348
val: Value to fill diagonal with
349
wrap: Wrap diagonal for non-square arrays
350
"""
351
352
def diag_indices(n, ndim=2):
353
"""Return indices for diagonal elements.
354
355
Args:
356
n: Size of arrays for which indices are returned
357
ndim: Number of dimensions
358
359
Returns:
360
tuple: Indices for diagonal elements
361
"""
362
363
def diag_indices_from(arr):
364
"""Return indices for diagonal of n-dimensional array.
365
366
Args:
367
arr: Input array
368
369
Returns:
370
tuple: Indices for diagonal elements
371
"""
372
```
373
374
### Masking and Conditional Operations
375
376
Advanced masking operations for selective array processing.
377
378
```python { .api }
379
def mask_indices(n, mask_func, k=0):
380
"""Return indices for masking based on function.
381
382
Args:
383
n: Number of rows/columns in output
384
mask_func: Function defining mask pattern
385
k: Optional parameter for mask function
386
387
Returns:
388
tuple: Indices satisfying mask condition
389
"""
390
391
def tril_indices(n, k=0, m=None):
392
"""Return indices for lower triangle of array.
393
394
Args:
395
n: Number of rows in output
396
k: Diagonal offset
397
m: Number of columns (defaults to n)
398
399
Returns:
400
tuple: Lower triangle indices
401
"""
402
403
def tril_indices_from(arr, k=0):
404
"""Return indices for lower triangle of given array.
405
406
Args:
407
arr: Input array
408
k: Diagonal offset
409
410
Returns:
411
tuple: Lower triangle indices
412
"""
413
414
def triu_indices(n, k=0, m=None):
415
"""Return indices for upper triangle of array.
416
417
Args:
418
n: Number of rows in output
419
k: Diagonal offset
420
m: Number of columns (defaults to n)
421
422
Returns:
423
tuple: Upper triangle indices
424
"""
425
426
def triu_indices_from(arr, k=0):
427
"""Return indices for upper triangle of given array.
428
429
Args:
430
arr: Input array
431
k: Diagonal offset
432
433
Returns:
434
tuple: Upper triangle indices
435
"""
436
437
def meshgrid(*xi, copy=True, sparse=False, indexing='xy'):
438
"""Create coordinate arrays from coordinate vectors.
439
440
Args:
441
*xi: 1-D arrays for coordinates
442
copy: Return copies of input arrays
443
sparse: Return sparse grid
444
indexing: Cartesian ('xy') or matrix ('ij') indexing
445
446
Returns:
447
list: Coordinate arrays
448
"""
449
```
450
451
### Iterator Objects
452
453
Iterator classes for advanced array traversal patterns.
454
455
```python { .api }
456
class flatiter:
457
"""Iterator for flattened array.
458
459
Provides iteration over array as if it were 1-dimensional.
460
461
Attributes:
462
base: Base array being iterated
463
coords: Current coordinates
464
index: Current flat index
465
"""
466
467
def __iter__(self):
468
"""Return iterator object."""
469
pass
470
471
def __next__(self):
472
"""Get next element."""
473
pass
474
475
def __getitem__(self, key):
476
"""Get element(s) by index/slice."""
477
pass
478
479
def __setitem__(self, key, value):
480
"""Set element(s) by index/slice."""
481
pass
482
483
class nditer:
484
"""Multi-dimensional iterator object.
485
486
Args:
487
op: Array(s) to iterate over
488
flags: Iteration flags
489
op_flags: Per-operand flags
490
op_dtypes: Per-operand data types
491
order: Iteration order
492
casting: Casting rule
493
op_axes: Per-operand axes
494
itershape: Iteration shape
495
buffersize: Buffer size
496
497
Provides advanced iteration patterns with broadcasting,
498
buffering, and multi-array iteration.
499
"""
500
501
def __init__(self, op, flags=None, op_flags=None, op_dtypes=None,
502
order='K', casting='safe', op_axes=None, itershape=None,
503
buffersize=0):
504
pass
505
```
506
507
## Usage Examples
508
509
### Basic Indexing and Selection
510
511
```python
512
import cupy as cp
513
514
# Create sample array
515
data = cp.arange(24).reshape(4, 6)
516
print(f"Original array:\n{data}")
517
518
# Basic indexing
519
element = data[1, 3] # Single element
520
row = data[2] # Entire row
521
column = data[:, 1] # Entire column
522
subarray = data[1:3, 2:5] # Rectangular slice
523
524
print(f"Element [1,3]: {element}")
525
print(f"Row 2: {row}")
526
print(f"Column 1: {column}")
527
print(f"Subarray [1:3, 2:5]:\n{subarray}")
528
529
# Take elements by indices
530
indices = cp.array([0, 2, 1, 3])
531
taken_rows = cp.take(data, indices, axis=0)
532
taken_elements = cp.take(data.flatten(), cp.array([5, 10, 15, 20]))
533
534
print(f"Taken rows (indices {indices}):\n{taken_rows}")
535
print(f"Taken elements: {taken_elements}")
536
537
# Diagonal extraction
538
diag_main = cp.diagonal(data) # Main diagonal
539
diag_upper = cp.diagonal(data, offset=1) # Upper diagonal
540
diag_lower = cp.diagonal(data, offset=-1) # Lower diagonal
541
542
print(f"Main diagonal: {diag_main}")
543
print(f"Upper diagonal: {diag_upper}")
544
print(f"Lower diagonal: {diag_lower}")
545
```
546
547
### Boolean and Fancy Indexing
548
549
```python
550
import cupy as cp
551
552
# Create test data
553
temperatures = cp.array([18.5, 22.1, 28.7, 31.4, 19.8, 25.3, 33.1, 16.9])
554
cities = cp.array(['NYC', 'LA', 'MIA', 'PHX', 'SEA', 'CHI', 'LAS', 'BOS'])
555
556
# Boolean indexing
557
hot_weather = temperatures > 25
558
cold_weather = temperatures < 20
559
moderate_weather = (temperatures >= 20) & (temperatures <= 30)
560
561
hot_cities = cities[hot_weather]
562
cold_cities = cities[cold_weather]
563
hot_temps = temperatures[hot_weather]
564
565
print(f"Hot cities (>25°C): {hot_cities}")
566
print(f"Hot temperatures: {hot_temps}")
567
print(f"Cold cities (<20°C): {cold_cities}")
568
569
# Fancy indexing with arrays
570
indices = cp.array([1, 3, 5, 7]) # Select specific indices
571
selected_temps = temperatures[indices]
572
selected_cities = cities[indices]
573
574
print(f"Selected temperatures: {selected_temps}")
575
print(f"Selected cities: {selected_cities}")
576
577
# Multi-dimensional boolean indexing
578
matrix = cp.random.randn(5, 8)
579
positive = matrix > 0
580
negative = matrix < 0
581
extreme = cp.abs(matrix) > 1.5
582
583
print(f"Matrix shape: {matrix.shape}")
584
print(f"Positive elements: {cp.sum(positive)}")
585
print(f"Negative elements: {cp.sum(negative)}")
586
print(f"Extreme values: {cp.sum(extreme)}")
587
588
# Extract extreme values and their positions
589
extreme_values = matrix[extreme]
590
extreme_positions = cp.argwhere(extreme)
591
592
print(f"First 5 extreme values: {extreme_values[:5]}")
593
print(f"First 5 extreme positions:\n{extreme_positions[:5]}")
594
```
595
596
### Advanced Selection with where and choose
597
598
```python
599
import cupy as cp
600
601
# Sample data - student scores
602
math_scores = cp.array([85, 92, 76, 88, 91, 73, 95, 82])
603
english_scores = cp.array([78, 89, 94, 82, 86, 88, 91, 79])
604
science_scores = cp.array([90, 87, 81, 95, 89, 76, 93, 85])
605
606
# Use where for conditional selection
607
# Select higher of math or english score for each student
608
higher_score = cp.where(math_scores > english_scores, math_scores, english_scores)
609
610
print(f"Math scores: {math_scores}")
611
print(f"English scores: {english_scores}")
612
print(f"Higher scores: {higher_score}")
613
614
# Multi-condition selection with where
615
# Assign letter grades based on best score
616
best_scores = cp.maximum(cp.maximum(math_scores, english_scores), science_scores)
617
grades = cp.where(best_scores >= 90, 'A',
618
cp.where(best_scores >= 80, 'B',
619
cp.where(best_scores >= 70, 'C', 'F')))
620
621
print(f"Best scores: {best_scores}")
622
print(f"Grades: {grades}")
623
624
# Using choose for more complex selection
625
# Choose subject based on student preference (0=math, 1=english, 2=science)
626
preferences = cp.array([0, 2, 1, 0, 2, 1, 0, 1]) # Student preferences
627
score_arrays = cp.array([math_scores, english_scores, science_scores])
628
preferred_scores = cp.choose(preferences, score_arrays)
629
630
print(f"Preferences: {preferences}")
631
print(f"Preferred scores: {preferred_scores}")
632
633
# Using select for multiple conditions
634
conditions = [
635
best_scores >= 95, # Excellent
636
best_scores >= 85, # Good
637
best_scores >= 75, # Fair
638
]
639
choices = ['Excellent', 'Good', 'Fair']
640
performance = cp.select(conditions, choices, default='Poor')
641
642
print(f"Performance ratings: {performance}")
643
```
644
645
### Finding and Extracting Elements
646
647
```python
648
import cupy as cp
649
650
# Create sample dataset
651
data = cp.random.randn(1000, 10)
652
outlier_threshold = 2.5
653
654
# Find indices of extremes
655
max_indices = cp.argmax(data, axis=1) # Max in each row
656
min_indices = cp.argmin(data, axis=1) # Min in each row
657
overall_max_idx = cp.argmax(data) # Overall max (flat index)
658
overall_min_idx = cp.argmin(data) # Overall min (flat index)
659
660
print(f"Data shape: {data.shape}")
661
print(f"Overall max at flat index: {overall_max_idx}")
662
print(f"Overall min at flat index: {overall_min_idx}")
663
664
# Convert flat indices to 2D coordinates
665
max_coords = cp.unravel_index(overall_max_idx, data.shape)
666
min_coords = cp.unravel_index(overall_min_idx, data.shape)
667
668
print(f"Max at coordinates: {max_coords}")
669
print(f"Min at coordinates: {min_coords}")
670
print(f"Max value: {data[max_coords]:.3f}")
671
print(f"Min value: {data[min_coords]:.3f}")
672
673
# Find outliers (values beyond threshold)
674
outliers_mask = cp.abs(data) > outlier_threshold
675
outlier_positions = cp.argwhere(outliers_mask)
676
outlier_values = data[outliers_mask]
677
678
print(f"Number of outliers: {len(outlier_values)}")
679
print(f"First 5 outlier positions:\n{outlier_positions[:5]}")
680
print(f"First 5 outlier values: {outlier_values[:5]}")
681
682
# Non-zero elements
683
nonzero_mask = data != 0
684
nonzero_indices = cp.nonzero(nonzero_mask)
685
nonzero_count = len(nonzero_indices[0])
686
687
print(f"Non-zero elements: {nonzero_count}/{data.size}")
688
689
# Extract elements satisfying complex conditions
690
condition = (data > 0) & (cp.abs(data) < 1.0) # Positive values between 0 and 1
691
extracted = cp.extract(condition, data)
692
693
print(f"Values between 0 and 1: {len(extracted)}")
694
print(f"Mean of extracted values: {cp.mean(extracted):.3f}")
695
```
696
697
### Sorting and Searching
698
699
```python
700
import cupy as cp
701
702
# Create unsorted data
703
scores = cp.array([87, 92, 76, 88, 91, 73, 95, 82, 89, 78])
704
names = cp.array(['Alice', 'Bob', 'Charlie', 'David', 'Eve',
705
'Frank', 'Grace', 'Henry', 'Iris', 'Jack'])
706
707
print(f"Original scores: {scores}")
708
print(f"Original names: {names}")
709
710
# Get indices that would sort the scores
711
sort_indices = cp.argsort(scores)
712
reverse_sort_indices = cp.argsort(-scores) # Descending order
713
714
sorted_scores = scores[sort_indices]
715
sorted_names = names[sort_indices]
716
top_scores = scores[reverse_sort_indices]
717
top_names = names[reverse_sort_indices]
718
719
print(f"Sorted scores (ascending): {sorted_scores}")
720
print(f"Sorted names (by score): {sorted_names}")
721
print(f"Top scores (descending): {top_scores}")
722
print(f"Top names (by score): {top_names}")
723
724
# Partial sorting - find top 3 students
725
top_k = 3
726
top_k_indices = cp.argpartition(-scores, top_k)[:top_k]
727
top_k_scores = scores[top_k_indices]
728
top_k_names = names[top_k_indices]
729
730
# Sort the top k for proper ranking
731
top_k_order = cp.argsort(-top_k_scores)
732
final_top_scores = top_k_scores[top_k_order]
733
final_top_names = top_k_names[top_k_order]
734
735
print(f"Top {top_k} scores: {final_top_scores}")
736
print(f"Top {top_k} names: {final_top_names}")
737
738
# Searching in sorted array
739
target_scores = cp.array([80, 90, 95])
740
sorted_scores = cp.sort(scores)
741
742
# Find insertion positions
743
insert_left = cp.searchsorted(sorted_scores, target_scores, side='left')
744
insert_right = cp.searchsorted(sorted_scores, target_scores, side='right')
745
746
print(f"Sorted scores: {sorted_scores}")
747
print(f"Target scores: {target_scores}")
748
print(f"Insert positions (left): {insert_left}")
749
print(f"Insert positions (right): {insert_right}")
750
751
# Count how many scores are below each target
752
below_count = insert_left
753
print(f"Scores below targets: {below_count}")
754
```
755
756
### Multi-dimensional Indexing and Meshgrids
757
758
```python
759
import cupy as cp
760
761
# Create coordinate grids
762
x = cp.linspace(-2, 2, 5)
763
y = cp.linspace(-1, 1, 4)
764
765
# Create meshgrid for function evaluation
766
X, Y = cp.meshgrid(x, y)
767
print(f"X coordinates:\n{X}")
768
print(f"Y coordinates:\n{Y}")
769
770
# Evaluate function over grid
771
Z = X**2 + Y**2 # Distance from origin squared
772
print(f"Function values:\n{Z}")
773
774
# Advanced indexing with meshgrid
775
# Select elements where distance is less than 2
776
distance_mask = Z < 2.0
777
selected_X = X[distance_mask]
778
selected_Y = Y[distance_mask]
779
selected_Z = Z[distance_mask]
780
781
print(f"Selected coordinates (distance < 2):")
782
print(f"X: {selected_X}")
783
print(f"Y: {selected_Y}")
784
print(f"Z: {selected_Z}")
785
786
# Open mesh indexing with ix_
787
rows = cp.array([0, 2])
788
cols = cp.array([1, 3, 4])
789
row_idx, col_idx = cp.ix_(rows, cols)
790
791
print(f"Open mesh indices:")
792
print(f"Row indices:\n{row_idx}")
793
print(f"Col indices:\n{col_idx}")
794
795
# Use open mesh to index into array
796
data = cp.arange(20).reshape(4, 5)
797
selected = data[row_idx, col_idx]
798
print(f"Original data:\n{data}")
799
print(f"Selected subarray:\n{selected}")
800
801
# Multi-dimensional index operations
802
shape = (6, 8)
803
flat_indices = cp.array([5, 12, 25, 33, 41])
804
multi_indices = cp.unravel_index(flat_indices, shape)
805
806
print(f"Flat indices: {flat_indices}")
807
print(f"Multi-dimensional indices:")
808
print(f" Row indices: {multi_indices[0]}")
809
print(f" Col indices: {multi_indices[1]}")
810
811
# Convert back to flat indices
812
recovered_flat = cp.ravel_multi_index(multi_indices, shape)
813
print(f"Recovered flat indices: {recovered_flat}")
814
```
815
816
### Array Modification and Masking
817
818
```python
819
import cupy as cp
820
821
# Create sample array
822
data = cp.random.randn(6, 8)
823
print(f"Original data shape: {data.shape}")
824
print(f"Original data (first 3 rows):\n{data[:3]}")
825
826
# Boolean masking for modification
827
# Replace negative values with zero
828
negative_mask = data < 0
829
data_clipped = data.copy()
830
data_clipped[negative_mask] = 0
831
832
print(f"Negative elements: {cp.sum(negative_mask)}")
833
print(f"After clipping negatives (first 3 rows):\n{data_clipped[:3]}")
834
835
# Use place for conditional replacement
836
data_replaced = data.copy()
837
outlier_mask = cp.abs(data) > 2.0
838
cp.place(data_replaced, outlier_mask, cp.nan)
839
840
print(f"Outlier elements: {cp.sum(outlier_mask)}")
841
print(f"Outliers replaced with NaN: {cp.sum(cp.isnan(data_replaced))}")
842
843
# Use putmask for different replacement strategy
844
data_putmask = data.copy()
845
extreme_mask = cp.abs(data) > 1.5
846
replacement_values = cp.sign(data) * 1.5 # Cap at ±1.5
847
cp.putmask(data_putmask, extreme_mask, replacement_values[extreme_mask])
848
849
print(f"Values capped at ±1.5")
850
print(f"Max absolute value: {cp.max(cp.abs(data_putmask)):.3f}")
851
852
# Direct indexing for complex modifications
853
# Set border elements to specific value
854
border_value = -999
855
data_border = data.copy()
856
data_border[0, :] = border_value # Top row
857
data_border[-1, :] = border_value # Bottom row
858
data_border[:, 0] = border_value # Left column
859
data_border[:, -1] = border_value # Right column
860
861
print(f"Border elements set to {border_value}")
862
print(f"Modified array:\n{data_border}")
863
864
# Diagonal operations
865
square_data = data[:6, :6] # Make it square
866
cp.fill_diagonal(square_data, 0)
867
diag_indices = cp.diag_indices(6)
868
square_data[diag_indices] = cp.arange(6) * 10 # Set diagonal to multiples of 10
869
870
print(f"Modified diagonal:\n{square_data}")
871
872
# Triangle operations
873
upper_tri_indices = cp.triu_indices(6, k=1)
874
lower_tri_indices = cp.tril_indices(6, k=-1)
875
876
tri_data = cp.zeros((6, 6))
877
tri_data[upper_tri_indices] = 1 # Upper triangle
878
tri_data[lower_tri_indices] = -1 # Lower triangle
879
880
print(f"Triangle pattern:\n{tri_data}")
881
```
882
883
### Performance-Optimized Indexing
884
885
```python
886
import cupy as cp
887
import time
888
889
# Large dataset for performance testing
890
n = 1_000_000
891
large_data = cp.random.randn(n)
892
indices = cp.random.randint(0, n, size=100_000)
893
894
print(f"Performance test with {n:,} elements")
895
896
# Time different indexing methods
897
methods = [
898
('Direct indexing', lambda: large_data[indices]),
899
('Take method', lambda: cp.take(large_data, indices)),
900
('Boolean masking', lambda: large_data[large_data > 0]),
901
('Where condition', lambda: cp.where(large_data > 0, large_data, 0)),
902
('Compress', lambda: cp.compress(large_data > 0, large_data)),
903
]
904
905
for name, method in methods:
906
start_time = time.perf_counter()
907
result = method()
908
cp.cuda.Stream.null.synchronize() # Wait for GPU
909
end_time = time.perf_counter()
910
911
print(f"{name:16}: {(end_time - start_time)*1000:6.2f} ms, "
912
f"result size: {result.size:8,}")
913
914
# Memory-efficient indexing patterns
915
# Process large array in chunks to avoid memory issues
916
chunk_size = 100_000
917
results = []
918
919
print(f"\nChunked processing:")
920
for i in range(0, n, chunk_size):
921
chunk_end = min(i + chunk_size, n)
922
chunk = large_data[i:chunk_end]
923
924
# Process chunk (example: find outliers)
925
outliers = chunk[cp.abs(chunk) > 2.0]
926
if len(outliers) > 0:
927
results.append(outliers)
928
929
if i // chunk_size < 5: # Show first few chunks
930
print(f"Chunk {i//chunk_size + 1}: "
931
f"processed {chunk_end - i:6,} elements, "
932
f"found {len(outliers):3} outliers")
933
934
if results:
935
all_outliers = cp.concatenate(results)
936
print(f"Total outliers found: {len(all_outliers)}")
937
else:
938
print("No outliers found")
939
```