Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
384 views

Python W3school

This document provides examples of built-in data types in Python like strings, numbers, lists, tuples, dictionaries and sets. It demonstrates how to define, initialize and perform common operations on each of these data types. For lists, some operations shown include accessing elements, slicing, changing elements, inserting, removing, sorting and copying lists. For tuples, examples cover unpacking, joining and changing values. Dictionary operations demonstrated include accessing, updating, removing items and looping through dictionaries.

Uploaded by

tarek hassan
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
384 views

Python W3school

This document provides examples of built-in data types in Python like strings, numbers, lists, tuples, dictionaries and sets. It demonstrates how to define, initialize and perform common operations on each of these data types. For lists, some operations shown include accessing elements, slicing, changing elements, inserting, removing, sorting and copying lists. For tuples, examples cover unpacking, joining and changing values. Dictionary operations demonstrated include accessing, updating, removing items and looping through dictionaries.

Uploaded by

tarek hassan
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 44

Many values to multiple variables One value to multiple variables

x, y, z = "Orange","Banana",123 x = y = z = "Orange"

Built-in Data types


Text Type : str
Unpack a collection
Numeric Types : int, float, complex
fruits = ["apple","banana","cherry"]
Sequence Types :list, tuple, range
x, y, z = fruits
Mapping Types : dict
print(x) # apple
Set Types : set, frozenset
print(y) # banana
Boolean Types : bool
print(z) # cherry
Binary Types : bytes, bytearray, memoryview
None Type : NoneType

String format: format() method


It takes unlimited number of argument and are placed into the respective placeholders.
quantity = 3
item_no = 567
price = 49.95
my_order = "I want {} pieces of item {} for {} dollars"
print(my_order.format(quantity,item_no,price))
You can use index numbers {0} to be sure the arguments are place in the correct placeholders
my_order = "I want to pay {2} dollars for {0} pieces of item {1}."
print(my_order.format(quantity,item_no,price))

List operation
Change a range of item values
L = ["apple","banana","cherry","orange","kiwi"]
# ['apple', 'blackcurrent', 'watermelon', 'orange', 'kiwi']
L[1:3] = ["blackcurrent","watermelon"]
Insert item
L.insert(1,"melon") # ['apple', 'melon', 'blackcurrent', 'watermelon', 'orange', 'kiwi']
Extend List
L2 = ["mango","pineapple","papaya"]
# ['apple', 'banana', 'cherry', 'orange', 'kiwi', 'mango', 'pineapple', 'papaya']
L.extend(L2)
You can add any iterable object(tuples,sets,dictionaries)
T = ("kiwi","orange")
# ['apple', 'banana', 'cherry', 'orange', 'kiwi', 'mango', 'pineapple', 'papaya', 'kiwi', 'orange']
L.extend(T)
Remove specified item
# ['apple', 'cherry', 'orange', 'kiwi', 'mango', 'pineapple', 'papaya', 'kiwi', 'orange']
L.remove("banana")
Remove specified index
# ['apple', 'orange', 'kiwi', 'mango', 'pineapple', 'papaya', 'kiwi', 'orange']
L.pop(1) is equal to del L[1]
Clear the list
L.clear() # []
Sort Method
L.sort() # Ascending
L.sort(reverse = True) # Descending

