<jupyter_start><jupyter_text>Numpy for Data Science NumPy arrays are a bit like Python lists, but still very much different at the same time a NumPy array is a central data structure of the numpy library. The library’s name is short for “Numeric Python” or “Numerical Python”.<jupyter_code>import numpy as np
np.__version__ # to check the version of numpy installed<jupyter_output><empty_output><jupyter_text>arrays in numpy<jupyter_code>##Normal 1D arrays, np.array
list1 = [1,2,3,4,5]
np.array(list1)
#or
np.array([1,2,3,4,5])
#upcasting
np.array([1,2,3,4,5.0])
#dtypes in np.array
def dtype_array(dtype=None):
    print(np.array([1,2,3,4,5], dtype = dtype))
dtype_array()# default datatype to int
dtype_array(dtype=str)# dtype str
dtype_array(dtype=float)# dtype str
dtype_array(dtype=complex)#complex dtype<jupyter_output>[1 2 3 4 5]
['1' '2' '3' '4' '5']
[1. 2. 3. 4. 5.]
[1.+0.j 2.+0.j 3.+0.j 4.+0.j 5.+0.j]<jupyter_text>arange - > Return an array object satisfying the specified requirementsones -> Return a new array setting values to onezeros - >Return a new array setting values to zeroempty -> Return a new uninitialized arrayfull -> Return a new array of given shape filled with valueones_like -> Return an array of ones with shape and type of inputzeros_like -> Return an array of zeros with shape and type of inputempty_like -> Return an empty array with shape and type of inputfull_like -> Return a new array with shape of input filled with value<jupyter_code>#np.linspace
#This function is similar to arange() function. In this function, instead of step size,
#the number of evenly spaced values between the interval is specified
np.linspace(1,10,50)
##numpy arange
print("array of 3 elements -> ", np.arange(3))
print("array of 3 float elements ->", np.arange(3.0))
print("array of number between 3 and 7(exclude) ->", np.arange(3,7))
print("array of number between 3 and 7(exclude) seperated by 2 ->", np.arange(3,7,2))
#create your own 1D array
def make_array(start_value=0, end_value=10, seperate_by=2):# start and end values default to 0 and 10(excluded)
    print(np.arange(start_value, end_value, seperate_by))
    
make_array(4,80,5)
make_array(12,18,1.5)
#np.ones
print('1D array of ones\n', np.ones(5))
print('1D array of ones. dtype int\n',np.ones((5,), dtype=int))

print('nd array of ones\n', np.ones((5,4)))
print('nd array of ones. dtype int\n',np.ones((5,4), dtype=int))
#np.zeros
print('1D array of zeros\n', np.zeros(6))
print('1D array of zeros. dtype int\n',np.zeros((6,), dtype=int))

print('nd array of zeros\n', np.zeros((2,3)))
print('nd array of zeros. dtype int \n',np.zeros((6,4), dtype=int))
#np.empty
#Return a new array of given shape and type, without initializing entries.
print('1d empty array\n', np.empty(2)) # one dimesional
print('nd empty array\n ',np.empty([2, 2], dtype=int)) # multi dimesional
# np.full
#Return a new array of given shape and type, filled with fill_value.
print('one dimesional full array \n ', np.full(5,np.inf)) # array filled with np.inf
print('multi -dimensional full array \n', np.full((2, 2), 10)) #array filled with 10<jupyter_output>one dimesional full array 
  [inf inf inf inf inf]
multi -dimensional full array 
 [[10 10]
 [10 10]]<jupyter_text>nd arrays - 2d, 3d...<jupyter_code>print(np.array([[1,2,3],[4,5,6]])) #normal 2d array
