Skip to content
Snippets Groups Projects
Commit 630a28ed authored by wa2-alaaiddin's avatar wa2-alaaiddin :speech_balloon:
Browse files

Task 1

parent 163f5560
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# UFCFVQ-15-M Programming for Data Science # UFCFVQ-15-M Programming for Data Science
# Programming Task 1 # Programming Task 1
## Student Id: 23003188 ## Student Id: 23003188
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.1 - Find the arithmetic mean ### Requirement FR1.1 - Find the arithmetic mean
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Create a variable called 'TaskoneDat' and open the 'task1.dat' file in 'read' mode #Create a variable called 'TaskoneDat' and open the 'task1.dat' file in 'read' mode
TaskoneDat = open('task1.dat','r') TaskoneDat = open('task1.dat','r')
#Read the data from the file #Read the data from the file
TaskoneDat = TaskoneDat.read() TaskoneDat = TaskoneDat.read()
#Remove newline characters and create a list from the data #Remove newline characters and create a list from the data
ConvertToList = list(TaskoneDat.strip().split()) ConvertToList = list(TaskoneDat.strip().split())
#Convert all elements in the list to integers #Convert all elements in the list to integers
TaskoneDat = list(map(int, ConvertToList)) TaskoneDat = list(map(int, ConvertToList))
#Define a function to find the mean of a given list #Define a function to find the mean of a given list
def meanFinder(List): def meanFinder(List):
# Assign the global variable 'ListMean' (as it has been called in FR1.7) # Assign the global variable 'ListMean' (as it has been called in FR1.7)
global ListMean global ListMean
#Calculate the mean of the list using the mathematical mean equation #Calculate the mean of the list using the mathematical mean equation
ListMean = sum(List)/len(List) ListMean = sum(List)/len(List)
#Return the result #Return the result
return ListMean return ListMean
# Call the function and pass the list as an argument # Call the function and pass the list as an argument
print(f'The mean of the dataset is {meanFinder(TaskoneDat)}') print(f'The Arithmetic Mean is {meanFinder(TaskoneDat)}')
``` ```
%% Output %% Output
The mean of the dataset is 120.89453125 The Arithmetic Mean is 120.89453125
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.2 - Find the standard deviation ### Requirement FR1.2 - Find the standard deviation
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Define a function to find the standard deviation of a given list #Define a function to find the standard deviation of a given list
def StdDevFinder(List): def StdDevFinder(List):
#Find the variance among the list using its mathematical equation #Find the variance among the list using its mathematical equation
# (Square each deviation from the mean & Calculate the variance) # (Square each deviation from the mean & Calculate the variance)
StdVariance = sum((DataInList - ListMean)**2 for DataInList in List) / len(List) StdVariance = sum((DataInList - ListMean)**2 for DataInList in List) / len(List)
STD_DEV = StdVariance ** 0.5 STD_DEV = StdVariance ** 0.5
#Return the result #Return the result
return STD_DEV return STD_DEV
#Call the function and pass the list as an argument #Call the function and pass the list as an argument
print(f'Standard Devision of the dataset is {StdDevFinder(TaskoneDat)}') print(f'The Standard Devision is {StdDevFinder(TaskoneDat)}')
``` ```
%% Output %% Output
Standard Devision of the dataset is 31.95179590820272 The Standard Devision is 31.95179590820272
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.3 - Find the min/max values ### Requirement FR1.3 - Find the min/max values
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Define a function to find the minimum value in a list #Define a function to find the minimum value in a list
def MinFinder(List): def MinFinder(List):
# Find the minimum value in the list # Find the minimum value in the list
ListMin = min(List) ListMin = min(List)
return ListMin return ListMin
#Define a function to find the maximum value in a list #Define a function to find the maximum value in a list
def MaxFinder(List): def MaxFinder(List):
# Find the maximum value in the list # Find the maximum value in the list
ListMax = max(List) ListMax = max(List)
return ListMax return ListMax
#Call the functions and pass the list as an argument #Call the functions and pass the list as an argument
print(f'The minimum number in the dataset is {MinFinder(TaskoneDat)}') print(f'The minimum number is {MinFinder(TaskoneDat)}')
print(f'The maximum number in the dataset is {MaxFinder(TaskoneDat)}') print(f'The maximum number is {MaxFinder(TaskoneDat)}')
``` ```
%% Output %% Output
The minimum number in the dataset is 0 The minimum number is 0
The maximum number in the dataset is 199 The maximum number is 199
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
#### Percentile Function #### Percentile Function
Creating Percentile Function to be used for FR1.4 to FR1.7 Creating Percentile Function to be used for FR1.4 to FR1.7
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#A function has been created to calculate percentiles within a list #A function has been created to calculate percentiles within a list
#The function takes two arguments: 1) data- the list of data. 2) percentile - the percentile number to calculate #The function takes two arguments: 1) data- the list of data. 2) percentile - the percentile number to calculate
def percentileFinder(List,percentile): def percentileFinder(List,percentile):
# Find the length of the list # Find the length of the list
ListNumber = len(List) ListNumber = len(List)
# Calculate the desired percentile using the equation: # Calculate the desired percentile using the equation:
# (length of list * percentile) / 100 # (length of list * percentile) / 100
Listpercentile = ListNumber * percentile / 100 Listpercentile = ListNumber * percentile / 100
# If the calculated index is an integer, sort the data and return the value at that index # If the calculated index is an integer, sort the data and return the value at that index
if Listpercentile.is_integer(): if Listpercentile.is_integer():
Listpercentile = sorted(List)[int(Listpercentile)] Listpercentile = sorted(List)[int(Listpercentile)]
return Listpercentile return Listpercentile
#else, remove it from (ListPercentile list) #else, remove it from (ListPercentile list)
else: else:
Listpercentile = sorted(List)[int(round(Listpercentile)) -1] Listpercentile = sorted(List)[int(round(Listpercentile)) -1]
return Listpercentile return Listpercentile
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.4 - Find the 25th percentile ### Requirement FR1.4 - Find the 25th percentile
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Calculate the 25th percentile of the data #Calculate the 25th percentile of the data
percentileOf_25 = percentileFinder(TaskoneDat,25) percentileOf_25 = percentileFinder(TaskoneDat,25)
#Print the result #Print the result
print(f'The 25 percentile in the dataset is {percentileOf_25}') print(f'The 25th percentile is {percentileOf_25}')
``` ```
%% Output %% Output
The 25 percentile in the dataset is 99 The 25th percentile is 99
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.5 - Find the 50th percentile ### Requirement FR1.5 - Find the 50th percentile
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Calculate the 50th percentile of the data #Calculate the 50th percentile of the data
percentileOf_50 = percentileFinder(TaskoneDat,50) percentileOf_50 = percentileFinder(TaskoneDat,50)
#Print the result #Print the result
print(f'The 50 percentile in the dataset is {percentileOf_50}') print(f'The 50th percentile is {percentileOf_50}')
``` ```
%% Output %% Output
The 50 percentile in the dataset is 117 The 50th percentile is 117
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.6 - Find the 75th percentile ### Requirement FR1.6 - Find the 75th percentile
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Calculate the 75th percentile of the data #Calculate the 75th percentile of the data
percentileOf_75 = percentileFinder(TaskoneDat,75) percentileOf_75 = percentileFinder(TaskoneDat,75)
#Print the result #Print the result
print(f'The 75 percentile in the dataset is {percentileOf_75}') print(f'The 75th percentile is {percentileOf_75}')
``` ```
%% Output %% Output
The 75 percentile in the dataset is 141 The 75th percentile is 141
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.7 - Print the set of summary statistics in tabular form ### Requirement FR1.7 - Print the set of summary statistics in tabular form
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Create a dictionary that contains all the needed summary statistics #Create a dictionary that contains all the needed summary statistics
TabularDic = { TabularDic = {
'Count':len(TaskoneDat), 'Count':len(TaskoneDat),
'Mean':round(ListMean,3), 'Mean':round(ListMean,3),
'Std':round(StdDevFinder(TaskoneDat),3), 'Std':round(StdDevFinder(TaskoneDat),3),
'Minimum':min(TaskoneDat), 'Minimum':min(TaskoneDat),
'25%':percentileOf_25, '25%':percentileOf_25,
'50%':percentileOf_50, '50%':percentileOf_50,
'70%':percentileOf_75, '70%':percentileOf_75,
'Maximum':max(TaskoneDat) 'Maximum':max(TaskoneDat)
} }
#Printing out the result #Printing out the result
print('Summary Statistics\n') print('Summary Statistics\n')
#Iterate through the dictionary and print the definition and variables #Iterate through the dictionary and print the definition and variables
for definition, variables in TabularDic.items(): for definition, variables in TabularDic.items():
print(f'{definition: <30}{variables}') print(f'{definition: <30}{variables}')
``` ```
%% Output %% Output
Summary Statistics Summary Statistics
Count 768 Count 768
Mean 120.895 Mean 120.895
Std 31.952 Std 31.952
Minimum 0 Minimum 0
25% 99 25% 99
50% 117 50% 117
70% 141 70% 141
Maximum 199 Maximum 199
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.8 - Read data from a file into memory ### Requirement FR1.8 - Read data from a file into memory
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Open the 'task1.dat' file in 'read' mode and assign the data to the variable 'TaskOneDat' #Open the 'task1.dat' file in 'read' mode and assign the data to the variable 'TaskOneDat'
TaskOneDat = open('task1.dat','r') TaskOneDat = open('task1.dat','r')
#Reading the data of the file. #Reading the data of the file.
TaskOneDat = TaskOneDat.read() TaskOneDat = TaskOneDat.read()
#At this point, the data is a string #At this point, the data is a string
print(f'[+] The data at this point is {type(TaskOneDat)}') print(f'[+] The data at this point is {type(TaskOneDat)}')
#Removing the \n and making it as list #Removing the \n and making it as list
ConvertToList = list(TaskOneDat.strip().split()) ConvertToList = list(TaskOneDat.strip().split())
#The type is (TaskOneDat) at this point but each item is (string) inside the list is e.g['148', '85', '183'] #The type is (TaskOneDat) at this point but each item is (string) inside the list is e.g['148', '85', '183']
print(f'[+] The items inside {type(ConvertToList)} is {type(ConvertToList[0])} | Now its a list of string') print(f'[+] The items inside {type(ConvertToList)} is {type(ConvertToList[0])} | Now its a list of string')
#Converting all string numbers to (integer) #Converting all string numbers to (integer)
TaskOneDat = list(map(int, ConvertToList)) TaskOneDat = list(map(int, ConvertToList))
#Now all numbers are integer niside the TaskOneDat e.g [148, 85, 183] #Now all numbers are integer niside the TaskOneDat e.g [148, 85, 183]
print(f'[+] The items inside {type(TaskOneDat)} is {type(TaskOneDat[0])} | Now its a list of integer\n') print(f'[+] The items inside {type(TaskOneDat)} is {type(TaskOneDat[0])} | Now its a list of integer\n')
print(f'[+] The data inside task1.dat is as shown\n\n{TaskOneDat}') print(f'[+] The data inside task1.dat is as shown\n\n{TaskOneDat}')
``` ```
%% Output %% Output
[+] The data at this point is <class 'str'> [+] The data at this point is <class 'str'>
[+] The items inside <class 'list'> is <class 'str'> | Now its a list of string [+] The items inside <class 'list'> is <class 'str'> | Now its a list of string
[+] The items inside <class 'list'> is <class 'int'> | Now its a list of integer [+] The items inside <class 'list'> is <class 'int'> | Now its a list of integer
[+] The data inside task1.dat is as shown [+] The data inside task1.dat is as shown
[148, 85, 183, 89, 137, 116, 78, 115, 197, 125, 110, 168, 139, 189, 166, 100, 118, 107, 103, 115, 126, 99, 196, 119, 143, 125, 147, 97, 145, 117, 109, 158, 88, 92, 122, 103, 138, 102, 90, 111, 180, 133, 106, 171, 159, 180, 146, 71, 103, 105, 103, 101, 88, 176, 150, 73, 187, 100, 146, 105, 84, 133, 44, 141, 114, 99, 109, 109, 95, 146, 100, 139, 126, 129, 79, 0, 62, 95, 131, 112, 113, 74, 83, 101, 137, 110, 106, 100, 136, 107, 80, 123, 81, 134, 142, 144, 92, 71, 93, 122, 163, 151, 125, 81, 85, 126, 96, 144, 83, 95, 171, 155, 89, 76, 160, 146, 124, 78, 97, 99, 162, 111, 107, 132, 113, 88, 120, 118, 117, 105, 173, 122, 170, 84, 96, 125, 100, 93, 129, 105, 128, 106, 108, 108, 154, 102, 57, 106, 147, 90, 136, 114, 156, 153, 188, 152, 99, 109, 88, 163, 151, 102, 114, 100, 131, 104, 148, 120, 110, 111, 102, 134, 87, 79, 75, 179, 85, 129, 143, 130, 87, 119, 0, 73, 141, 194, 181, 128, 109, 139, 111, 123, 159, 135, 85, 158, 105, 107, 109, 148, 113, 138, 108, 99, 103, 111, 196, 162, 96, 184, 81, 147, 179, 140, 112, 151, 109, 125, 85, 112, 177, 158, 119, 142, 100, 87, 101, 162, 197, 117, 142, 134, 79, 122, 74, 171, 181, 179, 164, 104, 91, 91, 139, 119, 146, 184, 122, 165, 124, 111, 106, 129, 90, 86, 92, 113, 111, 114, 193, 155, 191, 141, 95, 142, 123, 96, 138, 128, 102, 146, 101, 108, 122, 71, 106, 100, 106, 104, 114, 108, 146, 129, 133, 161, 108, 136, 155, 119, 96, 108, 78, 107, 128, 128, 161, 151, 146, 126, 100, 112, 167, 144, 77, 115, 150, 120, 161, 137, 128, 124, 80, 106, 155, 113, 109, 112, 99, 182, 115, 194, 129, 112, 124, 152, 112, 157, 122, 179, 102, 105, 118, 87, 180, 106, 95, 165, 117, 115, 152, 178, 130, 95, 0, 122, 95, 126, 139, 116, 99, 0, 92, 137, 61, 90, 90, 165, 125, 129, 88, 196, 189, 158, 103, 146, 147, 99, 124, 101, 81, 133, 173, 118, 84, 105, 122, 140, 98, 87, 156, 93, 107, 105, 109, 90, 125, 119, 116, 105, 144, 100, 100, 166, 131, 116, 158, 127, 96, 131, 82, 193, 95, 137, 136, 72, 168, 123, 115, 101, 197, 172, 102, 112, 143, 143, 138, 173, 97, 144, 83, 129, 119, 94, 102, 115, 151, 184, 94, 181, 135, 95, 99, 89, 80, 139, 90, 141, 140, 147, 97, 107, 189, 83, 117, 108, 117, 180, 100, 95, 104, 120, 82, 134, 91, 119, 100, 175, 135, 86, 148, 134, 120, 71, 74, 88, 115, 124, 74, 97, 120, 154, 144, 137, 119, 136, 114, 137, 105, 114, 126, 132, 158, 123, 85, 84, 145, 135, 139, 173, 99, 194, 83, 89, 99, 125, 80, 166, 110, 81, 195, 154, 117, 84, 0, 94, 96, 75, 180, 130, 84, 120, 84, 139, 91, 91, 99, 163, 145, 125, 76, 129, 68, 124, 114, 130, 125, 87, 97, 116, 117, 111, 122, 107, 86, 91, 77, 132, 105, 57, 127, 129, 100, 128, 90, 84, 88, 186, 187, 131, 164, 189, 116, 84, 114, 88, 84, 124, 97, 110, 103, 85, 125, 198, 87, 99, 91, 95, 99, 92, 154, 121, 78, 130, 111, 98, 143, 119, 108, 118, 133, 197, 151, 109, 121, 100, 124, 93, 143, 103, 176, 73, 111, 112, 132, 82, 123, 188, 67, 89, 173, 109, 108, 96, 124, 150, 183, 124, 181, 92, 152, 111, 106, 174, 168, 105, 138, 106, 117, 68, 112, 119, 112, 92, 183, 94, 108, 90, 125, 132, 128, 94, 114, 102, 111, 128, 92, 104, 104, 94, 97, 100, 102, 128, 147, 90, 103, 157, 167, 179, 136, 107, 91, 117, 123, 120, 106, 155, 101, 120, 127, 80, 162, 199, 167, 145, 115, 112, 145, 111, 98, 154, 165, 99, 68, 123, 91, 195, 156, 93, 121, 101, 56, 162, 95, 125, 136, 129, 130, 107, 140, 144, 107, 158, 121, 129, 90, 142, 169, 99, 127, 118, 122, 125, 168, 129, 110, 80, 115, 127, 164, 93, 158, 126, 129, 134, 102, 187, 173, 94, 108, 97, 83, 114, 149, 117, 111, 112, 116, 141, 175, 92, 130, 120, 174, 106, 105, 95, 126, 65, 99, 102, 120, 102, 109, 140, 153, 100, 147, 81, 187, 162, 136, 121, 108, 181, 154, 128, 137, 123, 106, 190, 88, 170, 89, 101, 122, 121, 126, 93] [148, 85, 183, 89, 137, 116, 78, 115, 197, 125, 110, 168, 139, 189, 166, 100, 118, 107, 103, 115, 126, 99, 196, 119, 143, 125, 147, 97, 145, 117, 109, 158, 88, 92, 122, 103, 138, 102, 90, 111, 180, 133, 106, 171, 159, 180, 146, 71, 103, 105, 103, 101, 88, 176, 150, 73, 187, 100, 146, 105, 84, 133, 44, 141, 114, 99, 109, 109, 95, 146, 100, 139, 126, 129, 79, 0, 62, 95, 131, 112, 113, 74, 83, 101, 137, 110, 106, 100, 136, 107, 80, 123, 81, 134, 142, 144, 92, 71, 93, 122, 163, 151, 125, 81, 85, 126, 96, 144, 83, 95, 171, 155, 89, 76, 160, 146, 124, 78, 97, 99, 162, 111, 107, 132, 113, 88, 120, 118, 117, 105, 173, 122, 170, 84, 96, 125, 100, 93, 129, 105, 128, 106, 108, 108, 154, 102, 57, 106, 147, 90, 136, 114, 156, 153, 188, 152, 99, 109, 88, 163, 151, 102, 114, 100, 131, 104, 148, 120, 110, 111, 102, 134, 87, 79, 75, 179, 85, 129, 143, 130, 87, 119, 0, 73, 141, 194, 181, 128, 109, 139, 111, 123, 159, 135, 85, 158, 105, 107, 109, 148, 113, 138, 108, 99, 103, 111, 196, 162, 96, 184, 81, 147, 179, 140, 112, 151, 109, 125, 85, 112, 177, 158, 119, 142, 100, 87, 101, 162, 197, 117, 142, 134, 79, 122, 74, 171, 181, 179, 164, 104, 91, 91, 139, 119, 146, 184, 122, 165, 124, 111, 106, 129, 90, 86, 92, 113, 111, 114, 193, 155, 191, 141, 95, 142, 123, 96, 138, 128, 102, 146, 101, 108, 122, 71, 106, 100, 106, 104, 114, 108, 146, 129, 133, 161, 108, 136, 155, 119, 96, 108, 78, 107, 128, 128, 161, 151, 146, 126, 100, 112, 167, 144, 77, 115, 150, 120, 161, 137, 128, 124, 80, 106, 155, 113, 109, 112, 99, 182, 115, 194, 129, 112, 124, 152, 112, 157, 122, 179, 102, 105, 118, 87, 180, 106, 95, 165, 117, 115, 152, 178, 130, 95, 0, 122, 95, 126, 139, 116, 99, 0, 92, 137, 61, 90, 90, 165, 125, 129, 88, 196, 189, 158, 103, 146, 147, 99, 124, 101, 81, 133, 173, 118, 84, 105, 122, 140, 98, 87, 156, 93, 107, 105, 109, 90, 125, 119, 116, 105, 144, 100, 100, 166, 131, 116, 158, 127, 96, 131, 82, 193, 95, 137, 136, 72, 168, 123, 115, 101, 197, 172, 102, 112, 143, 143, 138, 173, 97, 144, 83, 129, 119, 94, 102, 115, 151, 184, 94, 181, 135, 95, 99, 89, 80, 139, 90, 141, 140, 147, 97, 107, 189, 83, 117, 108, 117, 180, 100, 95, 104, 120, 82, 134, 91, 119, 100, 175, 135, 86, 148, 134, 120, 71, 74, 88, 115, 124, 74, 97, 120, 154, 144, 137, 119, 136, 114, 137, 105, 114, 126, 132, 158, 123, 85, 84, 145, 135, 139, 173, 99, 194, 83, 89, 99, 125, 80, 166, 110, 81, 195, 154, 117, 84, 0, 94, 96, 75, 180, 130, 84, 120, 84, 139, 91, 91, 99, 163, 145, 125, 76, 129, 68, 124, 114, 130, 125, 87, 97, 116, 117, 111, 122, 107, 86, 91, 77, 132, 105, 57, 127, 129, 100, 128, 90, 84, 88, 186, 187, 131, 164, 189, 116, 84, 114, 88, 84, 124, 97, 110, 103, 85, 125, 198, 87, 99, 91, 95, 99, 92, 154, 121, 78, 130, 111, 98, 143, 119, 108, 118, 133, 197, 151, 109, 121, 100, 124, 93, 143, 103, 176, 73, 111, 112, 132, 82, 123, 188, 67, 89, 173, 109, 108, 96, 124, 150, 183, 124, 181, 92, 152, 111, 106, 174, 168, 105, 138, 106, 117, 68, 112, 119, 112, 92, 183, 94, 108, 90, 125, 132, 128, 94, 114, 102, 111, 128, 92, 104, 104, 94, 97, 100, 102, 128, 147, 90, 103, 157, 167, 179, 136, 107, 91, 117, 123, 120, 106, 155, 101, 120, 127, 80, 162, 199, 167, 145, 115, 112, 145, 111, 98, 154, 165, 99, 68, 123, 91, 195, 156, 93, 121, 101, 56, 162, 95, 125, 136, 129, 130, 107, 140, 144, 107, 158, 121, 129, 90, 142, 169, 99, 127, 118, 122, 125, 168, 129, 110, 80, 115, 127, 164, 93, 158, 126, 129, 134, 102, 187, 173, 94, 108, 97, 83, 114, 149, 117, 111, 112, 116, 141, 175, 92, 130, 120, 174, 106, 105, 95, 126, 65, 99, 102, 120, 102, 109, 140, 153, 100, 147, 81, 187, 162, 136, 121, 108, 181, 154, 128, 137, 123, 106, 190, 88, 170, 89, 101, 122, 121, 126, 93]
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.9 - Design and build a data structure to store CSV data in memory ### Requirement FR1.9 - Design and build a data structure to store CSV data in memory
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
###The results are output based on appendix one example ###The results are output based on appendix one example
###For better visualization, only 5 results in each column are outputted ###For better visualization, only 5 results in each column are outputted
## ##
#Reading the CSV File #Reading the CSV File
CSVFile = 'task1.csv' CSVFile = 'task1.csv'
CSVFileTask1 = open(CSVFile,'r') CSVFileTask1 = open(CSVFile,'r')
EachLine = CSVFileTask1.readlines() EachLine = CSVFileTask1.readlines()
#Each header name will be saved inside this variable #Each header name will be saved inside this variable
CloumnName = EachLine[0].strip("\n").split(',') CloumnName = EachLine[0].strip("\n").split(',')
#Creating one empty dictionary and one empty list #Creating one empty dictionary and one empty list
Result = {} Result = {}
ListOfData = [] ListOfData = []
#View explanation 1 and 2 at the end #View explanation 1 and 2 at the end
for x in range(len(CloumnName)): for x in range(len(CloumnName)):
AllValues = [subList.strip("\n").split(',')[x] for subList in EachLine] AllValues = [subList.strip("\n").split(',')[x] for subList in EachLine]
test = AllValues[1:] test = AllValues[1:]
ListOfData.append(test) ListOfData.append(test)
#passing the key and value to a variable #passing the key and value to a variable
for columnNumber in range(len(CloumnName)): for columnNumber in range(len(CloumnName)):
keyNames = CloumnName[columnNumber] keyNames = CloumnName[columnNumber]
Result[keyNames] = ListOfData[columnNumber][:5] #In case to print all result remove the [:5] Result[keyNames] = ListOfData[columnNumber][:5] #In case to print all result remove the [:5]
# >> For better visualization, only 5 results in each column are outputted << # >> For better visualization, only 5 results in each column are outputted <<
#Print out the result #Print out the result
Result Result
``` ```
%% Output %% Output
{'Pregnancies': ['6', '1', '8', '1', '0'], {'Pregnancies': ['6', '1', '8', '1', '0'],
'Glucose': ['148', '85', '183', '89', '137'], 'Glucose': ['148', '85', '183', '89', '137'],
'BloodPressure': ['72', '66', '64', '66', '40'], 'BloodPressure': ['72', '66', '64', '66', '40'],
'SkinThickness': ['35', '29', '0', '23', '35'], 'SkinThickness': ['35', '29', '0', '23', '35'],
'Insulin': ['0', '0', '0', '94', '168'], 'Insulin': ['0', '0', '0', '94', '168'],
'BMI': ['33.6', '26.6', '23.3', '28.1', '43.1'], 'BMI': ['33.6', '26.6', '23.3', '28.1', '43.1'],
'DiabetesPedigreeFunction': ['0.627', '0.351', '0.672', '0.167', '2.288'], 'DiabetesPedigreeFunction': ['0.627', '0.351', '0.672', '0.167', '2.288'],
'Age': ['50', '31', '32', '21', '33'], 'Age': ['50', '31', '32', '21', '33'],
'Outcome': ['1', '0', '1', '0', '1']} 'Outcome': ['1', '0', '1', '0', '1']}
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.10 - Create and demonstrate a function to read CSV data from a file into memory ### Requirement FR1.10 - Create and demonstrate a function to read CSV data from a file into memory
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
###Following the given instruction in the appendix.A (output structure), this function has been created. ###Following the given instruction in the appendix.A (output structure), this function has been created.
##For better visualization, only 5 results in each column are outputted ##For better visualization, only 5 results in each column are outputted
#This function reads all columns from a csv file. #This function reads all columns from a csv file.
def read_csv_column(CSVFile): def read_csv_column(CSVFile):
# Creating one empty dictionary and one empty list # Creating one empty dictionary and one empty list
Result = {} Result = {}
ListOfData = [] ListOfData = []
# Read the CSV file # Read the CSV file
CSVFileTask1 = open(CSVFile,'r') CSVFileTask1 = open(CSVFile,'r')
# Read The CSV First Lines # Read The CSV First Lines
EachLine = CSVFileTask1.readlines() EachLine = CSVFileTask1.readlines()
# Each header name will be saved inside this variable # Each header name will be saved inside this variable
CloumnName = EachLine[0].strip("\n").split(',') CloumnName = EachLine[0].strip("\n").split(',')
#Explanation 1 and 2 #Explanation 1 and 2
for x in range(len(CloumnName)): for x in range(len(CloumnName)):
AllValues = [subList.strip("\n").split(',')[x] for subList in EachLine] AllValues = [subList.strip("\n").split(',')[x] for subList in EachLine]
test = AllValues[1:] test = AllValues[1:]
ListOfData.append(test) ListOfData.append(test)
for columnNumber in range(len(CloumnName)): for columnNumber in range(len(CloumnName)):
keyNames = CloumnName[columnNumber] keyNames = CloumnName[columnNumber]
Result[keyNames] = ListOfData[columnNumber][:5] #remove [:5] to print all result Result[keyNames] = ListOfData[columnNumber][:5] #remove [:5] to print all result
return Result return Result
##>>> For better visualization, only 5 results in each column are outputted <<< ##>>> For better visualization, only 5 results in each column are outputted <<<
SavedInMemory = read_csv_column(CSVFile) SavedInMemory = read_csv_column(CSVFile)
SavedInMemory SavedInMemory
``` ```
%% Output %% Output
{'Pregnancies': ['6', '1', '8', '1', '0'], {'Pregnancies': ['6', '1', '8', '1', '0'],
'Glucose': ['148', '85', '183', '89', '137'], 'Glucose': ['148', '85', '183', '89', '137'],
'BloodPressure': ['72', '66', '64', '66', '40'], 'BloodPressure': ['72', '66', '64', '66', '40'],
'SkinThickness': ['35', '29', '0', '23', '35'], 'SkinThickness': ['35', '29', '0', '23', '35'],
'Insulin': ['0', '0', '0', '94', '168'], 'Insulin': ['0', '0', '0', '94', '168'],
'BMI': ['33.6', '26.6', '23.3', '28.1', '43.1'], 'BMI': ['33.6', '26.6', '23.3', '28.1', '43.1'],
'DiabetesPedigreeFunction': ['0.627', '0.351', '0.672', '0.167', '2.288'], 'DiabetesPedigreeFunction': ['0.627', '0.351', '0.672', '0.167', '2.288'],
'Age': ['50', '31', '32', '21', '33'], 'Age': ['50', '31', '32', '21', '33'],
'Outcome': ['1', '0', '1', '0', '1']} 'Outcome': ['1', '0', '1', '0', '1']}
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.11 - Create and demonstrate a generic statistical summary function ### Requirement FR1.11 - Create and demonstrate a generic statistical summary function
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#function to create a statistics table #function to create a statistics table
def statisticsTable(items): def statisticsTable(items):
#The key names #The key names
stats = {'stats': ['Mean', 'stdev', 'Min', 'Max', '25th', '50th', '75th']} stats = {'stats': ['Mean', 'stdev', 'Min', 'Max', '25th', '50th', '75th']}
#For loop to sort the items (key,value) #For loop to sort the items (key,value)
for name, data in items.items(): for name, data in items.items():
# values contain string entries so parse them to the appropriate types # values contain string entries so parse them to the appropriate types
data = [ data = [
float(EachItem) if (len(EachItem.split('.'))) float(EachItem) if (len(EachItem.split('.')))
else int(EachItem) if EachItem.isnumeric() else int(EachItem) if EachItem.isnumeric()
else 0 for EachItem in data else 0 for EachItem in data
] ]
#To get the result, stats have the [key] value and apply each function over ecah line of data #To get the result, stats have the [key] value and apply each function over ecah line of data
stats[name] = [ stats[name] = [
round(meanFinder(data),3), round(meanFinder(data),3),
round(StdDevFinder(data),3), round(StdDevFinder(data),3),
MinFinder(data),MaxFinder(data), MinFinder(data),MaxFinder(data),
percentileFinder(data,25), percentileFinder(data,25),
percentileFinder(data,50), percentileFinder(data,50),
percentileFinder(data,75) percentileFinder(data,75)
] ]
#return the result #return the result
return stats return stats
#save the result to the memory #save the result to the memory
statisticsToMemory = statisticsTable(SavedInMemory) statisticsToMemory = statisticsTable(SavedInMemory)
#Print out the result #Print out the result
statisticsToMemory statisticsToMemory
``` ```
%% Output %% Output
{'stats': ['Mean', 'stdev', 'Min', 'Max', '25th', '50th', '75th'], {'stats': ['Mean', 'stdev', 'Min', 'Max', '25th', '50th', '75th'],
'Pregnancies': [3.2, 3.187, 0.0, 8.0, 0.0, 1.0, 6.0], 'Pregnancies': [3.2, 3.187, 0.0, 8.0, 0.0, 1.0, 6.0],
'Glucose': [128.4, 37.082, 85.0, 183.0, 85.0, 89.0, 148.0], 'Glucose': [128.4, 37.082, 85.0, 183.0, 85.0, 89.0, 148.0],
'BloodPressure': [61.6, 11.128, 40.0, 72.0, 40.0, 64.0, 66.0], 'BloodPressure': [61.6, 11.128, 40.0, 72.0, 40.0, 64.0, 66.0],
'SkinThickness': [24.4, 12.986, 0.0, 35.0, 0.0, 23.0, 35.0], 'SkinThickness': [24.4, 12.986, 0.0, 35.0, 0.0, 23.0, 35.0],
'Insulin': [52.4, 68.31, 0.0, 168.0, 0.0, 0.0, 94.0], 'Insulin': [52.4, 68.31, 0.0, 168.0, 0.0, 0.0, 94.0],
'BMI': [30.94, 6.931, 23.3, 43.1, 23.3, 26.6, 33.6], 'BMI': [30.94, 6.931, 23.3, 43.1, 23.3, 26.6, 33.6],
'DiabetesPedigreeFunction': [0.821, 0.756, 0.167, 2.288, 0.167, 0.351, 0.672], 'DiabetesPedigreeFunction': [0.821, 0.756, 0.167, 2.288, 0.167, 0.351, 0.672],
'Age': [33.4, 9.351, 21.0, 50.0, 21.0, 31.0, 33.0], 'Age': [33.4, 9.351, 21.0, 50.0, 21.0, 31.0, 33.0],
'Outcome': [0.6, 0.49, 0.0, 1.0, 0.0, 0.0, 1.0]} 'Outcome': [0.6, 0.49, 0.0, 1.0, 0.0, 0.0, 1.0]}
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Requirement FR1.12 - Create and demonstrate a function to print a custom table ### Requirement FR1.12 - Create and demonstrate a function to print a custom table
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
''' '''
This function takes in two arguments: a dictionary of statistics and a padding value This function takes in two arguments: a dictionary of statistics and a padding value
The statistics dictionary has keys that are strings and values that are lists of strings The statistics dictionary has keys that are strings and values that are lists of strings
The padding value is an integer that determines the amount of space between the table columns The padding value is an integer that determines the amount of space between the table columns
The separate argument is a string that is used to separate the columns in the table The separate argument is a string that is used to separate the columns in the table
''' '''
def CustomStatisticsTable(stats, padding=1, separate='*'): def CustomStatisticsTable(stats, padding=1, separate='*'):
# Initialize an empty list to store all the data # Initialize an empty list to store all the data
AllData = [] AllData = []
# Iterate over the key-value pairs in the stats dictionary and append the key and value to AllData # Iterate over the key-value pairs in the stats dictionary and append the key and value to AllData
for names, data in stats.items(): for names, data in stats.items():
InOrder = [names] + data InOrder = [names] + data
AllData.append(InOrder) AllData.append(InOrder)
# Initialize an empty list to store the widths of each column in the table # Initialize an empty list to store the widths of each column in the table
TableData = [] TableData = []
# Calculate the maximum width of the elements in each list in AllData and append it to TableData # Calculate the maximum width of the elements in each list in AllData and append it to TableData
for ItemInCol in AllData: for ItemInCol in AllData:
max_width = max(len(str(EachItem)) for EachItem in ItemInCol) max_width = max(len(str(EachItem)) for EachItem in ItemInCol)
TableData.append(padding + max_width) TableData.append(padding + max_width)
# Generate the upper border of the table by concatenating the separate string the specified number of times for each column # Generate the upper border of the table by concatenating the separate string the specified number of times for each column
UpperBorder = " " * (TableData[0] + 1) UpperBorder = " " * (TableData[0] + 1)
for i in range(1, len(TableData)): for i in range(1, len(TableData)):
UpperBorder += separate * TableData[i] UpperBorder += separate * TableData[i]
# Add extra padding to the upper border # Add extra padding to the upper border
UpperBorder += separate * 10 UpperBorder += separate * 10
# Print the upper border # Print the upper border
print(UpperBorder) print(UpperBorder)
# Convert the rows in AllData to a list of lists, where each inner list represents a row in the table # Convert the rows in AllData to a list of lists, where each inner list represents a row in the table
rows_to_list = [] rows_to_list = []
for i in range(len(AllData[0])): for i in range(len(AllData[0])):
row = [] row = []
for item_in_col in AllData: for item_in_col in AllData:
row.append(item_in_col[i]) row.append(item_in_col[i])
rows_to_list.append(row) rows_to_list.append(row)
# Generate the lower border of the table by concatenating the separate string the specified number of times for each column # Generate the lower border of the table by concatenating the separate string the specified number of times for each column
lower_border = separate.join([separate*TableData[star] for star in range(len(TableData))]) + separate*2 lower_border = separate.join([separate*TableData[star] for star in range(len(TableData))]) + separate*2
# Iterate over the rows in rows_to_list and print each row # Iterate over the rows in rows_to_list and print each row
for RowNumber, Row in enumerate(rows_to_list): for RowNumber, Row in enumerate(rows_to_list):
if RowNumber==0: if RowNumber==0:
# Print the first row preceded by a space # Print the first row preceded by a space
print(" " + separate.join(str(Row[line]).center(TableData[line])for line in range(len(Row))) + separate) print(" " + separate.join(str(Row[line]).center(TableData[line])for line in range(len(Row))) + separate)
else: else:
# Print all other rows preceded by the separate string # Print all other rows preceded by the separate string
print(separate + separate.join(str(Row[star]).center(TableData[star])for star in range(len(Row)))+ separate) print(separate + separate.join(str(Row[star]).center(TableData[star])for star in range(len(Row)))+ separate)
if RowNumber == 0: if RowNumber == 0:
# Print the lower border after the first row # Print the lower border after the first row
print(lower_border) print(lower_border)
# Print the lower border after the last row # Print the lower border after the last row
print(lower_border) print(lower_border)
# Call the function and pass 'statisticsToMemory' value # Call the function and pass 'statisticsToMemory' value
CustomStatisticsTable(statisticsToMemory) CustomStatisticsTable(statisticsToMemory)
``` ```
%% Output %% Output
*************************************************************************************************************** ***************************************************************************************************************
stats *Pregnancies *Glucose *BloodPressure *SkinThickness *Insulin * BMI * DiabetesPedigreeFunction* Age *Outcome * stats *Pregnancies *Glucose *BloodPressure *SkinThickness *Insulin * BMI * DiabetesPedigreeFunction* Age *Outcome *
********************************************************************************************************************** **********************************************************************************************************************
* Mean * 3.2 * 128.4 * 61.6 * 24.4 * 52.4 *30.94 * 0.821 * 33.4 * 0.6 * * Mean * 3.2 * 128.4 * 61.6 * 24.4 * 52.4 *30.94 * 0.821 * 33.4 * 0.6 *
*stdev * 3.187 * 37.082 * 11.128 * 12.986 * 68.31 *6.931 * 0.756 *9.351 * 0.49 * *stdev * 3.187 * 37.082 * 11.128 * 12.986 * 68.31 *6.931 * 0.756 *9.351 * 0.49 *
* Min * 0.0 * 85.0 * 40.0 * 0.0 * 0.0 * 23.3 * 0.167 * 21.0 * 0.0 * * Min * 0.0 * 85.0 * 40.0 * 0.0 * 0.0 * 23.3 * 0.167 * 21.0 * 0.0 *
* Max * 8.0 * 183.0 * 72.0 * 35.0 * 168.0 * 43.1 * 2.288 * 50.0 * 1.0 * * Max * 8.0 * 183.0 * 72.0 * 35.0 * 168.0 * 43.1 * 2.288 * 50.0 * 1.0 *
* 25th * 0.0 * 85.0 * 40.0 * 0.0 * 0.0 * 23.3 * 0.167 * 21.0 * 0.0 * * 25th * 0.0 * 85.0 * 40.0 * 0.0 * 0.0 * 23.3 * 0.167 * 21.0 * 0.0 *
* 50th * 1.0 * 89.0 * 64.0 * 23.0 * 0.0 * 26.6 * 0.351 * 31.0 * 0.0 * * 50th * 1.0 * 89.0 * 64.0 * 23.0 * 0.0 * 26.6 * 0.351 * 31.0 * 0.0 *
* 75th * 6.0 * 148.0 * 66.0 * 35.0 * 94.0 * 33.6 * 0.672 * 33.0 * 1.0 * * 75th * 6.0 * 148.0 * 66.0 * 35.0 * 94.0 * 33.6 * 0.672 * 33.0 * 1.0 *
********************************************************************************************************************** **********************************************************************************************************************
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Process Development Report for Task 1 # Process Development Report for Task 1
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### 1) Explanation ### 1) Explanation
#### From tasks 1.1 to 1.7 #### From tasks 1.1 to 1.7
- The questions in these tasks can be solved using mathematical equations, utilizing pre-built functions in Python. These tasks are straightforward and have been solved using the task1.dot file. - The questions in these tasks can be solved using mathematical equations, utilizing pre-built functions in Python. These tasks are straightforward and have been solved using the task1.dot file.
##### From task 1.9 and onwards ##### From task 1.9 and onwards
- Explanation 1 - Explanation 1
In this task, the data is structured in the following way: In this task, the data is structured in the following way:
['A','B','C'], ['A','B','C'],
['1','2','3'], ['1','2','3'],
['4','5','6'], ['4','5','6'],
and so on... and so on...
As a result, the variable 'ListOfData' will have data in the following shape: [['A','1','4'..],[['B','2','5'..]]..] As a result, the variable 'ListOfData' will have data in the following shape: [['A','1','4'..],[['B','2','5'..]]..]
- Explanation 2 - Explanation 2
A for loop is created to access every single data element in 'ListOfData', ranging from 0 to 769 (or 768 if we start counting from 0). The loop starts at [0][0] and continues to [768][0], then moves on to [0][1] and so on until it reaches the last data element at [768][8]. As the loop progresses, the data is appended to a new list called 'ListOfData', as explained in Explanation 1. A for loop is created to access every single data element in 'ListOfData', ranging from 0 to 769 (or 768 if we start counting from 0). The loop starts at [0][0] and continues to [768][0], then moves on to [0][1] and so on until it reaches the last data element at [768][8]. As the loop progresses, the data is appended to a new list called 'ListOfData', as explained in Explanation 1.
### 2) Strength ### 2) Strength
- Some of the functions can be reused in different phases, and the tasks are interconnected, allowing results from one task to be used in another without the need to rewrite the entire code. - Some of the functions can be reused in different phases, and the tasks are interconnected, allowing results from one task to be used in another without the need to rewrite the entire code.
### 3) Weaknesses ### 3) Weaknesses
- One weakness of the code is that it heavily relies on pre-built Python functions and does not make use of libraries such as CSV and Pandas, which could potentially make the code shorter and more efficient. - One weakness of the code is that it heavily relies on pre-built Python functions and does not make use of libraries such as CSV and Pandas, which could potentially make the code shorter and more efficient.
### 4) Improvement Points ### 4) Improvement Points
- Any Python program can be improved and written in fewer lines. The custom table can be improved and created with a more efficient algorithm and better formatting. The tasks from 1.1 to 1.7 can be updated to be solved using pure Python, without the use of pre-built functions. - Any Python program can be improved and written in fewer lines. The custom table can be improved and created with a more efficient algorithm and better formatting. The tasks from 1.1 to 1.7 can be updated to be solved using pure Python, without the use of pre-built functions.
### 5) Alternative ### 5) Alternative
- Some of the mathematical equations, such as standard deviation, can be solved using alternative equations. Instead of using pre-built functions such as 'sum' and 'len', a for loop can be used to achieve the same result. The custom table can also be created using different shapes, such as (+) or (dots) instead of (*). - Some of the mathematical equations, such as standard deviation, can be solved using alternative equations. Instead of using pre-built functions such as 'sum' and 'len', a for loop can be used to achieve the same result. The custom table can also be created using different shapes, such as (+) or (dots) instead of (*).
### 6) Algorithm (FR.1.10 to 1.12) ### 6) Algorithm (FR.1.10 to 1.12)
- The first function, read_csv_column, reads in a CSV file and stores the data in a dictionary with the column names as keys and the column values as values. The second function, statisticsTable, takes in the dictionary from the first function and calculates various statistical measures (mean, standard deviation, minimum, maximum, 25th percentile, 50th percentile, and 75th percentile) for each column. The third function, CustomStatisticsTable, takes in the dictionary from the second function and generates a table of the statistical measures with each column aligned and separated by a specified character. The fourth function, meanFinder, calculates the mean of a list of numerical values. The fifth function, StdDevFinder, calculates the standard deviation of a list of numerical values. The sixth function, MinFinder, finds the minimum value in a list of numerical values. The seventh function, MaxFinder, finds the maximum value in a list of numerical values. The eighth function, percentileFinder, calculates the specified percentile of a list of numerical values. - The first function, read_csv_column, reads in a CSV file and stores the data in a dictionary with the column names as keys and the column values as values. The second function, statisticsTable, takes in the dictionary from the first function and calculates various statistical measures (mean, standard deviation, minimum, maximum, 25th percentile, 50th percentile, and 75th percentile) for each column. The third function, CustomStatisticsTable, takes in the dictionary from the second function and generates a table of the statistical measures with each column aligned and separated by a specified character. The fourth function, meanFinder, calculates the mean of a list of numerical values. The fifth function, StdDevFinder, calculates the standard deviation of a list of numerical values. The sixth function, MinFinder, finds the minimum value in a list of numerical values. The seventh function, MaxFinder, finds the maximum value in a list of numerical values. The eighth function, percentileFinder, calculates the specified percentile of a list of numerical values.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
##### MARK: % ##### MARK: %
#### FEEDBACK: #### FEEDBACK:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment