<jupyter_start><jupyter_text>Numpy  IntroductionAccording to [Wikipedia](https://en.wikipedia.org/wiki/NumPy):>NumPy (pronounced /ˈnʌmpaɪ/ (NUM-py) or sometimes /ˈnʌmpi/ (NUM-pee)) is a library for the Python programming language, adding support for large, multi-dimensional arrays and matrices, along with a large collection of high-level mathematical functions to operate on these arrays.   Let's get started<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>Datatypes & AttributesNumpy's main datatype is nd-Array(n dimensional Array)<jupyter_code>arr1 = np.array([1,2,3])
arr1
type(arr1)
arr2 = np.array([[1,2,3],[4.,5.,6.5]])
arr2
arr3 = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[10,11,12],[13,14,15],[16,17,18]]])
arr3<jupyter_output><empty_output><jupyter_text>![](Images/AnatomyOfNumpyArray.PNG)<jupyter_code>arr1.shape
arr2.shape
arr3.shape<jupyter_output><empty_output><jupyter_text><jupyter_code>arr1.ndim , arr2.ndim , arr3.ndim
# Number of dimensions<jupyter_output><empty_output><jupyter_text><jupyter_code>arr1.dtype , arr2.dtype , arr3.dtype
# type of data<jupyter_output><empty_output><jupyter_text><jupyter_code>arr1.size , arr2.size , arr3.size
# total number of elements in the array<jupyter_output><empty_output><jupyter_text><jupyter_code>type(arr1) , type(arr2) , type(arr3)<jupyter_output><empty_output><jupyter_text><jupyter_code># create a DataFrame from Numpy array
import pandas as pd
df = pd.DataFrame(arr2)
df<jupyter_output><empty_output><jupyter_text>Creating Arrays<jupyter_code>sample_array = np.array([1,2,3])
sample_array<jupyter_output><empty_output><jupyter_text>Ones()<jupyter_code>ones = np.ones((2,3))
# "shift + tab" inside the paranthesis to see the functions
# description
ones
ones.dtype , type(ones)<jupyter_output><empty_output><jupyter_text>Zeros()<jupyter_code>zeros = np.zeros((2,3))
zeros
range_array = np.arange(0,10,2)
range_array<jupyter_output><empty_output><jupyter_text>random.randint()<jupyter_code>random_array = np.random.randint(0 , 10 , size = (3,5))
random_array
random_array.size , random_array.shape<jupyter_output><empty_output><jupyter_text>random.random()<jupyter_code>np.random.random((5,3))<jupyter_output><empty_output><jupyter_text>random.rand()<jupyter_code>np.random.rand(5,3)<jupyter_output><empty_output><jupyter_text>random.seed()<jupyter_code>np.random.seed(seed = 0 ) # any seed keeps the array the same
new_random_arr = np.random.randint( 10 , size = (5,3) )
new_random_arr
np.random.seed(seed = 0 ) # any seed keeps the array the same
new_random_arr = np.random.randint( 10 , size = (5,3) )
new_random_arr
new_random_arr = np.random.randint( 10 , size = (5,3) )
new_random_arr<jupyter_output><empty_output><jupyter_text>This means that random numbers are not EXACTLY RANDOM. They are psuedo random based on the amount of the seed.  Viewing Matrices & Arrays<jupyter_code># finding unique elements of an array
np.unique(new_random_arr)<jupyter_output><empty_output><jupyter_text><jupyter_code>arr3
arr3[0]
# First two elements of each inner array
arr3[:2,:2,:2]<jupyter_output><empty_output><jupyter_text><jupyter_code>a4 = np.random.randint(10 , size = (2,3,4,5))
a4<jupyter_output><empty_output><jupyter_text>![](Images/ndimArraysAlignment.PNG)<jupyter_code>a4[:,:,:,:1]<jupyter_output><empty_output><jupyter_text>Manipulating and Compariung Arrays  Arithmetic<jupyter_code>arr1
arr1 + np.ones(3) , arr1 - np.ones(3)
arr2 , arr1