print(np.ones((2,3), dtype = int)) # ones array of shape (2,3)
print(np.zeros((2,3), dtype = int)) # eros array of shape (2,3)
#converting scaler 1d array into 2d array using reshape mathod
np.arange(2,10,2).reshape(2,2)
# to get shape and dtype of array
arr = np.arange(2,10,2).reshape(2,2)
print('arr shape ->', arr.shape)
print('arr dtype ->', arr.dtype)
# Create an array with random values
np.random.random((2,2))<jupyter_output><empty_output><jupyter_text>Some special arrays<jupyter_code>#Return a 2-D array with ones on the diagonal and zeros elsewhere.
#k - int, optional
#Index of the diagonal: 0 (the default) refers to the main diagonal, 
#a positive value refers to an upper diagonal, and a negative value to a lower diagonal.
np.eye(5,dtype=int, k=1) 
#Return the identity array.
#The identity array is a square array with ones on the main diagonal.
np.identity(3)<jupyter_output><empty_output><jupyter_text>Array operations  with scalers<jupyter_code>a = np.array(([1, 2, 3, 4],[4,5,6,7]))
print('addition->\n', a + 1) #addition of scaler value into array
print('multiplication->\n',a*2) #multiplication of scaler
print('subtraction->\n', a - 1) #subtraction of scaler value into array
print('division->\n',a/2) #division of scaler
print('combined->\n', (a+2)-1/3+4*2) #combined arithematic operations with scalers
#division by zero
a/0 # it gives warning but not error, we get inf in as array values
#arithematic operation on ones array
b = np.ones(4) + 1
a-b
#operation on arange
j = np.arange(5)
2**(j + 1) - j<jupyter_output><empty_output><jupyter_text>Element-wise operations<jupyter_code>#element wise comparision
a = np.array([1, 2, 3, 4])
b = np.array([4, 2, 2, 4])
print('equals', a==b)
print('greater',a>b)
# Array-wise comparisons:
a = np.array([1, 2, 3, 4])
b = np.array([4, 2, 2, 4])
c = np.array([4, 2, 2, 4])
print(np.array_equal(a,b))
print(np.array_equal(c,b))
#Array multiplication is not matrix multiplication
o = np.ones((3, 3))
o*o   # NOT matrix multiplication! this is array multiplication
#this is matrix multiplication
o.dot(o)
#Other operations
#Logical operations:
a = np.array([1, 0, 1, 0], dtype=bool)
b = np.array([1, 0, 1, 0], dtype=bool)
print(np.logical_or(a, b)) #logical or
print(np.logical_and(a, b)) #logical and
#Transcendental functions:
a = np.arange(8)
print(np.sin(a))
print(np.log(a))
print(np.exp(a))
#Shape mismatches. errors
a = np.arange(5)
a + np.array([1, 2])<jupyter_output><empty_output><jupyter_text>Indexing and slicing in numpy arrays Contents of ndarray object can be accessedand modified by indexing or slicing, just like Python's in-built container objects.<jupyter_code>index_arr = np.array([1, 2, 3, 4])
#array index starts with 0
print(index_arr)
print(index_arr[0]) # 1 
print(index_arr[2]) # 3<jupyter_output>[1 2 3 4]
1
3<jupyter_text>Indexing in 2 dimensions<jupyter_code>array_2d = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
# to fetch the item from 3rd row and 2nd column
print(array_2d[2, 1]) # 8<jupyter_output>8<jupyter_text>Picking a row or column of a 2d array<jupyter_code>print('first row', array_2d[0]) # to fetch the first row
print('second column', array_2d[:,1]) # to fetch the second column<jupyter_output>first row [1 2 3]
second column [2 5 8]<jupyter_text>indexing in 3 dimesions<jupyter_code>#3d arrays
array_3d = np.array([[[10, 11, 12], [13, 14, 15], [16, 17, 18]],
               [[20, 21, 22], [23, 24, 25], [26, 27, 28]],
               [[30, 31, 32], [33, 34, 35], [36, 37, 38]]])
# fetch 3rd matrix , 1st row, 2nd element
print(array_3d[2, 0, 1]) # 31
# fetch first matrix, all rows, 1st column
print(array_3d[0, :, 1]) # [11 14 17]<jupyter_output>[11 14 17]<jupyter_text>Picking a matrix in a 3D array<jupyter_code>#If we only specify the i index, numpy will return the corresponding matrix.
print('fetch 3rd metrix :\n',array_3d[2])
#step by step
print('use above matrix to open further: \n', array_3d[2][:,:2])
#fetching 2nd row and 3rd column value from all matrice
print(array_3d[:, 1, 2]) # [15, 25, 35]<jupyter_output>[15 25 35]<jupyter_text>Slicing 1D numpy arrays<jupyter_code>#slicing in 1d array
slice_arr = np.array([1, 2, 3, 4, 5])
sliced_arr = slice_arr[1:4]
print(sliced_arr)
sliced_arr2 =  slice_arr[2]
print(sliced_arr2)
print(sliced_arr2.dtype)
print(type(sliced_arr2))<jupyter_output>3
int64
<class 'numpy.int64'><jupyter_text>Slicing a 2D array<jupyter_code>#You can slice a 2D array in both axes to obtain a rectangular subset of the original array
slice_arr_2d = np.array([[10, 11, 12, 13, 14],
               [15, 16, 17, 18, 19],
               [20, 21, 22, 23, 24],
               [25, 26, 27, 28, 29]])

print(slice_arr_2d[1:,2:4])<jupyter_output>[[17 18]
 [22 23]
 [27 28]]<jupyter_text>Slicing a 3D array<jupyter_code>#You can slice a 3D array in all 3 axes to obtain a cuboid subset of the original array
slice_arr_3d = np.array([[[10, 11, 12], [13, 14, 15], [16, 17, 18]],
               [[20, 21, 22], [23, 24, 25], [26, 27, 28]],
               [[30, 31, 32], [33, 34, 35], [36, 37, 38]]])
print(slice_arr_3d[:2,1:,:2])<jupyter_output>[[[13 14]
  [16 17]]

 [[23 24]
  [26 27]]]
{'fraction_non_alphanumeric': 0.14799054373522458, 'fraction_numerical': 0.06182033096926714, 'mean_word_length': 4.896167247386759, 'pattern_counts': {'":': 0, '<': 52, '<?xml version=': 0, '>': 73, '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': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '32991', 'license': 'MIT', 'n_tokens_mistral': 3496, 'n_tokens_neox': 3155, 'n_words': 1022, 'path': 'notebooks/1.numpy.ipynb', 'repo_name': 'suyash2796/data-notebook', 'size': '8460'}