By using the keyword argument key=function, the function will return a number that will be used to sort the
list (the lowest number first. Example, sort the list based on how close the number is to 50.
def my_function(n):
return abs(n-50)
L = [100,50,65,82,23]
# [50, 65, 23, 82, 100]
L.sort(key = my_function)
Reverse order
What if you want to reverse the order of a list, regardless of the alphabet?
L = ["banana","orange","kiwi","cherry"]
# ['cherry', 'kiwi', 'orange', 'banana']
L.reverse()
Copy List
You can not copy a list simply by typing List2 = List1, because: List2 will only be a reference to List1, and
changes made in List1 will automatically also be made in List2.
We can solve it by choosing one from two way:-
# First Way
List1 = ["apple","banana","cherry"]
List2 = List1.copy()
# Second Way
List2 = list(List1)

Tuple Operation Using Asterisk *


Create tuple with one item FRUITS = ("apple","banana","cherry","mango","pineap
T = ("apple",) ple")
The tuple() constructor (green,yellow,*red) = FRUITS
T = tuple(("apple","orange")) print(green) # green
Change tuple value trick print(yellow) # banana
You can convert the tuple into a list, change the print(red) # ['cherry', 'mango', 'pineapple']
list and convert the list back into a tuple.
X = ("apple","banana","cherry") ‫اذا تمت إضافة عالمة النجمة الى اسم متغير آخر غير المتغير‬
Y = list(X) ‫األخير فستقوم بايثون بتعيين قيم للمتغير حتى يتطابق عدد القيم‬
Y[1] = "kiwi" .‫المتبقية مع عدد المتغيرات المتبقية‬
X = tuple(Y) Join two tuples
Unpacking a tuple T1 = ("tarek",)
FRUITS =("apple","banana","cherry") T2 = ("hassan",)
(green,yellow,red) = FRUITS T3 = T1 + T2
Set Operation
Join two sets
The set() constructor
# first way
# {'apple', 'orange', 'kiwi'}
S3 = S1.union(S2)
S1 = set(("apple","orange","kiwi"))
# second way
Once a set is created, you can not change its
S1.update(S2)
items, but you can add new items.
Join two sets
S1.add("cherry")
# first way
To add items from another set or ant iterable
S3 = S1.union(S2)
objects
# second way
S2 = {"banana","mango"}
S1.update(S2)
S1.update(S2)
Keep only the Duplicates
L1 = ["pineapple","papaya"]
Keep the items that exist in both set X and set Y.
S1.update(L1)
X = {"apple","banana","cherry"}
Remove set item
Y = {"google","microsoft","apple"}
# first way
X.intersection_update(Y)
#if the item to remove does not exist, remove()
The intersection() method will return a new set
will raise an error
Z = X.intersection(Y)
S1.remove("banana")
print(X) # {'apple'}
# second way
Keep All, but Not the Duplicates
# if the item to remove does not exist, discard()
X.symmetric_difference_update(Y)
will not raise an error
Z = X.symmetric_difference(Y)
S1.discard("apple")
Dictionary Operation
Short hand if if a > b: print("a is greater than b")
Dictionary accessing item
Short hand if……else
d = { "brand": "ford", "model": "Mustag",
print("A") if a > b else print("B")
"year": 1964 }
You can also have multiple else statement on the same line
# first way with raise error if key not exist print("A") if a > b else print("=") if a == b else print("B")
car_model = d["model"]
# second way, No error raise
Arbitrary Arguments *args
car_model = d.get("model") If you don’t know how many arguments that will be
Get Keys X = d.keys() passed into your function, add *args before the parameter
Get Values X = d.values() name in the function definition.This way the function will

Get Items receive a tuple of arguments and can access the items

X = d.items # will return each item in a dictionar accordingly.

y, as tuples in a list def my_func(*kids):


print("the youngest child is " + kids[2])
Update Dictionary
# the youngest child is Linus
X.update({"year":2020})
my_func("Emil","Tobias","Linus")
Removing Items X.pop("model")
keyword Arguments
Loop through a Dictionary
def my_func(child3,child2,child1):
# print all key names, one by one
print("the youngest child is " + child3)
for k in x: print(k) # the youngest child is Linus
# print all values, one by one -two ways my_func(child1 = "Emil",child2 = "Tobias", child3 = "Linus")
# first way Arbitrary keyword Arguments, **kwargs

for k in X: print(X[k]) if you don’t know how many keyword arguments that will

# second way be passed into your function, add two ** before the

for v in X.values(): print(v) parameter name in the function definition. This way the
function will receive a dictionary of arguments, and can
# print key with value
access the items accordingly
for k,v in X.items(): print(k,v)
def my_func(**kid):
copy a Dictionary
print("His Last name is " + kid["lname"])
y = d.copy() # OR
# the youngest child is Linus
y = dict(d)
my_func(fname = "Tobias",lname = "Refsnes")
Python Lambda
A lambda function is a small anonymous function. A lambda function can take any number of arguments,
but can only have one expression. lambda arguments : expression
x = lambda a : a + 10 print(x(5)) # 15
Lambda functions can take any number of arguments:
x = lambda a, b : a * b print(x(5, 6))
Why Use Lambda Functions?
The power of lambda is better shown when you use them as an anonymous function inside another
function. Use lambda functions when an anonymous function is required for a short period of time. Say
you have a function definition that takes one argument, and that argument will be multiplied with an
unknown number: Use that function definition to make a function that always doubles the number you
send in:
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
Or, use the same function definition to make a function that always triples the number you send in:
def myfunc(n):
return lambda a : a * n
mytripler = myfunc(3)
print(mytripler(11))
Or, use the same function definition to make both functions, in the same program:
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
mytripler = myfunc(3)
print(mydoubler(11))
print(mytripler(11))
Create a Class class Person:
def __init__(self, name, age):
self.name = name
To create a class, use the keyword class:
self.age = age
class MyClass:
def myfunc(self):
x=5
print("Hello my name is " + self.name)
Create Object
p1 = Person("John", 36)
Now we can use the class named MyClass to
p1.myfunc()
create objects:
It does not have to be named self , you can call it
p1 = MyClass() print(p1.x)
whatever you like, but it has to be the first parameter
The __init__() Function of any function in the class:
To understand the meaning of classes we have Use the words mysillyobject and abc instead of self:
to understand the built-in __init__() function. All class Person:
classes have a function called __init__(), which is def __init__(mysillyobject, name, age):
always executed when the class is being
mysillyobject.name = name
initiated. Use the __init__() function to assign
values to object properties, or other operations mysillyobject.age = age
that are necessary to do when the object is def myfunc(abc):
being created:
print("Hello my name is " + abc.name)
class Person:
p1 = Person("John", 36)
def __init__(self, name, age):
p1.myfunc()
self.name = name
Modify Object Properties
self.age = age
You can modify properties on objects like this:
p1 = Person("John", 36)
p1.age = 40
print(p1.name)
Delete Object Properties
The self Parameter
You can delete properties on objects by using
The self parameter is a reference to the current
instance of the class, and is used to access the del keyword:
variables that belongs to the class. del p1.age
Object Methods
Delete Objects
Methods in objects are functions that belong to
You can delete objects by using the del keyword:
the object.
del p1
Python Inheritance Now the Student class has the same properties and
Inheritance allows us to define a class that methods as the Person class.
inherits all the methods and properties from x = Student("Mike", "Olsen")
x.printname()
another class.
Add the __init__() Function
Parent class is the class being inherited from,
So far we have created a child class that inherits the
also called base class.
properties and methods from its parent.
Child class is the class that inherits from
We want to add the __init__() function to the child
another class, also called derived class.
class (instead of the pass keyword).
class Student(Person):
Create a Parent Class
def __init__(self, fname, lname):
class Person:
#add properties etc.
def __init__(self, fname, lname):
When you add the __init__() function, the child class
self.firstname = fname
will no longer inherit the parent's __init__() function.
self.lastname = lname
def printname(self):
Note:
print(self.firstname, self.lastname)
The child's __init__() function overrides the
#Use the Person class to create an object, and
inheritance of the parent's __init__() function.
then execute the printname method:
To keep the inheritance of the
x = Person("John", "Doe")
parent's __init__() function, add a call to the
x.printname()
parent's __init__() function:
class Student(Person):
Create a Child Class
def __init__(self, fname, lname):
To create a class that inherits the functionality
Person.__init__(self, fname, lname)
from another class, send the parent class as a
Now we have successfully added the __init__()
parameter when creating the child class:
function, and kept the inheritance of the parent class,
class Student(Person):
and we are ready to add functionality in
pass
the __init__() function.
Use the super() Function To do so, add another parameter in the __init__()
Python also has a super() function that will function:
make the child class inherit all the methods and class Student(Person):
properties from its parent: def __init__(self, fname, lname, year):
class Student(Person): super().__init__(fname, lname)
def __init__(self, fname, lname):
self.graduationyear = year
super().__init__(fname, lname)
x = Student("Mike", "Olsen", 2019)
By using the super() function, you do not have
to use the name of the parent element, it will
Add Methods
automatically inherit the methods and
class Student(Person):
properties from its parent.
def __init__(self, fname, lname, year):
super().__init__(fname, lname)
Add Properties
self.graduationyear = year
class Student(Person):
def welcome(self):
def __init__(self, fname, lname):
print("Welcome", self.firstname, self.lastname, "to
super().__init__(fname, lname)
the class of", self.graduationyear)
self.graduationyear = 2019
If you add a method in the child class with the same
In the example below, the year 2019 should be
name as a function in the parent class, the inheritance
a variable, and passed into the Student class
of the parent method will be overridden.
when creating student objects.

Python Iterators
An iterator is an object that contains a countable number of values.
An iterator is an object that can be iterated upon, meaning that you can traverse through all the values.
Technically, in Python, an iterator is an object which implements the iterator protocol, which consist of the
methods __iter__() and __next__().

Iterator vs Iterable Create an Iterator


Lists, tuples, dictionaries, and sets are all To create an object/class as an iterator you have to
iterable objects. They are implement the methods __iter__() and __next__() to
iterable containers which you can get an your object. As you have learned, all classes have a
iterator from. All these objects have function called __init__(), which allows you to do some
a iter() method which is used to get an iterator:
mytuple = ("apple", "banana", "cherry")
initializing when the object is being created.
myit = iter(mytuple)
The __iter__() method acts similar, you can do
print(next(myit))
operations (initializing etc.), but must always return
print(next(myit))
the iterator object itself.
Even strings are iterable objects, and can return
The __next__() method also allows you to do
an iterator:
operations, and must return the next item in the
mystr = "banana"
sequence.
myit = iter(mystr)
class MyNumbers:
print(next(myit))
def __iter__(self):
print(next(myit))
self.a = 1
print(next(myit))
return self
Looping Through an Iterator
def __next__(self):
We can also use a for loop to iterate through an
x = self.a
iterable object:
self.a += 1
mytuple = ("apple", "banana", "cherry")
return x
for x in mytuple:
myclass = MyNumbers()
print(x)
myiter = iter(myclass)
mystr = "banana"
print(next(myiter))
for x in mystr:
print(next(myiter))
print(x)
print(next(myiter))
The for loop actually creates an iterator object
print(next(myiter))
and executes the next() method for each loop.
print(next(myiter))

StopIteration def __next__(self):


The example above would continue forever if if self.a <= 20:
you had enough next() statements, or if it was x = self.a
used in a for loop. self.a += 1
To prevent the iteration to go on forever, we return x
can use the StopIteration statement. else:
In the __next__() method, we can add a raise StopIteration
terminating condition to raise an error if the
iteration is done a specified number of times: myclass = MyNumbers()
class MyNumbers: myiter = iter(myclass)
def __iter__(self):
self.a = 1 for x in myiter:
return self print(x)
Naming Variables
If you operate with the same variable name inside and outside of a function, Python will treat them as two
separate variables, one available in the global scope (outside the function) and one available in the local
scope (inside the function):
x = 300
def myfunc():
x = 200
print(x)
myfunc()
print(x)

Python Dates Creating Date Objects


A date in Python is not a data type of its own, To create a date, we can use the datetime() class
but we can import a module named datetime to (constructor) of the datetime module.
work with dates as date objects. The datetime() class requires three parameters to
import datetime create a date: year, month, day.
x = datetime.datetime.now() import datetime
print(x) x = datetime.datetime(2020, 5, 17)
print(x)
The datetime() class also takes parameters for time
and timezone (hour, minute, second, microsecond,
tzone), but they are optional, and has a default value
of 0, (None for timezone).
Date Output
The strftime() Method
When we execute the code from the example
The datetime object has a method for formatting date
above the result will be:
objects into readable strings.
2022-06-07 05:19:30.746825
The method is called strftime(), and takes one
The date contains year, month, day, hour,
parameter, format, to specify the format of the
minute, second, and microsecond.
returned string:
The datetime module has many methods to
import datetime
return information about the date object.
x = datetime.datetime(2018, 6, 1)
import datetime
print(x.strftime("%B")) # June
x = datetime.datetime.now()
print(x.year) # 2022
print(x.strftime("%A")) # Tuesday

Python JSON import json


JSON is a syntax for storing and exchanging print(json.dumps({"name": "John", "age": 30}))
data. JSON is text, written with JavaScript object print(json.dumps(["apple", "bananas"]))
notation. Python has a built-in package print(json.dumps(("apple", "bananas")))
called json, which can be used to work with print(json.dumps("hello"))
JSON data. import json print(json.dumps(42))
Parse JSON - Convert from JSON to Python print(json.dumps(31.76))
If you have a JSON string, you can parse it by print(json.dumps(True))
print(json.dumps(False))
using the json.loads() method.
print(json.dumps(None))
The result will be a Python dictionary.
Format the Result
import json
The example above prints a JSON string, but it is not
# some JSON:
very easy to read, with no indentations and line
x = '{ "name":"John", "age":30, "city":"New York"}'
# parse x: breaks. The json.dumps() method has parameters to

y = json.loads(x) make it easier to read the result:

# the result is a Python dictionary: Use the indent parameter to define the numbers of
print(y["age"]) indents: json.dumps(x, indent=4)
Convert from Python to JSON You can also define the separators, default value is (",
If you have a Python object, you can convert it ", ": "), which means using a comma and a space to
into a JSON string by using separate each object, and a colon and a space to
the json.dumps() method. separate keys from values: Use
import json the separators parameter to change the default
# a Python object (dict):
separator:
x = { "name": "John", "age": 30, "city": "New York"}
json.dumps(x, indent=4, separators=(". ", " = "))
# convert into JSON:
Order the Result
y = json.dumps(x)
The json.dumps() method has parameters to order
# the result is a JSON string:
the keys in the result: Use the sort_keys parameter to
print(y)
specify if the result should be sorted or not:
json.dumps(x, indent=4, sort_keys=True)
RegEx Module Metacharacters
Python has a built-in package called re, which Metacharacters are characters with a special meaning:
can be used to work with Regular Expressions.
Charact Description Example
Import the re module:
er
import re
[] A set of characters "[a-m]"
Example
Search the string to see if it starts with "The" \ Signals a special "\d"
and ends with "Spain" sequence (can also be
import re
txt = "The rain in Spain"
used to escape special
x = re.search("^The.*Spain$", txt)
characters)
RegEx Functions
The re module offers a set of functions that . Any character (except "he..o"
allows us to search a string for a match: newline character)

Functio Description ^ Starts with "^hello"


n
$ Ends with "planet$"
findall Returns a list containing all
* Zero or more occurrences "he.*o"
matches

+ One or more occurrences "he.+o"


search Returns a Match object if there is
a match anywhere in the string ? Zero or one occurrences "he.?o"

split Returns a list where the string has {} Exactly the specified "he.{2}o"
been split at each match number of occurrences

sub Replaces one or many matches | Either or "falls|


with a string stays"

() Capture and group

Special Sequences Characte Description Example


A special sequence is a \ followed by one of the r
characters in the list below, and has a special
\B Returns a match where the r"\Bain"
meaning:
specified characters are r"ain\B"
Characte Description Example present, but NOT at the
r beginning (or at the end)
of a word
\A Returns a match if the "\AThe"
(the "r" in the beginning is
specified characters are at
making sure that the
the beginning of the string
string is being treated as a
"raw string")
\b Returns a match where the r"\bain"
\d Returns a match where the "\d"
specified characters are at r"ain\b"
string contains digits
the beginning or at the
(numbers from 0-9)
end of a word
(the "r" in the beginning is \D Returns a match where the "\D"
making sure that the string DOES NOT contain
string is being treated as a digits
"raw string")
\w Returns a match where the "\w"
\s Returns a match where the "\s" string contains any word
string contains a white characters (characters
space character from a to Z, digits from 0-
9, and the underscore _
\S Returns a match where the "\S"
character)
string DOES NOT contain
a white space character \W Returns a match where the "\W"
string DOES NOT contain
\Z Returns a match if the "Spain\Z"
any word characters
specified characters are at
the end of the string

Sets
A set is a set of characters inside a pair of square brackets [] with a special meaning:

Set Description

[arn] Returns a match where one of the specified characters (a, r, or n) are present

[a-n] Returns a match for any lower case character, alphabetically between a and n

[^arn] Returns a match for any character EXCEPT a, r, and n

[0123] Returns a match where any of the specified digits (0, 1, 2, or 3) are present

[0-9] Returns a match for any digit between 0 and 9


[0-5][0-9] Returns a match for any two-digit numbers from 00 and 59

[a-zA-Z] Returns a match for any character alphabetically between a and z, lower case OR
upper case

[+] In sets, +, *, ., |, (), $,{} has no special meaning, so [+] means: return a match for
any + character in the string

The list contains the matches in the order they are


The findall() Function
found.
The findall() function returns a list containing all
If no matches are found, an empty list is returned:
matches.
Return an empty list if no match was found:
Print a list of all matches:
import re
import re

txt = "The rain in Spain"


txt = "The rain in Spain"
x = re.findall("Portugal", txt)
x = re.findall("ai", txt)
print(x)
print(x)

The search() Function The sub() Function


The search() function searches the string for a The sub() function replaces the matches with the text
match, and returns a Match object if there is a of your choice:
match. If there is more than one match, only the Replace every white-space character with the number 9:
first occurrence of the match will be returned: import re
Search for the first white-space character in the txt = "The rain in Spain"
string: x = re.sub("\s", "9", txt)
import re print(x)
txt = "The rain in Spain" You can control the number of replacements by
x = re.search("\s", txt) specifying the count parameter:
print("The first white-space character is located Replace the first 2 occurrences:
in position:", x.start()) import re
If no matches are found, the value None is txt = "The rain in Spain"
returned: x = re.sub("\s", "9", txt, 2)
print(x)
Match Object
Make a search that returns no match: A Match Object is an object containing information
import re about the search and the result.
txt = "The rain in Spain" Note: If there is no match, the value None will be
x = re.search("Portugal", txt) returned, instead of the Match Object.
print(x) import re
The split() Function txt = "The rain in Spain"
The split() function returns a list where the x = re.search("ai", txt)
string has been split at each match: print(x) #this will print an object
Split at each white-space character: The Match object has properties and methods used
import re to retrieve information about the search, and the
txt = "The rain in Spain" result:
x = re.split("\s", txt) .span() returns a tuple containing the start-, and end
print(x) positions of the match.
You can control the number of occurrences by .string returns the string passed into the function
specifying the maxsplit parameter: .group() returns the part of the string where there was
Split the string only at the first occurrence: a match
import re
txt = "The rain in Spain"
x = re.split("\s", txt, 1)
print(x)

Print the position (start- and end-position) of Print the part of the string where there was a match.
the first match occurrence. The regular expression looks for any words that starts
The regular expression looks for any words that with an upper case "S":
starts with an upper case "S": import re
import re txt = "The rain in Spain"
txt = "The rain in Spain" x = re.search(r"\bS\w+", txt)
x = re.search(r"\bS\w+", txt) print(x.group())
print(x.span()) Note: If there is no match, the value None will be
Print the string passed into the function: returned, instead of the Match Object.
import re
txt = "The rain in Spain"
x = re.search(r"\bS\w+", txt)
print(x.string)
Python Try Except try:
The try block lets you test a block of code for print(x)
errors. except:
The except block lets you handle the error. print("An exception occurred")
The else block lets you execute code when Many Exceptions
there is no error. You can define as many exception blocks as you want,
The finally block lets you execute code, e.g. if you want to execute a special block of code for
regardless of the result of the try- and except a special kind of error:
blocks. Print one message if the try block raises
Exception Handling a NameError and another for other errors:
When an error occurs, or exception as we call it, try:
Python will normally stop and generate an error print(x)
message. These exceptions can be handled except NameError:
using the try statement: print("Variable x is not defined")
The try block will generate an exception, except:
because x is not defined: print("Something else went wrong")
Else This can be useful to close objects and clean up
You can use the else keyword to define a block resources:
of code to be executed if no errors were raised: Try to open and write to a file that is not writable:
In this example, the try block does not generate try:
any error: f = open("demofile.txt")
try: try:
print("Hello") f.write("Lorum Ipsum")
except: except:
print("Something went wrong") print("Something went wrong when writing to the
else: file")
print("Nothing went wrong") finally:
Finally f.close()
The finally block, if specified, will be executed except:
regardless if the try block raises an error or not.
try:
print("Something went wrong when opening the
print(x)
file")
except:
The program can continue, without leaving the file
print("Something went wrong")
object open.
finally:
print("The 'try except' is finished")
Raise an exception
As a Python developer you can choose to throw The raise keyword is used to raise an exception.

an exception if a condition occurs. To throw (or You can define what kind of error to raise, and the

raise) an exception, use the raise keyword. text to print to the user.

Raise an error and stop the program if x is Raise a TypeError if x is not an integer:

lower than 0: x = "hello"

x = -1 if not type(x) is int:

if x < 0: raise TypeError("Only integers are allowed")


raise Exception("Sorry, no numbers below zero")

What is NumPy?
It also has functions for working in domain of Dimensions in Arrays
linear algebra, fourier transform, and matrices. A dimension in arrays is one level of array depth
NumPy stands for Numerical Python. (nested arrays).
Why Use NumPy? 0-D Arrays
In Python we have lists that serve the purpose 0-D arrays, or Scalars, are the elements in an array.
of arrays, but they are slow to process. Each value in an array is a 0-D array.
NumPy aims to provide an array object that is import numpy as np
up to 50x faster than traditional Python lists. arr = np.array(42)
NumPy arrays are stored at one continuous
print(arr)
place in memory unlike lists.
The array object in NumPy is called ndarray, it 1-D Arrays
provides a lot of supporting functions that
An array that has 0-D arrays as its elements is called
make working with ndarray very easy.
uni-dimensional or 1-D array.
Installation of NumPy These are the most common and basic arrays.
!pip install numpy
import numpy as np
NumPy as np arr = np.array([1, 2, 3, 4, 5])
print(arr)
NumPy is usually imported under the np alias.
import numpy as np
2-D Arrays
Checking NumPy Version
An array that has 1-D arrays as its elements is called a
The version string is stored under
2-D array.
__version__ attribute.
import numpy as np These are often used to represent matrix or 2nd order
print(np.__version__) tensors.
NumPy has a whole sub module dedicated
Create a NumPy ndarray Object towards matrix operations called numpy.mat
NumPy is used to work with arrays. The array import numpy as np
object in NumPy is called ndarray. arr = np.array([[1, 2, 3], [4, 5, 6]])
We can create a NumPy ndarray object by using print(arr)
the array() function.
To create an ndarray, we can pass a list, tuple or 3-D arrays
any array-like object into the array() method,
An array that has 2-D arrays (matrices) as its elements
and it will be converted into an ndarray:
is called 3-D array.
import numpy as np
These are often used to represent a 3rd order tensor.
arr = np.array([1, 2, 3, 4, 5])
print(arr)
import numpy as np
print(type(arr)) arr = np.array([[[1, 2, 3], [4, 5, 6]],
import numpy as np [[1, 2, 3], [4, 5, 6]]])
arr = np.array((1, 2, 3, 4, 5)) print(arr)
print(arr)
Check Number of Dimensions? Access 2-D Arrays
NumPy Arrays provides the ndim attribute that To access elements from 2-D arrays we can use
returns an integer that tells us how many comma separated integers representing the
dimensions the array have. dimension and the index of the element.
import numpy as np Think of 2-D arrays like a table with rows and
a = np.array(42) columns, where the row represents the dimension
b = np.array([1, 2, 3, 4, 5])
c = np.array([[1, 2, 3], [4, 5, 6]])
and the index represents the column.
import numpy as np
d = np.array([[[1, 2, 3], [4, 5, 6]],
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
[[1, 2, 3], [4, 5, 6]]])
print('2nd element on 1st row: ', arr[0, 1])
print(a.ndim)
print(b.ndim) Access 3-D Arrays
print(c.ndim)
To access elements from 3-D arrays we can use
print(d.ndim)
comma separated integers representing the
Higher Dimensional Arrays dimensions and the index of the element.
import numpy as np
An array can have any number of dimensions. arr = np.array([[[1, 2, 3], [4, 5, 6]],
When the array is created, you can define the [[7, 8, 9], [10, 11, 12]]])
print(arr[0, 1, 2])
number of dimensions by using
the ndmin argument. Example Explained
import numpy as np arr[0, 1, 2] prints the value 6.
arr = np.array([1, 2, 3, 4], ndmin=5) And this is why:
The first number represents the first dimension, which
print(arr)
contains two arrays:
print('number of dimensions :',
arr.ndim) [[1, 2, 3], [4, 5, 6]]
and:
In this array the innermost dimension (5th dim) [[7, 8, 9], [10, 11, 12]]
has 4 elements, the 4th dim has 1 element that Since we selected 0, we are left with the first array:
is the vector, the 3rd dim has 1 element that is [[1, 2, 3], [4, 5, 6]]
the matrix with the vector, the 2nd dim has 1 The second number represents the second
element that is 3D array and 1st dim has 1 dimension, which also contains two arrays:
element that is a 4D array. [1, 2, 3]
and:
Access Array Elements [4, 5, 6]
Since we selected 1, we are left with the second array:
Array indexing is the same as accessing an
[4, 5, 6]
array element.
You can access an array element by The third number represents the third dimension,
referring to its index number. which contains three values:
The indexes in NumPy arrays start with 0, 4
meaning that the first element has index 0, 5
and the second has index 1 etc. 6
import numpy as np
Since we selected 2, we end up with the third value:
arr = np.array([1, 2, 3, 4])
print(arr[0]) 6

Slicing 2-D Arrays NumPy Array Copy vs View


From the second element, slice elements The Difference Between Copy and View
from index 1 to index 4 (not included):
import numpy as np The copy is a new array, and the view is just a
view of the original array. The copy owns the data
arr = np.array([[1, 2, 3, 4, 5], and any changes made to the copy will not affect
[6, 7, 8, 9, 10]]) original array, and any changes made to the
original array will not affect the copy.
print(arr[1, 1:4]) # [7 8 9] The view does not own the data and any changes
made to the view will affect the original array, and
import numpy as np
any changes made to the original array will affect
arr = np.array([[1, 2, 3, 4, 5], the view.
Make a copy, change the original array, and
[6, 7, 8, 9, 10]])
display both arrays:
print(arr[0:2, 2]) # [3 8]
import numpy as np
From both elements, slice index 1 to index
arr = np.array([1, 2, 3, 4, 5])
4 (not included), this will return a 2-D
x = arr.copy() arr[0] = 42
array: print(arr) # [42 2 3 4 5]
import numpy as np
print(x) # [1 2 3 4 5]
arr = np.array([[1, 2, 3, 4, 5],
Make a view, change the original array, and display
[6, 7, 8, 9, 10]])
both arrays:
print(arr[0:2, 1:4]) # [[2 3 4]
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
[7 8 9]] x = arr.view() arr[0] = 42
print(arr) # [42 2 3 4 5]
print(x) # [42 2 3 4 5]
Shape of an Array
Check if Array Owns its Data
The shape of an array is the number of
elements in each dimension. copies owns the data, and views does not
own the data, but how can we check this?
Get the Shape of an Array
Every NumPy array has the attribute base that
NumPy arrays have an attribute returns None if the array owns the data.
called shape that returns a tuple with each Otherwise, the base attribute refers to the
index having the number of corresponding original object.
elements. import numpy as np
import numpy as np arr = np.array([1, 2, 3, 4, 5])
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
x = arr.copy()
print(arr.shape) # (2, 4)
y = arr.view()
The example above returns (2, 4), which
print(x.base) # None
means that the array has 2 dimensions,
where the first dimension has 2 elements print(y.base) # [1 2 3 4 5]
and the second has 4.
Reshaping arrays Unknown Dimension
Reshaping means changing the shape of an You are allowed to have one "unknown"
array. dimension.
The shape of an array is the number of Meaning that you do not have to specify an
elements in each dimension. exact number for one of the dimensions in the
By reshaping we can add or remove reshape method.
dimensions or change number of elements Pass -1 as the value, and NumPy will calculate
in each dimension. this number for you.
Convert the following 1-D array with 12 Convert 1D array with 8 elements to 3D array
elements into a 2-D array. with 2x2 elements:
The outermost dimension will have 4
arrays, each with 3 elements: import numpy as np
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
arr =
newarr = arr.reshape(2, 2, -1)
np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
print(newarr)
11, 12])
# [[[1 2]
newarr = arr.reshape(4, 3)
[3 4]]
print(newarr)
[[5 6]
# [[ 1 2 3]
[7 8]]]
[ 4 5 6]
Note: We can not pass -1 to more than one
[ 7 8 9]
[10 11 12]]
Convert the following 1-D array with 12 dimension.
elements into a 3-D array. Flattening the arrays
The outermost dimension will have 2 arrays
that contains 3 arrays, each with 2 Flattening array means converting a
elements: multidimensional array into a 1D array.
import numpy as np
arr = We can use reshape(-1) to do this.

np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12]) import numpy as np
newarr = arr.reshape(2, 3, 2) arr = np.array([[1, 2, 3], [4, 5, 6]])
print(newarr) newarr = arr.reshape(-1)
# [[[ 1 2] print(newarr)
[ 3 4] Note: There are a lot of functions for changing
[ 5 6]] the shapes of arrays in
[[ 7 8] numpy flatten, ravel and also for rearranging
[ 9 10] the elements rot90, flip, fliplr, flipud etc.
[11 12]]]
Iterating Arrays Using nditer() Iterating With Different Step Size
The function nditer() is a helping function We can use filtering and followed by iteration.
that can be used from very basic to very Iterate through every scalar element of the 2D
advanced iterations. It solves some basic array skipping 1 element:
issues which we face in iteration, lets go import numpy as np
through it with examples. arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
Iterating on Each Scalar Element
for x in np.nditer(arr[:, ::2]):
In basic for loops, iterating through each
print(x)
scalar of an array we need to
use n for loops which can be difficult to # 1
write for arrays with very high 3
dimensionality.
import numpy as np 5
arr = np.array([[[1, 2], [3, 4]], 7
[[5, 6], [7, 8]]]) Enumerated Iteration Using ndenumerate()
for x in np.nditer(arr): Enumeration means mentioning sequence
print(x) number of somethings one by one.
Sometimes we require corresponding index of
# 1 the element while iterating,
2 the ndenumerate() method can be used for
those usecases.
3
import numpy as np
4
arr = np.array([1, 2, 3])
5
for idx, x in np.ndenumerate(arr):
6
print(idx, x)
7
# (0,) 1
8
(1,) 2
Iterating Array With Different Data Types
(2,) 3
We can use op_dtypes argument and pass Enumerate on following 2D array's elements:
it the expected datatype to change the
datatype of elements while iterating. import numpy as np
NumPy does not change the data type of arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
the element in-place (where the element is
in array) so it needs some other space to for idx, x in np.ndenumerate(arr):
perform this action, that extra space is print(idx, x)
called buffer, and in order to enable it
# (0, 0) 1
in nditer() we pass flags=['buffered'].
import numpy as np (0, 1) 2
arr = np.array([1, 2, 3])
(0, 2) 3
for x in np.nditer(arr,
flags=['buffered'], op_dtypes=['S']): (0, 3) 4
print(x)
…………

