- git Init ( Initialize Git repo)
- git status (shows untracked files)
- git add <filename> ( add files to git staging area) [ git add . to add all the files]
- git commit -m"<commit msg>" ( commit the change to git repo)
- git log (shows the commit)
Tuesday, March 19, 2024
Git steps
Thursday, March 14, 2024
Apply any function of your choice
Pandas.apply allow the users to pass a function and apply it on every single value of the Pandas series.
import pandas as pd
data = {"K1": [12, 23], "K2": [25,50]}
df = pd.DataFrame(data, index=['R1', 'R2'])
print(df.apply(lambda x: x-2))
Output:
K1 K2
R1 10 23
R2 21 48
Monday, March 11, 2024
Conditional Operation on DataFrame
import pandas as pd
import numpy as np
from numpy.random import randn
np.random.seed(121)
# Create Dataframe
df = pd.DataFrame(randn(5, 4), ['A', 'B', 'C', 'D', 'E'], ['W', 'X', 'Y', 'Z'])
print("DataFrame:\n")
print(df)
print("Check if value > 0")
print(df[df>0])
print("Get all the row where Col. X value is >0")
print(df[df['X']>0])
O/p:
DataFrame:
W X Y Z
A -0.212033 -0.284929 -0.573898 -0.440310
B -0.330111 1.183695 1.615373 0.367062
C -0.014119 0.629642 1.709641 -1.326987
D 0.401873 -0.191427 1.403826 -1.968769
E -0.790415 -0.732722 0.087744 -0.500286
Check if value > 0
W X Y Z
A NaN NaN NaN NaN
B NaN 1.183695 1.615373 0.367062
C NaN 0.629642 1.709641 NaN
D 0.401873 NaN 1.403826 NaN
E NaN NaN 0.087744 NaN
Get all the row where Col. X value is >0
W X Y Z
B -0.330111 1.183695 1.615373 0.367062
C -0.014119 0.629642 1.709641 -1.326987
Pandas Series and Dataframe
What is Series?
In pandas, a series is a one-dimensional labeled array capable of holding any data type. It is a fundamental data structure in pandas and can be thought of as a column in a spreadsheet or a single column of a DataFrame. The Series is similar to a NumPy array but comes with additional features like labeled indices, which makes it more powerful and flexible.
import pandas as pd
# Creating a Series with custom indices data = [1, 2, 3, 4, 5] custom_indices = ['a', 'b', 'c', 'd', 'e'] series = pd.Series(data, index=custom_indices)
#1st argument is Data, next is index # Displaying the Series with custom indices print(series)
O/P:
a 1 b 2 c 3 d 4 e 5 dtype: int64
How to access value from Series?
print(series['c'])
O/p:
3
What is DataFrame?
In pandas, a DataFrame is a two-dimensional labeled data structure that is widely used for handling and manipulating tabular data. It can be thought of as a table, similar to a spreadsheet or a SQL table, where data is organized in rows and columns. import pandas as pd
import numpy as np
from numpy.random import randn
np.random.seed(121)
# Create Dataframe
df = pd.DataFrame(randn(5, 4), ['A', 'B', 'C', 'D', 'E'], ['W', 'X', 'Y', 'Z'])
print("DataFrame:\n")
print(df)
# Access Column: Return type -> Series
print("Access Column named 'W'\n")
print(df['W'])
# Access list of Column : Return type -> Dataframe
print("Access Columns named Y & Z\n")
print(df[['Y', 'Z']])
# Create a new column
df['V'] = df['Y'] + df['Z']
print("DataFrame:\n")
print(df)
# Drop the new column, Inplace -> To drop row, use axis=0
df.drop('V', axis=1, inplace=True)
print("DataFrame:\n")
print(df)
# Access Row using its label : Return type -> Series
print("Access Row labeled as 'B':\n")
print(df.loc['B'])
# Access Row using its internal index : Return type -> Series
print("Access Row 1:\n")
print(df.iloc[1])
#Access multiple rows : Return type-> DataFrame
print("Access Row labeled as B & C:\n")
print(df.loc[['B','C']])O/p:DataFrame: W X Y Z A -0.212033 -0.284929 -0.573898 -0.440310 B -0.330111 1.183695 1.615373 0.367062 C -0.014119 0.629642 1.709641 -1.326987 D 0.401873 -0.191427 1.403826 -1.968769 E -0.790415 -0.732722 0.087744 -0.500286 Access Column named 'W' A -0.212033 B -0.330111 C -0.014119 D 0.401873 E -0.790415 Name: W, dtype: float64 Access Columns named Y & Z Y Z A -0.573898 -0.440310 B 1.615373 0.367062 C 1.709641 -1.326987 D 1.403826 -1.968769 E 0.087744 -0.500286 DataFrame: W X Y Z V A -0.212033 -0.284929 -0.573898 -0.440310 -1.014208 B -0.330111 1.183695 1.615373 0.367062 1.982435 C -0.014119 0.629642 1.709641 -1.326987 0.382653 D 0.401873 -0.191427 1.403826 -1.968769 -0.564943 E -0.790415 -0.732722 0.087744 -0.500286 -0.412542 DataFrame: W X Y Z A -0.212033 -0.284929 -0.573898 -0.440310 B -0.330111 1.183695 1.615373 0.367062 C -0.014119 0.629642 1.709641 -1.326987 D 0.401873 -0.191427 1.403826 -1.968769 E -0.790415 -0.732722 0.087744 -0.500286 Access Row labeled as 'B': W -0.330111 X 1.183695 Y 1.615373 Z 0.367062 Name: B, dtype: float64 Access Row 1: W -0.330111 X 1.183695 Y 1.615373 Z 0.367062 Name: B, dtype: float64 Access Row labeled as B & C: W X Y Z B -0.330111 1.183695 1.615373 0.367062 C -0.014119 0.629642 1.709641 -1.326987Similarly,
# Access a particular cell
print(df.loc['B', 'Y'])
# Access a subset of DF
print(df.loc[['B','C'],['X','Y']])
1.6153729283493805
X Y
B 1.183695 1.615373
C 0.629642 1.709641Friday, March 8, 2024
Cool features of Numpy
a = np.array([6,0,9,0,0,5,0])
def nonzero(a):
return a!=0
print(a[nonzero(a)])
output:
[6 9 5]
Wednesday, March 6, 2024
Numpy Array vs Python List
import numpy as np
list = [1,2,'Heaven','Hell']
arr = np.array(list)
#Please note, generally numpy generally does not contain Strings. It is mainly used
for numerical Operration.
list[2:] = 3
This is not allowed for normal python list. This will throw an error like
below:
list[2:] = 3 TypeError: can only assign an iterable
However, it is allowed for numpy array and it will change theoriginal numpy array.
import numpy as np
list = [1,2,'Heaven','Hell']
arr = np.array(list)
arr[2:] = 3
print(arr)Ouput: ['1' '2' '3' '3']Now, no avoid changing the original array, we can use copy option as below.Without copy:import numpy as np
list = [1,2,'Heaven','Hell']
arr = np.array(list)
arr_copy =arr
arr_copy[2:] = 3
print(arr)
print(arr_copy)O/p:['1' '2' '3' '3'] ['1' '2' '3' '3']With copy:import numpy as np
list = [1,2,'Heaven','Hell']
arr = np.array(list)
arr_copy =arr.copy()
arr_copy[2:] = 3
print(arr)
print(arr_copy)O/p:['1' '2' 'Heaven' 'Hell'] ['1' '2' '3' '3']
list_one = [1,2,3]
list_two = [4,5,6]
print(f"Result of list addition: {list_one + list_two}")
arr_one = np.array(list_one)
arr_two = np.array(list_two)
print(f"Result of array addition: {arr_one + arr_two}")O/p:Result of list addition: [1, 2, 3, 4, 5, 6] Result of array addition: [5 7 9]
Monday, March 4, 2024
Lamda Function
lambda keyword.passwords = ['72tK3', '6zW5P3', '1P3=it3?', 'i"u7/auX{m']
allowed_passwords = list(filter(lambda x: len(x) >= 8, passwords))
print(allowed_passwords)
Filter Function
Takes input a function which returns True/False and keeps the items which return True.
passwords = ['72tK3', '6zW5P3', '1P3=it3?', 'i"u7/auX{m']
def strong_password(password):
return len(password) >= 8
allowed_passwords = list(filter(strong_password, passwords))
print(allowed_passwords)
Output:['1P3=it3?', 'i"u7/auX{m']
Sunday, March 3, 2024
Map function
def names(firstname, lastname):
"""returns full name, inputs: first name and last name"""
return firstname + ' ' + lastname
fname = 'Priyanka'
lname = 'Chakraborti'
name = names(fname,lname)
print(name)
Output:
Priyanka Chakraborti
# I want to apply the same function over list
list_of_firstnames = ['Andy', 'Sam', 'Jim', 'Micheal']
list_of_surnames = ['Smith', 'Doe', 'Baker', 'Hendrix']
result = map(names,list_of_firstnames,list_of_surnames)
list_of_names = list(result)
print(list_of_names)Output:['Andy Smith', 'Sam Doe', 'Jim Baker', 'Micheal Hendrix']
Saturday, March 2, 2024
How to remove duplicates from list?
Use set().
list_of_subjects= ['Physics', 'English', 'Statistics', 'English','Computer Science']
print(list(set(list_of_subjects)))
Output:
['Computer Science', 'English', 'Physics', 'Statistics']
Thursday, February 29, 2024
Slice Object in Python
Built-in type that represents a range of indices. It's commonly used with sequences (like lists, strings, and tuples) to extract portions of the sequence.
list_of_students = [(1,"Joe"), (2,"John"), (3,"Jacob"), (4,"Jack"),
(5,"Karan"), (6, "Kavya"), (7,"Kamal")]
odd_slice = slice(0,len(list_of_students),2)
even_slice = slice(1,len(list_of_students),2)
list_of_group_one = list_of_students[odd_slice]
list_of_group_two = list_of_students[even_slice]
print(list_of_group_one)
print(list_of_group_two)
Output:
[(1, 'Joe'), (3, 'Jacob'), (5, 'Karan'), (7, 'Kamal')]
[(2, 'John'), (4, 'Jack'), (6, 'Kavya')]Wednesday, February 28, 2024
Python Decorator
In Python, a decorator is a design pattern that allows you to extend or modify the behavior of functions or methods without modifying their actual code. Decorators are applied using the @decorator syntax and are a concise way to wrap a function or method with additional functionality.
It helps you to off/on some functionality.
def log_function_call(func):
def wrapper(*args):
print(f"Calling {func.__name__} with arguments {args}")
result = func(*args)
print(f"{func.__name__} execution completed.")
return result
return wrapper
@log_function_call
def add_numbers(a, b):
return a + b
@log_function_call
def multiply_numbers(x, y):
return x * y
# Calling decorated functions
result_add = add_numbers(3, 5)
print(result_add)
result_multiply = multiply_numbers(4, 6)
print(result_multiply)
Output:
Calling add_numbers with arguments (3, 5)
add_numbers execution completed.
8
Calling multiply_numbers with arguments (4, 6)
multiply_numbers execution completed.
24
Now if we comment out the decorator,def log_function_call(func):
def wrapper(*args):
print(f"Calling {func.__name__} with arguments {args}")
result = func(*args)
print(f"{func.__name__} execution completed.")
return result
return wrapper
# @log_function_call
def add_numbers(a, b):
return a + b
# @log_function_call
def multiply_numbers(x, y):
return x * y
# Calling decorated functions
result_add = add_numbers(3, 5)
print(result_add)
result_multiply = multiply_numbers(4, 6)
print(result_multiply)Output:8 24
Slice vs Split
Slicing is a broader concept applicable to sequences like lists, tuples, and strings. It involves extracting a portion, or a "slice," of a sequence based on indices. It is not an in-built function, it is a concept.
art_board = "ArtBoard1"
list_of_shapes = ["Square", "Triangle", "Circle"]
tuple_of_colors = ('59D5E0', 'F5DD61', 'FAA300', 'F4538A')
# Slice works on both string and Iterables
# Get first 3 characters
print(art_board[:3])
# Reverse the list
print(list_of_shapes[::-1])
print(tuple_of_colors[1::2])
Output:
Art
['Circle', 'Triangle', 'Square']
('F5DD61', 'F4538A')
Split is used to divide a string into a list of substrings basedon a specified delimiter.
By default, the delimiter is a space.
# Split only works on String and create a list as outcome
my_name = "Priyanka Chakraborti"
my_first_name = my_name.split()[0]
my_last_name = my_name.split()[1]
print(my_first_name, my_last_name, sep=',')
print(my_name.split())
# Change list to Tuple
print(tuple(my_name.split()))
Output:
Priyanka,Chakraborti
['Priyanka', 'Chakraborti']
('Priyanka', 'Chakraborti')
Understanding the Purpose of if name == 'main' in Python Scripts
The __name__ == "__main__" construct in Python is a common pattern used to determine whether a Python script is being run as the main program or if it is being imported as a module into another script. This check is often used to control the execution of code that should only run when the script is executed directly.
We have two .py files.
File 1: sample.py
print('This is sample.py code')
def print_sample_text():
print('This is a sample text')
# __name__ is in-built variable
if __name__ == "__main__":
print('Sample.py is executed directly')
else:
print('Sample.py is imported')
print(f"Its name is: {__name__}")
File 2: demo.py
import sample
sample.print_sample_text()
if __name__ == "__main__":
print('demo.py is executed directly')
else:
print('demo.py is imported')
print(f"Its name is: {__name__}")Now, if we run sample.py, output will be like:This is sample.py code Sample.py is executed directlyIf we run demo.py, output will be like:This is sample.py code Sample.py is imported Its name is: sample This is a sample text demo.py is executed directlyNow, notice the highlighted line. It should be executedonly when we are running sample.py. But it is getting executedwhile import. Lets move this to the if block.# print('This is sample.py code')
def print_sample_text():
print('This is a sample text')
# __name__ is in-built variable
if __name__ == "__main__":
print('Sample.py is executed directly')
print('This is sample.py code')
else:
print('Sample.py is imported')
print(f"Its name is: {__name__}")
Now, the output is:
Sample.py is imported
Its name is: sample
This is a sample text
demo.py is executed directlyRandom module and String module
Example 1:
import random,string
list_of_alphabets = [letter for letter in string.ascii_letters]
random.shuffle(list_of_alphabets)
print(list_of_alphabets)
Output:
['Y', 'M', 'b', 'F', 'X', 'r', 'm', 'J', 'w', 'o', 'Z', 'U', 'g', 'l', 'c', 'f', 'A', 'B', 'N', 'G', 'L', 'V', 'h', 'n', 'I', 'T', 'x', 'y', 'E', 'H', 'D', 'q', 'd', 'O', 't', 'R', 'S', 's', 'v', 'P', 'e', 'Q', 'k', 'p', 'i', 'W', 'K', 'C', 'j', 'z', 'a', 'u']
Example 2:
import random
import string
def generate_random_password(length=12):
if length < 8 or length > 16:
raise ValueError("Password length must be between 8 and 16 characters")
password = []
# Combine letters and symbols
list_of_chars = [letter for letter in string.ascii_letters]
list_of_symbols = [symbol for symbol in string.punctuation]
list_of_chars.extend(list_of_symbols)
# Shuffle the characters
random.shuffle(list_of_chars)
# Select characters for the password
for _ in range(length):
password.append(random.choice(list_of_chars))
return ''.join(password)
# Generate a random password of length between 8 and 16
random_password = generate_random_password(random.randint(8, 16))
print(random_password)Output:x#=K@_&p.D
Access and modify global variable
# Trying to change global variable
my_surname = 'Chakraborti'
def change_my_surname():
my_surname = 'Chakraborty'
print(f"My Surname before change: {my_surname}")
# Call change my surname function
change_my_surname()
print(f"My Surname after change: {my_surname}")
Output:My Surname before change: Chakraborti
My Surname after change: Chakraborti
The above code could not change the my_surname (global variable). Actually in the change_my_surname() function,
it is creating a local variable.This can be verified just writing a print statement.
# Access global variable
my_surname = 'Chakraborti'
def change_my_surname():my_surname = 'Chakraborty'
print(f"Changing surname to: {my_surname}")
print(f"My Surname before change: {my_surname}")
# Call change my surname function
change_my_surname()
print(f"My Surname after change: {my_surname}")Output:My Surname before change: Chakraborti Changing surname to: Chakraborty My Surname after change: ChakrabortiHowever, inside function, we can access the value.# Access global variable
my_surname = 'Chakraborti'
def change_my_surname():
print(f"Current Surname: {my_surname}")
change_my_surname()Output:Current Surname: ChakrabortiNow to change the global variable,# Change global variable
my_surname = 'Chakraborti'
def change_my_surname():
global my_surname
my_surname = 'Chakraborty'
print(f"Changing surname to: {my_surname}")
print(f"My Surname before change: {my_surname}")
# Call change my surname function
change_my_surname()
print(f"My Surname after change: {my_surname}")Output:My Surname before change: Chakraborti Changing surname to: Chakraborty My Surname after change: Chakraborty
Combine related information using zip function
Example 1:
# Example with three lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 22]
cities = ["New York", "San Francisco", "Los Angeles"]
# Using zip to combine the three lists
combined = zip(names, ages, cities)
# Converting the result to a list for printing
# Example with three lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 22]
cities = ["New York", "San Francisco", "Los Angeles"]
# Using zip to combine the three lists
combined = zip(names, ages, cities)
# Converting the result to a list for printing
result_list = list(combined)
# Output
print(result_list)
Output:[('Alice', 25, 'New York'), ('Bob', 30, 'San Francisco'), ('Charlie', 22, 'Los Angeles')]
Modified Example 1:
# Example with three lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 22]
cities = ["New York", "San Francisco", "Los Angeles"]
# Using zip to combine the three lists
combined = zip(names, ages, cities)
# Converting the result to a list for printing
# Example with three lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 22]
cities = ["New York", "San Francisco", "Los Angeles"]
# Using zip to combine the three lists
combined = zip(names, ages, cities)
for emp in combined:
print(f"Employee name: {emp[0]},Employee Age: {emp[1]} and Work location is {emp[2]}")Output:Employee name: Alice, Employee Age: 25 and Work location is New York Employee name: Bob, Employee Age: 30 and Work location is San Francisco Employee name: Charlie, Employee Age: 22 and Work location is Los Angeles
**kwargs to handle any number of keyword arguments
def my_grocery_list(**kwargs):
print(kwargs)
print(type(kwargs))
for item in kwargs:
print(f"{kwargs[item]} {item}")
my_grocery_list(toothpaste='Colgate',toothbrush='Colgate',
num_of_toothbrush=2)
Output:
{'toothpaste': 'Colgate', 'toothbrush': 'Colgate','num_of_toothbrush': 2}<class 'dict'> Colgate toothpaste Colgate toothbrush 2 num_of_toothbrush