arr1*arr2<jupyter_output><empty_output><jupyter_text>> Manipulating array datas in Numpy is called Brodcasting[Broadcasting-TutorialsPoint](https://www.tutorialspoint.com/numpy/numpy_broadcasting.htm)<jupyter_code>## Search : how to reshape numpy array ?
## Search : how to make two numpy arrays compatible ?
arr2/arr1

# Floor division removes the decimal points
arr2//arr1
# All elements will go to the power of two
arr2 ** 2
np.square(9)
# Numpy has all mathematic opeartors and functions :
# Ex : np.exp() , np.log() ,  np.sqrt() , ...<jupyter_output><empty_output><jupyter_text>AggregationMeaning : >the formation of a number of things into a cluster.<jupyter_code>listOfNumbers = [1,2,3,4]
sum(listOfNumbers)
np.sum(listOfNumbers)
# We'd better use Numpy predefined functions and methods on Numpy arrays.
# they are a lot faster.
# created a 1000-element array.
massive_array = np.random.random(1000)
# magic function "timeit" returns the amount of time that each line of code
# takes to execute thoroughly.
%timeit sum(massive_array) # python's sum
%timeit np.sum(massive_array) #Numpy's sum
## this might take some time
# as we can see, Numpy's sum method is about 50 times faster than Python's sum.
np.mean(arr2) # Avg of arr2
np.max(arr2) # max elements of arr2
np.min(arr2) # min elements of arr2
np.var(arr2) ## calculates the Variance<jupyter_output><empty_output><jupyter_text>Standard Deviation & Variance  Varinace (واریانس)<jupyter_code>high_var_Arr = np.array([1,100,200,300,4000,5000])
low_var_Arr = np.array([2,6,4,8,10])
np.var(high_var_Arr) , np.var(low_var_Arr)<jupyter_output><empty_output><jupyter_text>Deviation (انحراف از معیار)<jupyter_code>np.std(high_var_Arr),np.std(low_var_Arr)
import matplotlib.pyplot as plt
plt.hist(high_var_Arr)
plt.show()
plt.hist(low_var_Arr)
plt.show()<jupyter_output><empty_output><jupyter_text>Reshape and Transpose  Reshaping<jupyter_code>arr2

arr2.shape
arr3
arr3.shape
# we can't multiply these two arrays due to different shape. We must reshape them
arr2.reshape(2,3,1).shape
# Now we can multiply arr2 & arr3<jupyter_output><empty_output><jupyter_text>Transpose<jupyter_code>arr2

arr2.T # tranpose operator is an Attribute :\<jupyter_output><empty_output><jupyter_text>Create CSV by Python<jupyter_code>indices = np.array(["Sat","Sun","Mon","Tue","Wed","Thur","Frid"])
peanut_coulmns = np.array(["Almond Butter" , "peanut Butter" , "Creamy Butter"])
salesAmounts = np.random.randint(20,size=(7,3))
weeklySales = pd.DataFrame(salesAmounts,index = indices , columns = peanut_coulmns )
weeklySales
prices = np.array([10,8,12])
penaut_prices = pd.DataFrame(prices.reshape(1,3),index=["Price"],columns = peanut_coulmns)
penaut_prices
totalSales = prices.dot(salesAmounts)
# shapes aren't aligned, let's transpose
totalSales = prices.dot(salesAmounts.T)
totalSales
## This part is incompleted ... Youa re supposed to add the weekly total sales
# to the table as a column.<jupyter_output><empty_output><jupyter_text>Comaprison Operators<jupyter_code>arr1
arr2
## Element wise checks wheter each element in left-hand side is greater than each element in Right-hand-side
arr1>arr2
arr1 >= arr2
arr1 > 5 , arr1 < 5
arr1 == arr2 # you'll get the Same results with : arr2 == arr1<jupyter_output><empty_output><jupyter_text>Sorting Arrays<jupyter_code>random_array = np.random.randint(10,size=(3,5))
random_array
# sorts each row in increasing form.
np.sort(random_array)
# Sorts the values but the indices will be replaced by the real value
np.argsort(random_array)
np.argsort(arr1) , np.sort(arr1) , arr1
# returns the index of matimum value
np.argmax(arr1)
random_array
# Axis zero = horizontally
np.argmax(random_array , axis = 0)
# Axis one = vertically
np.argmax(random_array , axis = 1)<jupyter_output><empty_output><jupyter_text>A Practical Example : Turn Images into arrays See the Image Below : ![](Images/panda.png)<jupyter_code># import a library to read an image
from matplotlib.image import imread as imr
panda_img = imr("Images/panda.png")
print(type(panda_img))
panda_img
panda_img.size , panda_img.shape , panda_img.ndim
# that's pretty big.
# Image Properties : 3500 x 2330
# the numbers in this array are the RGB of the picture.<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12411902897415818, 'fraction_numerical': 0.029626729313495172, 'mean_word_length': 7.257543103448276, 'pattern_counts': {'":': 0, '<': 122, '<?xml version=': 0, '>': 127, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, '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': '30', 'dir': 'jupyter-structured-clean-dedup', 'id': '621405', 'license': 'Apache-2.0', 'n_tokens_mistral': 3008, 'n_tokens_neox': 2864, 'n_words': 608, 'path': '2 - Numpy/Numpy.ipynb', 'repo_name': 'hosseindehghanipour1998/Machine-Learning', 'size': '7662'}