Joining NumPy Arrays Stacking Along Rows


Joining means putting contents of two or NumPy provides a helper function: hstack() to
more arrays in a single array. stack along rows.
In SQL we join tables based on a key, import numpy as np
whereas in NumPy we join arrays by axes. arr1 = np.array([1, 2, 3])
We pass a sequence of arrays that we want
to join to the concatenate() function, along arr2 = np.array([4, 5, 6])
with the axis. If axis is not explicitly arr = np.hstack((arr1, arr2))
passed, it is taken as 0.
import numpy as np print(arr)

arr1 = np.array([1, 2, 3]) Stacking Along Columns


arr2 = np.array([4, 5, 6]) NumPy provides a helper function: vstack() to
arr = np.concatenate((arr1, arr2)) stack along columns.
import numpy as np
print(arr) # [1 2 3 4 5 6]
arr1 = np.array([1, 2, 3])
Join two 2-D arrays along rows (axis=1):
arr2 = np.array([4, 5, 6])
import numpy as np
arr = np.vstack((arr1, arr2))
arr1 = np.array([[1, 2], [3, 4]])
print(arr)
arr2 = np.array([[5, 6], [7, 8]])
Stacking Along Height (depth)
arr = np.concatenate((arr1, arr2),
NumPy provides a helper function: dstack() to
axis=1)
stack along height, which is the same as depth.
print(arr) # [[1 2 5 6] import numpy as np
[3 4 7 8]]
Joining Arrays Using Stack Functions
Stacking is same as concatenation, the
only difference is that stacking is done
along a new axis.
We can concatenate two 1-D arrays along
the second axis which would result in
arr1 = np.array([1, 2, 3])
putting them one over the other, ie.
stacking. arr2 = np.array([4, 5, 6])
We pass a sequence of arrays that we want
arr = np.dstack((arr1, arr2))
to join to the stack() method along with the
axis. If axis is not explicitly passed it is print(arr)
taken as 0.
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.stack((arr1, arr2), axis=1)
print(arr)

