<jupyter_start><jupyter_text>When you modify a slice, you actually modify the underlying array.<jupyter_code>print("Before:", an_array[0, 1])   #inspect the element at 0, 1  
a_slice[0, 0] = 99    # a_slice[0, 0] is the same piece of data as an_array[0, 1]
print("After:", an_array[0, 1])    
print(an_array)
# Now copying, not referenceing
a_slice = np.array(an_array[:2, 1:3])
print(a_slice)
print()
print(an_array)
a_slice[0, 0] = 12
print(a_slice)
# but
print(an_array)
# Create a Rank 2 array of shape (3, 4)
an_array = np.array([[11,12,13,14], [21,22,23,24], [31,32,33,34]])
print(an_array)
# Using both integer indexing & slicing generates an array of lower rank
row_rank1 = np.array(an_array[1, :])    # Rank 1 view 

print(row_rank1, row_rank1.shape)  # notice only a single []
print(row_rank1.shape)
# Slicing alone: generates an array of the same rank as the an_array
row_rank2 = an_array[1:2, :]  # Rank 2 view 

print(row_rank2, row_rank2.shape)   # Notice the [[ ]]
print(row_rank2.shape)
row_rank2 = np.array(an_array[1:2, :])
print(row_rank2, row_rank2.shape)
#We can do the same thing for columns of an array:

print()
col_rank1 = an_array[:, 1]
col_rank2 = an_array[:, 1:2]

print(col_rank1, col_rank1.shape)  # Rank 1
print()
print(col_rank2, col_rank2.shape)  # Rank 2<jupyter_output>[12 22 32] (3,)

[[12]
 [22]
 [32]] (3, 1)<jupyter_text>Sometimes it's useful to use an array of indexes to access or change elements.<jupyter_code># Create a new array
an_array = np.array([[11,12,13], [21,22,23], [31,32,33], [41,42,43]])

print('Original Array:')
print(an_array)
# Create an array of indices
col_indices = np.array([0, 1, 2, 0])
print('\nCol indices picked : ', col_indices)

row_indices = np.arange(4)
print('\nRows indices picked : ', row_indices)
# Examine the pairings of row_indices and col_indices.  These are the elements we'll change next.
for row,col in zip(row_indices,col_indices):
    print(row, ", ",col)
# Select one element from each row
print(row_indices)
print(col_indices)
print('Values in the array at those indices: ',an_array[row_indices, col_indices])
# Change one element from each row using the indices selected
an_array[row_indices, col_indices] += 100000

print('\nChanged Array:')
print(an_array)
# create a 3x2 array
an_array = np.array([[11,12], [21, 22], [31, 32]])
print(an_array)
# create a filter which will be boolean values for whether each element meets this condition
filter = (an_array > 15)
filter<jupyter_output><empty_output><jupyter_text>Notice that the filter is a same size ndarray as an_array which is filled with True for each element whose corresponding element in an_array which is greater than 15 and False for those elements whose value is less than 15.<jupyter_code># we can now select just those elements which meet that criteria
print(an_array[filter])

print(an_array[(an_array > 20) & (an_array < 30)])

newfilter = (an_array < 30)
print(an_array[newfilter])
# For short, we could have just used the approach below without the need for the separate filter array.

an_array[(an_array % 2 == 0)]<jupyter_output><empty_output><jupyter_text>What is particularly useful is that we can actually change elements in the array applying a similar logical filter.  Let's add 100 to all the even values.<jupyter_code>an_array[an_array % 2 == 0] +=100
print(an_array)
ex1 = np.array([11, 12]) # Python assigns the  data type
print(ex1.dtype)
ex2 = np.array([11.0, 12.0]) # Python assigns the  data type
print(ex2.dtype)
ex3 = np.array([11, 21], dtype=np.int64) #You can also tell Python the  data type
print(ex3.dtype)
# you can use this to force floats into integers (using floor function)
ex4 = np.array([11.1,12.7], dtype=np.int64)
print(ex4.dtype)
print()
print(ex4)
# you can use this to force integers into floats if you anticipate
# the values may change to floats later
ex5 = np.array([11, 21], dtype=np.float64)
print(ex5.dtype)
print()
print(ex5)
x = np.array([[111,112],[121,122]], dtype=np.int)
y = np.array([[211.1,212.1],[221.1,222.1]], dtype=np.float64)

print(x)
print()
print(y)
# add
print(x + y)         # The plus sign works
print()
print(np.add(x, y))  # so does the numpy function "add"
# subtract
print(x - y)
print()
print(np.subtract(x, y))
# multiply
print(x * y)
print()
print(np.multiply(x, y))
# divide
print(x / y)
print()
print(np.divide(x, y))
# square root
print(np.sqrt(x))
# exponent (e ** x)
print(np.exp(x))<jupyter_output>[[  1.60948707e+48   4.37503945e+48]
 [  3.54513118e+52   9.63666567e+52]]<jupyter_text>Basic Statistical Operations:<jupyter_code># setup a random 2 x 4 matrix