Splitting NumPy Arrays # [array([[1, 2],

Splitting is reverse operation of Joining. [3, 4]]), array([[5, 6],


Joining merges multiple arrays into one [7, 8]]), array([[ 9, 10],
and Splitting breaks one array into
[11, 12]])]
multiple.
We use array_split() for splitting arrays, we Split the 2-D array into three 2-D arrays.
pass it the array we want to split and the
import numpy as np
number of splits.
import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6],
arr = np.array([1, 2, 3, 4, 5, 6])
[7, 8, 9], [10, 11, 12], [13, 14, 15],
newarr = np.array_split(arr, 3)
print(newarr) # [array([1, 2]), [16, 17, 18]])
array([3, 4]), array([5, 6])]
newarr = np.array_split(arr, 3)
If the array has less elements than print(newarr)
required, it will adjust from the end
accordingly. # [array([[1, 2, 3],

import numpy as np [4, 5, 6]]), array([[ 7, 8, 9],


arr = np.array([1, 2, 3, 4, 5, 6]) [10, 11, 12]]), array([[13, 14, 15],
newarr = np.array_split(arr, 4)
print(newarr) # [array([1, 2]), [16, 17, 18]])]
array([3, 4]), array([5]), array([6])] In addition, you can specify which axis you want
to do the split around.
Split Into Arrays
The example below also returns three 2-D
The return value of arrays, but they are split along the row (axis=1).
the array_split() method is an array import numpy as np
containing each of the split as an array.
If you split an array into 3 arrays, you can arr = np.array([[1, 2, 3], [4, 5, 6],
access them from the result just like any [7, 8, 9], [10, 11, 12], [13, 14, 15],
array element:
import numpy as np [16, 17, 18]])
arr = np.array([1, 2, 3, 4, 5, 6]) newarr = np.array_split(arr, 3, axis=1)
newarr = np.array_split(arr, 3)
print(newarr[0]) print(newarr)
print(newarr[1]) # [array([[ 1],
print(newarr[2])
[ 4],
Splitting 2-D Arrays
[ 7],
Use the same syntax when splitting 2-D
arrays.Use the array_split() method, pass [10],
in the array you want to split and the [13],
number of splits you want to do.
[16]]), array([[ 2],
import numpy as np
[ 5],
arr = np.array([[1, 2], [3, 4], [5, 6],
[ 8],
[7, 8], [9, 10], [11, 12]])
[11],
newarr = np.array_split(arr, 3)
[14],
print(newarr)
[17]]), ……]
An alternate solution is import numpy as np
using hsplit() opposite of hstack() arr = np.array([1, 2, 3, 4, 5, 4, 4])

Use the hsplit() method to split the 2-D x = np.where(arr == 4)

array into three 2-D arrays along rows. print(x) # (array([3, 5, 6]),)

import numpy as np Find the indexes where the values are even:

arr = np.array([[1, 2, 3], [4, 5, 6], import numpy as np

[7, 8, 9], [10, 11, 12], [13, 14, 15], arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])

[16, 17, 18]]) x = np.where(arr%2 == 0)

newarr = np.hsplit(arr, 3) print(x) # (array([1, 3, 5, 7]),)

print(newarr) Search Sorted


# [array([[ 1], There is a method called searchsorted() which
[ 4], performs a binary search in the array, and
returns the index where the specified value
[ 7], would be inserted to maintain the search order.
[10], The searchsorted() method is assumed to be
used on sorted arrays.
[13], import numpy as np
[16]]), array([[ 2], arr = np.array([6, 7, 8, 9])
x = np.searchsorted(arr, 7)
[ 5], print(x) # 1
[ 8], The method starts the search from the left and
returns the first index where the number 7 is no
[11],
longer larger than the next value.
[14], Search From the Right Side
[17]]), array([[ 3], By default the left most index is returned, but
[ 6], we can give side='right' to return the right most
index instead.
[ 9], import numpy as np
[12], arr = np.array([6, 7, 8, 9])
x = np.searchsorted(arr, 7, side='right')
[15], print(x) # 2
[18]])] Multiple Values