arr = 10 * np.random.randn(2,5)
print(arr)
# compute the mean for all elements
print(arr.mean())
# compute the means by row
print(arr.mean(axis = 1))
# compute the means by column
print(arr.mean(axis = 0))
# sum all the elements
print(arr.sum())
print(np.median(arr, axis = 0))
print(np.mean(arr, axis = 0))
print(arr.mean(axis = 0 ))
# compute the medians
print(np.median(arr, axis = 1))<jupyter_output>[-6.90211742 -0.81886272]<jupyter_text>Sorting:<jupyter_code># create a 10 element array of randoms
unsorted = np.random.randn(10)

print(unsorted)
# create copy and sort
sorted = np.array(unsorted)
sorted.sort()

print(sorted)
print()
print(unsorted)
# inplace sorting
unsorted.sort() 

print(unsorted)<jupyter_output>[-1.38647752 -1.28321287 -1.2744958  -0.17271585 -0.06194821  0.18559001
  0.27221768  0.82544437  1.08645158  2.27437313]<jupyter_text>Finding Unique elements:<jupyter_code>array = np.array([1,2,1,4,2,1,4,2])

print(np.unique(array))<jupyter_output>[1 2 4]<jupyter_text>Set Operations with np.array data type:<jupyter_code>s1 = np.array(['desk','chair','bulb'])
s2 = np.array(['lamp','bulb','chair'])
print(s1, s2)
print(s1.shape)
print( np.intersect1d(s1, s2) ) 
print( np.union1d(s1, s2) )
print( np.setdiff1d(s1, s2) )# elements in s1 that are not in s2
print( np.in1d(s1, s2) )#which element of s1 is also in s2<jupyter_output>[False  True  True]<jupyter_text>Broadcasting:<jupyter_code>import numpy as np

start = np.zeros((4,3))
print(start)
# create a rank 1 ndarray with 3 values
add_rows = np.array([1, 0, 2])
print(add_rows)
y = start + add_rows  # add to each row of 'start' using broadcasting
print(y)
# create an ndarray which is 4 x 1 to broadcast across columns
add_cols = np.array([[0,1,2,3]])
add_cols = add_cols.T

print(add_cols)
# add to each column of 'start' using broadcasting
y = start + add_cols 
print(y)
# this will just broadcast in both dimensions
add_scalar = np.array([1])  
print(add_scalar)
print(start+add_scalar)
b1 = 1
b1
print(start + b1)<jupyter_output>[[ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]]<jupyter_text>Example from the slides:<jupyter_code># create our 3x4 matrix
arrA = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(arrA)
# create our 4x1 array
arrB = [0,1,0,2]
print(arrB)
# add the two together using broadcasting
print(arrA + arrB)<jupyter_output>[[ 1  3  3  6]
 [ 5  7  7 10]
 [ 9 11 11 14]]<jupyter_text>Dot Product on Matrices and Inner Product on Vectors:<jupyter_code># determine the dot product of two matrices
x2d = np.array([[1,1],[1,1]])
y2d = np.array([[2,2],[2,2]])

print(x2d.dot(y2d))
print()
print(np.dot(x2d, y2d))
# determine the inner product of two vectors
a1d = np.array([9 , 9 ])
b1d = np.array([10, 10])

print(a1d.dot(b1d))
print()
print(np.dot(a1d, b1d))
# dot produce on an array and vector
print(x2d.dot(a1d))
print()
print(np.dot(x2d, a1d))<jupyter_output><empty_output><jupyter_text>Sum:<jupyter_code># sum elements in the array
ex1 = np.array([[11,12],[21,22]])

print(np.sum(ex1))          # add all members
print(np.sum(ex1, axis=0))  # columnwise sum
print(np.sum(ex1, axis=1))  # rowwise sum<jupyter_output><empty_output><jupyter_text>Element-wise Functions: For example, let's compare two arrays values to get the maximum of each.<jupyter_code># random array
x = np.random.randn(8)
x
# another random array
y = np.random.randn(8)
y
# returns element wise maximum between two arrays

np.maximum(x, y)<jupyter_output><empty_output><jupyter_text>Reshaping array:<jupyter_code># grab values from 0 through 19 in an array
arr = np.arange(20)
print(arr)
# reshape to be a 4 x 5 matrix
arr.reshape(4,5)<jupyter_output><empty_output><jupyter_text>Transpose:<jupyter_code># transpose
ex1 = np.array([[11,12],[21,22]])

ex1.T<jupyter_output><empty_output><jupyter_text>"any" or "all" conditionals:<jupyter_code>arr_bools = np.array([ True, False, True, True, False ])
arr_bools.any()
arr_bools.all()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14238837454588069, 'fraction_numerical': 0.06656510019922653, 'mean_word_length': 5.36865671641791, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '314941', 'license': 'MIT', 'n_tokens_mistral': 3613, 'n_tokens_neox': 3306, 'n_words': 918, 'path': 'Numpy/PracticeNumpy.ipynb', 'repo_name': 'codexponent/machinelearningprerequisite101', 'size': '8533'}