Note: Similar alternates To search for more than one value, use an array
with the specified values.
to vstack() and dstack() are available import numpy as np
as vsplit() and dsplit(). arr = np.array([1, 3, 5, 7])
Searching Arrays x = np.searchsorted(arr, [2, 4, 6])

You can search an array for a certain value, print(x) # [1 2 3]


and return the indexes that get a match. The return value is an array: [1 2 3] containing
To search an array, use the three indexes where 2, 4, 6 would be
the where() method. inserted in the original array to maintain the
Find the indexes where the value is 4: order.
Sorting Arrays Filtering Arrays
Sorting means putting elements in Getting some elements out of an existing array
an ordered sequence. and creating a new array out of them is
Ordered sequence is any sequence that has called filtering.
an order corresponding to elements, like In NumPy, you filter an array using a boolean
numeric or alphabetical, ascending or index list.
descending. A boolean index list is a list of booleans
The NumPy ndarray object has a function corresponding to indexes in the array.
called sort(), that will sort a specified If the value at an index is True that element is
array. contained in the filtered array, if the value at
import numpy as np that index is False that element is excluded from
arr = np.array([3, 2, 0, 1]) the filtered array.
import numpy as np
print(np.sort(arr))
arr = np.array([41, 42, 43, 44])
Note: This method returns a copy of the
x = [True, False, True, False]
array, leaving the original array
unchanged. newarr = arr[x]
You can also sort arrays of strings, or any print(newarr)
other data type:
import numpy as np The example above will return [41, 43], why?
Because the new filter contains only the values
arr =
where the filter array had the value True, in this
np.array(['banana', 'cherry', 'apple']) case, index 0 and 2.
print(np.sort(arr)) Creating the Filter Array

Sorting a 2-D Array Create a filter array that will return only values

If you use the sort() method on a 2-D higher than 42:


import numpy as np
arr = np.array([41, 42, 43, 44])
# Create an empty list
filter_arr = []
# go through each element in arr
array, both arrays will be sorted:
for element in arr:
import numpy as np
# if the element is higher than 42, set the
arr = np.array([[3, 2, 4], [5, 0, 1]])
value to True, otherwise False:
print(np.sort(arr))
if element > 42:
# [[2 3 4]
filter_arr.append(True)
[0 1 5]]
else:
filter_arr.append(False)
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)
Create a filter array that will return only What is a Random Number?
even elements from the original array: Random number does NOT mean a different
import numpy as np number every time. Random means something
that can not be predicted logically.
arr = np.array([1, 2, 3, 4, 5, 6, 7])
Pseudo Random and True Random.
# Create an empty list
Random numbers generated through a
filter_arr = [] generation algorithm are called pseudo random.
# go through each element in arr Can we make truly random numbers?
Yes. In order to generate a truly random number
for element in arr: on our computers we need to get the random
# if the element is completely divisble by data from some outside source. This outside
2, set the value to True, otherwise False source is generally our keystrokes, mouse
movements, data on network etc.
if element % 2 == 0: We do not need truly random numbers, unless
filter_arr.append(True) its related to security (e.g. encryption keys) or
the basis of application is the randomness (e.g.
else:
Digital roulette wheels).
filter_arr.append(False) Generate Random Number
newarr = arr[filter_arr] NumPy offers the random module to work with
print(filter_arr) random numbers.
Generate a random integer from 0 to 100:
print(newarr)
from numpy import random
Creating Filter Directly From Array x = random.randint(100)
print(x)
The above example is quite a common task
in NumPy and NumPy provides a nice way Generate Random Float
to tackle it.
We can directly substitute the array instead The random module's rand() method returns a
of the iterable variable in our condition and random float between 0 and 1.
it will work just as we expect it to. Generate a random float from 0 to 1:
Create a filter array that will return only
from numpy import random
values higher than 42:
import numpy as np x = random.rand()
arr = np.array([41, 42, 43, 44]) print(x)
filter_arr = arr > 42
newarr = arr[filter_arr] Generate Random Array
print(filter_arr)
Integers
print(newarr)
Create a filter array that will return only The randint() method takes a size parameter
even elements from the original array: where you can specify the shape of an array.
import numpy as np Generate a 1-D array containing 5 random
arr = np.array([1, 2, 3, 4, 5, 6, 7]) integers from 0 to 100:
filter_arr = arr % 2 == 0
newarr = arr[filter_arr] from numpy import random
print(filter_arr) x=random.randint(100, size=(5))
print(newarr) print(x)

Generate a 2-D array with 3 rows, each What is Data Distribution?


row containing 5 random integers from 0 to
100: Data Distribution is a list of all possible values,
and how often each value occurs.
from numpy import random
x = random.randint(100, size=(3, 5)) Such lists are important when working with
statistics and data science.
print(x)
Floats The random module offer methods that returns
randomly generated data distributions.
The rand() method also allows you to
specify the shape of the array. Random Distribution
Generate a 1-D array containing 5 random
floats:
from numpy import random A random distribution is a set of random
x = random.rand(5) numbers that follow a certain probability density
print(x) function.

Generate a 2-D array with 3 rows, each Probability Density Function: A function that
row containing 5 random numbers: describes a continuous probability. i.e.
from numpy import random probability of all values in an array.
x = random.rand(3, 5)
print(x) We can generate random numbers based on
defined probabilities using the choice() method
Generate Random Number From Array of the random module.

The choice() method allows you to The choice() method allows us to specify the
generate a random value based on an
probability for each value.
array of values.
The choice() method takes an array as a The probability is set by a number between 0
parameter and randomly returns one of the and 1, where 0 means that the value will never
values. occur and 1 means that the value will always
Return one of the values in an array: occur.
from numpy import random
x = random.choice([3, 5, 7, 9]) Generate a 1-D array containing 100 values,
print(x)
where each value has to be 3, 5, 7 or 9.
The choice() method also allows you to The probability for the value to be 3 is set to be
return an array of values. 0.1
Add a size parameter to specify the shape The probability for the value to be 5 is set to be
of the array. 0.3
Generate a 2-D array that consists of the The probability for the value to be 7 is set to be
values in the array parameter (3, 5, 7, and 0.6
9): The probability for the value to be 9 is set to be
from numpy import random
0
x = random.choice([3, 5, 7, 9],
size=(3, 5))
print(x)

from numpy import random Generating Permutation of Arrays


x = random.choice([3, 5, 7, 9], Generate a random permutation of elements of
p=[0.1, 0.3, 0.6, 0.0], size=(100)) following array:
print(x)
from numpy import random
Even if you run the example above 100 import numpy as np
times, the value 9 will never occur.
arr = np.array([1, 2, 3, 4, 5])
You can return arrays of any shape and print(random.permutation(arr))
size by specifying the shape in The permutation() method returns a re-arranged
the size parameter. array (and leaves the original array un-
changed).
Same example as above, but return a 2-D
array with 3 rows, each containing 5 Seaborn
values. Visualize Distributions With Seaborn
from numpy import random Seaborn is a library that uses Matplotlib
x = random.choice([3, 5, 7, 9], underneath to plot graphs. It will be used to
visualize random distributions.
p=[0.1, 0.3, 0.6, 0.0], size=(3, 5))
print(x)
Random Permutations of Elements
A permutation refers to an arrangement of
elements. e.g. [3, 2, 1] is a permutation of
[1, 2, 3] and vice-versa.
The NumPy Random module provides two
methods for
this: shuffle() and permutation().
Shuffling Arrays
Shuffle means changing arrangement of
elements in-place. i.e. in the array itself.
Randomly shuffle elements of following
array:
from numpy import random
import numpy as np
arr = np.array([1, 2, 3, 4, 5]) !pip install seaborn
random.shuffle(arr)
Distplots
print(arr)
The shuffle() method makes changes to Distplot stands for distribution plot, it takes as
the original array.
input an array and plots a curve corresponding
to the distribution of points in the array.

Plotting a Distplot
Import Matplotlib import matplotlib.pyplot as plt
Import the pyplot object of the Matplotlib import seaborn as sns
module in your code using the following sns.distplot([0, 1, 2, 3, 4, 5])
statement: plt.show()
import matplotlib.pyplot as plt Plotting a Distplot Without the Histogram
Import Seaborn import matplotlib.pyplot as plt

Import the Seaborn module in your code import seaborn as sns

using the following statement: sns.distplot([0, 1, 2, 3, 4, 5], hist=False)

import seaborn as sns plt.show()

Normal (Gaussian) Distribution Generate a random normal distribution of size

Normal Distribution 2x3 with mean at 1 and standard deviation of 2:


from numpy import random
The Normal Distribution is one of the most
x = random.normal(loc=1, scale=2,
important distributions. It is also called the
size=(2, 3))
Gaussian Distribution after the German
print(x)
mathematician Carl Friedrich Gauss. It fits
Visualization of Normal Distribution
the probability distribution of many events,
from numpy import random
eg. IQ Scores, Heartbeat etc. Use
import matplotlib.pyplot as plt
the random.normal() method to get a
import seaborn as sns
Normal Data Distribution.
sns.distplot(random.normal(size=1000),
It has three parameters:
hist=False)
plt.show()
loc - (Mean) where the peak of the bell
exists.

scale - (Standard Deviation) how flat the


graph distribution should be.

size - The shape of the returned array.


Generate a random normal distribution of
size 2x3: Note: The curve of a Normal Distribution is also
from numpy import random
known as the Bell Curve because of the bell-
x = random.normal(size=(2, 3))
shaped curve.
print(x)

Binomial Distribution
Binomial Distribution
Binomial Distribution is a Discrete Distribution.
It describes the outcome of binary
scenarios, e.g. toss of a coin, it will either
be head or tails.
It has three parameters:

n - number of trials.

Difference Between Normal and Binomial


p - probability of occurence of each trial
(e.g. for toss of a coin 0.5 each). Distribution

size - The shape of the returned array. The main difference is that normal distribution is
continous whereas binomial is discrete, but if
Discrete Distribution: The distribution is defined
there are enough data points it will be quite
at separate set of events, e.g. a coin toss's
similar to normal distribution with certain loc and
scale.
from numpy import random
result is discrete as it can be only head or
import matplotlib.pyplot as plt
tails whereas height of people is continuous
import seaborn as sns
as it can be 170, 170.1, 170.11 and so on.
sns.distplot(random.normal(loc=50, scale=5,
Given 10 trials for coin toss generate 10
size=1000), hist=False, label='normal')
data points:
sns.distplot(random.binomial(n=100, p=0.5,
from numpy import random
size=1000), hist=False, label='binomial')
x = random.binomial(n=10, p=0.5,
plt.show()
size=10)
print(x)
Visualization of Binomial Distribution
from numpy import random
import matplotlib.pyplot as plt
import seaborn as sns
sns.distplot(random.binomial(n=10,
p=0.5, size=1000), hist=True, kde=False)
plt.show()

Poisson Distribution Difference Between Normal and Poisson


Poisson Distribution is a Discrete Distribution
Distribution. It estimates how many times Normal distribution is continous whereas poisson
an event can happen in a specified time. is discrete. But we can see that similar to
e.g. If someone eats twice a day what is binomial for a large enough poisson distribution
probability he will eat thrice? it will become similar to normal distribution with
certain std dev and mean.
It has two parameters:
from numpy import random
lam - rate or known number of occurences import matplotlib.pyplot as plt
e.g. 2 for above problem.
import seaborn as sns
size - The shape of the returned array. sns.distplot(random.normal(loc=50, scale=7,
size=1000), hist=False, label='normal')
Generate a random 1x10 distribution for
sns.distplot(random.poisson(lam=50,
occurence 2:
size=1000), hist=False, label='poisson')
from numpy import random
plt.show()
x = random.poisson(lam=2, size=10)
print(x)
Visualization of Poisson Distribution
from numpy import random
import matplotlib.pyplot as plt
import seaborn as sns
sns.distplot(random.poisson(lam=2,
size=1000), kde=False)
plt.show()
Difference Between Poisson and Binomial
Distribution
The difference is very subtle it is that, binomial
distribution is for discrete trials, whereas poisson
distribution is for continuous trials.
But for very large n and near-zero p binomial
distribution is near identical to poisson
distribution such that n * p is nearly equal
to lam.

from numpy import random Visualization of Uniform Distribution


import matplotlib.pyplot as plt
import seaborn as sns from numpy import random
import matplotlib.pyplot as plt
sns.distplot(random.binomial(n=1000, import seaborn as sns
p=0.01, size=1000), sns.distplot(random.uniform(size=1000),
hist=False)
hist=False, label='binomial') plt.show()
sns.distplot(random.poisson(lam=10,
size=1000), hist=False, label='poisson')
plt.show()
Uniform Distribution Logistic Distribution
Used to describe probability where every Logistic Distribution is used to describe growth.
event has equal chances of occuring. Used extensively in machine learning in logistic
E.g. Generation of random numbers. regression, neural networks etc.
It has three parameters: It has three parameters:

a - lower bound - default 0 .0. loc - mean, where the peak is. Default 0.

b - upper bound - default 1.0. scale - standard deviation, the flatness of


distribution. Default 1.
size - The shape of the returned array.
size - The shape of the returned array.
Create a 2x3 uniform distribution sample:
Draw 2x3 samples from a logistic distribution
from numpy import random with mean at 1 and stddev 2.0:
x = random.uniform(size=(2, 3))
print(x) from numpy import random
x = random.logistic(loc=1, scale=2,
size=(2, 3))
print(x)
Visualization of Logistic Distribution
from numpy import random
import matplotlib.pyplot as plt
import seaborn as sns
sns.distplot(random.logistic(size=1000),
hist=False)
plt.show()

Multinomial Distribution

Multinomial distribution is a generalization of


binomial distribution.

It describes outcomes of multi-nomial scenarios


unlike binomial where scenarios must be only
Difference Between Logistic and Normal one of two. e.g. Blood type of a population, dice
roll outcome.
Distribution
It has three parameters:
Both distributions are near identical, but
n - number of possible outcomes (e.g. 6 for dice
logistic distribution has more area under
roll).
the tails, meaning it represents more
possibility of occurrence of an event further
pvals - list of probabilties of outcomes (e.g. [1/6,
away from mean.
1/6, 1/6, 1/6, 1/6, 1/6] for dice roll).
For higher value of scale (standard
size - The shape of the returned array.
deviation) the normal and logistic
distributions are near identical apart from
Draw out a sample for dice roll:
the peak.
from numpy import random
from numpy import random
x = random.multinomial(n=6,
import matplotlib.pyplot as plt pvals=[1/6, 1/6, 1/6, 1/6, 1/6, 1/6])
print(x)
import seaborn as sns
sns.distplot(random.normal(scale=2, Note: Multinomial samples will NOT produce a
size=1000), hist=False, label='normal') single value! They will produce one value for
each pval.
sns.distplot(random.logistic(size=1000),
hist=False, label='logistic') Note: As they are generalization of binomial
distribution their visual representation and
plt.show()
similarity of normal distribution is same as that
of multiple binomial distributions.

Exponential Distribution Relation Between Poisson and Exponential


Distribution
Exponential distribution is used for
describing time till next event e.g.
failure/success etc. Poisson distribution deals with number of
occurences of an event in a time period whereas
It has two parameters: exponential distribution deals with the time
between these events.
scale - inverse of rate ( see lam in poisson
distribution ) defaults to 1.0. Chi Square Distribution

size - The shape of the returned array. Chi Square distribution is used as a basis to
verify the hypothesis.
Draw out a sample for exponential
distribution with 2.0 scale with 2x3 size: It has two parameters:
from numpy import random
df - (degree of freedom).
x = random.exponential(scale=2,
size - The shape of the returned array.
size=(2, 3))
print(x) Draw out a sample for chi squared distribution
Visualization of Exponential Distribution with degree of freedom 2 with size 2x3:
from numpy import random from numpy import random
import matplotlib.pyplot as plt x = random.chisquare(df=2, size=(2, 3))
import seaborn as sns print(x)
sns.distplot(random.exponential(size=100 Visualization of Chi Square Distribution
0), hist=False) from numpy import random
plt.show() import matplotlib.pyplot as plt
import seaborn as sns
sns.distplot(random.chisquare(df=1,
size=1000), hist=False)
plt.show()
Rayleigh Distribution Similarity Between Rayleigh and Chi Square
Distribution
Rayleigh distribution is used in signal
processing.
At unit stddev the and 2 degrees of freedom
It has two parameters: rayleigh and chi square represent the same
distributions.
scale - (standard deviation) decides how
flat the distribution will be default 1.0). Pareto Distribution

size - The shape of the returned array. A distribution following Pareto's law i.e. 80-20
distribution (20% factors cause 80% outcome).
Draw out a sample for rayleigh distribution
with scale of 2 with size 2x3: It has two parameter:
from numpy import random
a - shape parameter.
x = random.rayleigh(scale=2,
size - The shape of the returned array.
size=(2, 3))
print(x) Draw out a sample for pareto distribution with
Visualization of Rayleigh Distribution shape of 2 with size 2x3:
from numpy import random from numpy import random
import matplotlib.pyplot as plt x = random.pareto(a=2, size=(2, 3))
import seaborn as sns print(x)
sns.distplot(random.rayleigh(size=1000), Visualization of Pareto Distribution
hist=False) from numpy import random
plt.show() import matplotlib.pyplot as plt
import seaborn as sns
sns.distplot(random.pareto(a=2, size=1000),
kde=False)
plt.show()
Zipf Distribution
Visualization of Zipf Distribution

Zipf distritutions are used to sample data


Sample 1000 points but plotting only ones with
based on zipf's law.
value < 10 for more meaningful chart.
Zipf's Law: In a collection the nth common
from numpy import random
term is 1/n times of the most common
term. E.g. 5th common word in english has import matplotlib.pyplot as plt
occurs nearly 1/5th times as of the most import seaborn as sns
used word.
x = random.zipf(a=2, size=1000)
It has two parameters: sns.distplot(x[x<10], kde=False)

a - distribution parameter. plt.show()

size - The shape of the returned array.

Draw out a sample for zipf distribution with


distribution parameter 2 with size 2x3:

from numpy import random


x = random.zipf(a=2, size=(2, 3))
print(x)

NumPy ufuncs Why use ufuncs?


What are ufuncs?
ufuncs are used to implement vectorization in
NumPy which is way faster than iterating over
ufuncs stands for "Universal Functions" and elements.
they are NumPy functions that operates on
the ndarray object. They also provide broadcasting and additional
methods like reduce, accumulate etc. that are
very helpful for computation.
ufuncs also take additional arguments, like: With ufunc, we can use the add() function:
import numpy as np
where boolean array or condition defining
where the operations should take place.
x = [1, 2, 3, 4]
dtype defining the return type of elements.
y = [4, 5, 6, 7]

out output array where the return value z = np.add(x, y)


should be copied. print(z)

What is Vectorization? How To Create Your Own ufunc

Co nverting iterative statements into a To create you own ufunc, you have to define a
vector based operation is called function, like you do with normal functions in
vectorization. Python, then you add it to your NumPy ufunc
library with the frompyfunc() method.
It is faster as modern CPUs are optimized
for such operations. The frompyfunc() method takes the following
arguments:
Add the Elements of Two Lists
1. function - the name of the function.
2. inputs - the number of input arguments
list 1: [1, 2, 3, 4] (arrays).
3. outputs - the number of output arrays.
list 2: [4, 5, 6, 7]
Create your own ufunc for addition:
One way of doing it is to iterate over both
import numpy as np
of the lists and then sum each elements.
def myadd(x, y):
Without ufunc, we can use Python's built- return x+y
in zip() method: myadd = np.frompyfunc(myadd, 2, 1)
x = [1, 2, 3, 4] print(myadd([1, 2, 3, 4], [5, 6, 7, 8]))
y = [4, 5, 6, 7] Check if a Function is a ufunc
z = []
for i, j in zip(x, y): Check the type of a function to check if it is a
z.append(i + j) ufunc or not.

print(z) A ufunc should return <class 'numpy.ufunc'>.


NumPy has a ufunc for this, called add(x,
Check if a function is a ufunc:
y) that will produce the same result.
import numpy as np
print(type(np.add))
If it is not a ufunc, it will return another Add the values in arr1 to the values in arr2:
type, like this built-in NumPy function for
joining two or more arrays: import numpy as np
arr1 = np.array([10, 11, 12, 13, 14, 15])
Check the type of another function: arr2 = np.array([20, 21, 22, 23, 24, 25])
concatenate(): newarr = np.add(arr1, arr2)
print(newarr)
import numpy as np
print(type(np.concatenate)) The example above will return [30 32 34 36 38
40] which is the sums of 10+20, 11+21, 12+22
To test if the function is a ufunc in an if etc.
statement, use the numpy.ufunc value
(or np.ufunc if you use np as an alias for Subtraction
numpy):

Use an if statement to check if the function The subtract() function subtracts the values from
is a ufunc or not: one array with the values from another array,
and return the results in a new array.
import numpy as np
if type(np.add) == np.ufunc: Subtract the values in arr2 from the values in
print('add is ufunc') arr1:
else:
print('add is not ufunc') import numpy as np
arr1 = np.array([10, 20, 30, 40, 50, 60])
Simple Arithmetic arr2 = np.array([20, 21, 22, 23, 24, 25])
newarr = np.subtract(arr1, arr2)
print(newarr)
You could use arithmetic
operators + - * / directly between NumPy The example above will return [-10 -1 8 17 26
arrays, but this section discusses an
35] which is the result of 10-20, 20-21, 30-22
extension of the same where we have
functions that can take any array-like etc.
objects e.g. lists, tuples etc. and perform
arithmetic conditionally. Multiplication

Arithmetic Conditionally: means that we The multiply() function multiplies the values from
can define conditions where the arithmetic one array with the values from another array,
operation should happen. and return the results in a new array.

All of the discussed arithmetic functions Multiply the values in arr1 with the values in
take a where parameter in which we can arr2:
specify that condition.
import numpy as np
Addition arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([20, 21, 22, 23, 24, 25])
newarr = np.multiply(arr1, arr2)
The add() function sums the content of two print(newarr)
arrays, and return the results in a new
array.
Remainder

Both the mod() and the remainder() functions


The example above will return [200 420 return the remainder of the values in the first
660 920 1200 1500] which is the result of array corresponding to the values in the second
10*20, 20*21, 30*22 etc. array, and return the results in a new array.
Divide the values in arr1 with the values in import numpy as np
arr2: arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([3, 7, 9, 8, 2, 33])
import numpy as np newarr = np.mod(arr1, arr2)
arr1 = print(newarr)
np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([3, 5, 10, 8, 2, 33]) The example above will return [1 6 3 0 0 27]
newarr = np.divide(arr1, arr2)
which is the remainders when you divide 10 with
print(newarr)
3 (10%3), 20 with 7 (20%7) 30 with 9 (30%9)
etc.
The example above will return
[3.33333333 4. 3. 5. 25. 1.81818182]
You get the same result when using
which is the result of 10/3, 20/5, 30/10
the remainder() function:
etc.
import numpy as np
Power arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([3, 7, 9, 8, 2, 33])
newarr = np.remainder(arr1, arr2)
The power() function rises the values from
print(newarr)
the first array to the power of the values of
the second array, and return the results in
a new array. Quotient and Mod

Raise the valules in arr1 to the power of The divmod() function return both the quotient
values in arr2: and the the mod. The return value is two arrays,
the first array contains the quotient and second
import numpy as np array contains the mod.
arr1 =
np.array([10, 20, 30, 40, 50, 60]) import numpy as np
arr2 = np.array([3, 5, 6, 8, 2, 33]) arr1 = np.array([10, 20, 30, 40, 50, 60])
newarr = np.power(arr1, arr2) arr2 = np.array([3, 7, 9, 8, 2, 33])
print(newarr) newarr = np.divmod(arr1, arr2)
print(newarr)
The example above will return [1000
3200000 729000000 6553600000000 2500 The example above will return:
0] which is the result of 10*10*10, (array([3, 2, 3, 5, 25, 1]), array([1, 6, 3, 0, 0,
20*20*20*20*20, 30*30*30*30*30*30 27]))
etc. The first array represents the quotients, (the
integer value when you divide 10 with 3, 20 with
7, 30 with 9 etc.
The second array represents the remainders of
the same divisions.
Absolute Values

Both the absolute() and the abs() functions


functions do the same absolute operation
element-wise but we should
use absolute() to avoid confusion with
python's inbuilt math.abs()

Return the quotient and mod:

import numpy as np
arr = np.array([-1, -2, 1, 2, 3, -4])
newarr = np.absolute(arr)
print(newarr)

The example above will return [1 2 1 2 3


4].

You might also like