SVM in Python

In this post:

1. About SVM

As SVM (Support Vector Machine) like algorithm is good documented, we will not discuss in current material SVM theory, we will start directly presenting a little bit dataset that we will use with SVM, and then using effectively SVM. Nevertheless, for some more details about SVM algorithm we can check it here.

To exemplify classification using SVM in Python we will use wine dataset from scikit-learn (sklearn) module sklearn package have many datasets that can be used in tests (iris, wine, files, digits, reast_cancer, diabetes, linnerud, sample_image, sample_images, svmlight_file, svmlight_files )

2. Things about dataset used

a) To load wine dataset we will use load_wine method:

# import section

from sklearn import datasets

#load wine data set

ds_wine=datasets.load_wine()


b) Let's see some things about wine dataset. Any phython dataset is characterized by features and targets (label name). For wine: 

#check features of dataset

print("Features: ", ds_wine.feature_names)

# print wine type (i.e labels )

print("Labels: ", ds_wine.target_names)


#output:

Features:  ['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 

'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']

Labels:  ['class_0' 'class_1' 'class_2']

We see wine features means: 'alcohol', 'malic_acid', 'ash', etc. Wine labels (or targets, or types ) means 'class_0', 'class_1', 'class_2'


Dataset has 178 samples. Our SVM classification from this example will classify wines. 

c) Let's print first 2 records of our wine dataset:

print(ds_wine.data[0:2])


#output

[[1.423e+01 1.710e+00 2.430e+00 1.560e+01 1.270e+02 2.800e+00 3.060e+00

  2.800e-01 2.290e+00 5.640e+00 1.040e+00 3.920e+00 1.065e+03]

 [1.320e+01 1.780e+00 2.140e+00 1.120e+01 1.000e+02 2.650e+00 2.760e+00

  2.600e-01 1.280e+00 4.380e+00 1.050e+00 3.400e+00 1.050e+03]]

We observe comparing with output from a) for the first record 

alcohol=1.423e+01

malic_acid=1.710e+00

ash=2.430e+00

etc

In general, to determine how many records are in datasets and how many features each record has we use the shape method:

#shape of the dataset

print(ds_wine.data.shape)

#output

(178, 13)

This means ds_win dataset has 178 records, and as we see each one has 13 features.


3. Applying SVM classification to dataset

Now that we see what wine dataset looks like, we will apply SVM classification to it. 

Like in any machine learning algorithm we will need part for data for training the model, and another part for testing it.

3.1. Train and test dataset

For the SVM model we will choose train and test dataset from ds_wine initial dataset,using train_test_split method.

# Import train_test_split function

from sklearn.model_selection import train_test_split

# split ds_wine

dsx_train, dsx_test, dsy_train, dsy_test = train_test_split(ds_wine.data, ds_wine.target, test_size=0.15,random_state=109) # 85% training and 15% test

print(dsx_train[0:2])

print(dsy_train[0:2])

#output:

[[1.279e+01 2.670e+00 2.480e+00 2.200e+01 1.120e+02 1.480e+00 1.360e+00

  2.400e-01 1.260e+00 1.080e+01 4.800e-01 1.470e+00 4.800e+02]

 [1.438e+01 1.870e+00 2.380e+00 1.200e+01 1.020e+02 3.300e+00 3.640e+00

  2.900e-01 2.960e+00 7.500e+00 1.200e+00 3.000e+00 1.547e+03]]

[2 0]

Above we printed the first two records from train dataset, referring to dsy_train we see target for first record is 2, i.e. 'class_2' label, and the second record have target 0, i.e. 'class_0' label.


3.2. Create SVM classifier

To generate SVM model, we will create first SVM classifier object using SVC method:

from sklearn import svm

myclassifier = svm.SVC(kernel='linear')

We used method SVC (letters come from Support Vector Classification), method have many parameters, we used only kernel, a linear kernel. Kernel can also be 'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'.


3.3. Train and test SVM model

To train the model use "fit" method with train dataset then to test classification, use "predict" method with test dataset:

#train model with fit method using our dsx_train dataset

myclassifier.fit(dsx_train, dsy_train)

dsy_pred = myclassifier.predict(dsx_test)

#output: 

[0 0 1 2 0 1 0 0 1 0 2 1 2 2 0 1 1 0 0 1 2 1 0 2 0 0 1]


To understand more intuitive, we will take a record from dataset, and predict in which target it is, let's take first record from dsx_test it looks like: 

print(dsx_test[0])

#output

[1.330e+01 1.720e+00 2.140e+00 1.700e+01 9.400e+01 2.400e+00 2.190e+00

 2.700e-01 1.350e+00 3.950e+00 1.020e+00 2.770e+00 1.285e+03]

and appropriate value (target) in reality is dsy_test[0]

print(dsy_test[0])

#output:

0

Predicted target for dsx_test[0] is:

dsy_pred_0=myclassifier.predict([dsx_test[0]])

print(dsy_pred_0)

#output:

[0]

We see predicted value dsy_pred_0 is for this record the same with real value dsy_test[0].


4. SVM model accuracy

To evaluate accuracy for entire test dataset we use accuracy_score method:

from sklearn import metrics

print("SVM Accuracy:",metrics.accuracy_score(dsy_test, dsy_pred))

#output:

SVM Accuracy: 0.9259259259259259

Precision is good, it is about 92%


5. Full code sample 

#import section

from sklearn import datasets

from sklearn.model_selection import train_test_split

from sklearn import svm

from sklearn import metrics


#load wine data set

ds_wine=datasets.load_wine()

#check features of dataset

print("Features: ", ds_wine.feature_names)

# print wine type (i.e labels )

print("Labels: ", ds_wine.target_names)

#print first 2 records of our wind dataset

print(ds_wine.data[0:2])

#shape of the dataset

print(ds_wine.data.shape)

# split ds_wine

dsx_train, dsx_test, dsy_train, dsy_test = train_test_split(ds_wine.data, ds_wine.target, test_size=0.15,random_state=109) # 85% training and 15% test

print(dsx_train[0:2])

print(dsy_train[0:2])

# Generate SVM model, creating first SVM classifier object

myclassifier = svm.SVC(kernel='linear') # Linear Kernel

#train model with fit method using our X_train dataset

myclassifier.fit(dsx_train, dsy_train)

#make prediction for test dataset X_test

dsy_pred = myclassifier.predict(dsx_test)

print(dsy_pred)

print(dsx_test[0])

print(dsy_test[0])

dsy_pred_0=myclassifier.predict([dsx_test[0]])

print(dsy_pred_0)

print("SVM Accuracy:",metrics.accuracy_score(dsy_test, dsy_pred))

Create dataframe in Pandas

One of the simple modes to create dataframe in Python, pandas is to create it from a dictionary. Below example create a dataframe from dictionary.

import pandas as pd

dict1 = {

    'Ford': [120, 230, 120, 431],

    'Renault': [320, 233, 547, 622],

    'Audi': [230, 123, 457, 232],

    'Toyota': [230, 123, 457, 232],

    'Opel': [230, 123, 457, 232]

}

print(dict1.keys())

print("Ford key is:", end=' ')

print(dict1['Ford'])

sells = pd.DataFrame(dict1) # create sells dataframe from 'dict1' dictionary

print('DataFrame is:')

print(sells)


#output:

dict_keys(['Ford', 'Renault', 'Audi', 'Toyota', 'Opel'])

Ford key is: [120, 230, 120, 431]

DataFrame is:

   Ford  Renault  Audi  Toyota  Opel

0   120      320   230     230   230

1   230      233   123     123   123

2   120      547   457     457   457

3   431      622   232     232   232

Comments about above code: "dict1" dictionary contain situation with car sales for a machine dealer, for first 4 month of the year.

Dictionary keys are 'Ford', 'Renault' 'Audi' 'Toyota' 'Opel'.

Dictionary values are lists, means for 'Ford' key value is list [120, 230, 120, 431].

Recalling from dictionaries theory print(dict1.keys()), which will show: 

dict_keys(['Ford', 'Renault', 'Audi', 'Toyota', 'Opel'])

and print(dict1['Ford']) will show [120, 230, 120, 431].

And finally, method that create sells dataframe from dictionary is: sells = pd.DataFrame(dict1).


There is a possibility to create dataframe from dictionary using method from_dict of class DataFrame, which works similar like in previous example, but it has more options.

Example: 

import pandas as pd

dict2 = {

    'candy':['80%', '60%', '45%'],

    'chocolate':['12%', '24%', '7%'],

    'wafer':['14%', '18%', '16%']

}


sells2=pd.DataFrame.from_dict(dict2)

print(sells2)


#output: 

  candy chocolate wafer

0   80%       12%   14%

1   60%       24%   18%

2   45%        7%   16%

We see using DataFrame.from_dict specifying only dictionary from which we create dataframe, it will create a dataframe in which keys become dataframe columns.


Using from_dict with parameter orient='index' will create a dataframe in which keys are first values in row like below example: 

import pandas as pd

dict2 = {

    'candy':['80%', '60%', '45%'],

    'chocolate':['12%', '24%', '7%'],

    'wafer':['14%', '18%', '16%']

}


sells2i=pd.DataFrame.from_dict(dict2, orient='index')

print(sells2i)


#output:

                   0       1       2

candy         80%  60%  45%

chocolate  12%   24%   7%

wafer         14%   18%  16%


Creating dataframe from a list of tuples. 

This can be achieved using method DataFrame.from_records

Example: 

import pandas as pd

marks = [('Mike', 9), ('Debora', 10), ('Steve', 9), ('Tim', 8)]

marks_df = pd.DataFrame.from_records(marks, columns=['Student', 'Mark'])


#Output:

      Student  Mark

0    Mike         9

1    Debora    10

2    Steve        9

3    Tim           8


Other example for dataframe from list of tuples with more elements: 

import pandas as pd

marks = [('Mike', 9, 8), ('Debora', 10, 9), ('Steve', 9, 10), ('Tim', 8, 9)]

marks_df = pd.DataFrame.from_records(marks, columns=['Student', 'Mark1','Mark2'])

print(marks_df)


#output:

  Student     Mark1  Mark2

0    Mike       9         8

1   Debora    10       9

2   Steve        9        10

3   Tim           8        9


from_records can be used similar to create dataframe from a list of dictionaries,

Example:

import pandas as pd

marks = [{'Student':'Mike' , 'Mark':9},

               {'Student':'Debora' , 'Mark':10},

       {'Student':'Steve' , 'Mark':9},

       {'Student':'Tim' , 'Mark':8}

        ]

marks_df1 = pd.DataFrame.from_records(marks)

print(marks_df1)


#Output

      Student   Mark

0    Mike         9

1    Debora    10

2    Steve        9

3    Tim           8


We can create dataframe from numpy array

Example:

import pandas as pd

import numpy as np

data = np.array([('Student','Mark'),('Mike', 9), ('Debora', '10'), ('Steve', 9), ('Tim', 8)])

marks_df2= pd.DataFrame.from_records(data)

print(marks_df2)


#output:

         0            1

0     Student  Mark

1     Mike         9

2     Debora    10

3     Steve        9

4     Tim           8

Strings in Python

To create a string variable, enclose characters with " " or ' ' 

Example:

string1 = "This is Python string 1"

string2 = 'This is Python string 2'

print(string1)

print(string2)


#output: 

This is Python string 1

This is Python string 2


This is when defining strings on a single line. There exists a possibility to define a string that spread on multiple lines using triple double quotes or triple single quotes i.e. """ or '''. 

Example: 

string_m = """Today is Monday and 

the sky is perfect clear"""


To understand the way to access elements in a string we start from analogy that Python strings are like a list of characters, hence elements can be accessed using index, negative index or even slicing notation. Exist also __getitem__() method which is a little bit similar with accessing using index. 


Example using index: 

mystr = "Today is Monday"

print(mystr[0]) 

print(mystr[1]) 


#output: 

T

o


Example using negative index:

mystr = "Today is Monday"

print(mystr[-1])

print(mystr[-3])


#output: 

Y

d

We observe that negativ index "count back" from the end of the string elements.


Example using slicing notation: 

mystr = "Today is Monday"

print(mystr[0:2]) 

print(mystr[1:5]) 


#output: 

To

oday

We observe that in slicing it count till "right slice value -1" means mystr[0:2] will show mystr[0], mystr[1] but will not show mystr[2]


Example using __getitem__()

mystr = "Today is Monday"

print(mystr.__getitem__(0))


#output

T


String comparison

It is performed with == operator

example: 

s1="alfa"

s2="Alfa"

s3="alfa"

if(s1==s2):

    print("s1 is equal with s2")

else:

    print("s1 is not equal with s2")

#

if(s1==s3):

    print("s1 is equal with s3")

else:

    print("s1 is not equal with s3")


#output: 

s1 is not equal with s2

s1 is equal with s3

We observe that == with strings is case sensitive.


The other way to compare strings is using __eq__() or __ne__()

Example: 

s1="alfa"

s2="Alfa"

s3="alfa"

print(s1.__eq__(s2))

print(s1.__eq__(s3))

print(s1.__ne__(s2))


#output:

False

True

True

Thus method __eq__() return True if strings are equal, while __ne__() return True if strings are not equal. Basically == operator automatically call __eq__() method.


Concatenating or joining strings

Strings can be concatenated using "+"  operator

Example: 

s1 = "Alfa"

s2 = "Beta"

print(s1+s2)


#output:

AlfaBeta

locals() and globals() in Python

Python globals() function

Method globals() return a dictionary which contains global environment variables used by interpretor for the program.

Example: 

print(globals())


#output

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000024C64E14850>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\Stefan\\builtin1\\main.py', '__cached__': None}



Or writing each key:value of dictionary in a single line, example:

d_globals = globals()

for key in d_globals.copy():

    print(f"{key}: {d_globals[key]}")

#output

__name__: __main__

__doc__: None

__package__: None

__loader__: <_frozen_importlib_external.SourceFileLoader object at 0x000001FFF0B44850>

__spec__: None

__annotations__: {}

__builtins__: <module 'builtins' (built-in)>

__file__: C:\Users\Stefan\builtin1\main.py

__cached__: None



Python locals() function

Method locals(), return a dictionary which contains all environment variables (key: value) related to program local scope. 

Example:

print(locals())


#output

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001449C894850>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\Stefan\\builtin1\\main.py', '__cached__': None}


Or writing each key:value of dictionary in a single line, example:

d_locals = locals()

for key in d_locals.copy():

    print(f"{key}: {d_locals[key]}")


#output

__name__: __main__

__doc__: None

__package__: None

__loader__: <_frozen_importlib_external.SourceFileLoader object at 0x000001EFDCAF4850>

__spec__: None

__annotations__: {}

__builtins__: <module 'builtins' (built-in)>

__file__: C:\Users\Stefan\builtin1\main.py

__cached__: None


If we define a local variable in the program, it will appear in locals() output.

Example in below with variable named month:

def aboutyear():

    month = 'May'

    print(locals())

    print(locals()['month'])


print(aboutyear())


#output: 

{'month': 'May'}

May

We see in this case printing locals() inside function aboutyear will print only one key:value  for the variable month defined inside (or local) in the function itself.


We can change values for a key from locals() or globals(). Below is an example of doing this with a key from globals():

year=2023

def aboutmonth():

    month = 'May'


print(globals())

globals()['year']=2022

print(globals())


#output: 

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000023389FB4850>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\Stefan\\builtin1\\main.py', '__cached__': None, 'year': 2023, 'aboutmonth': <function aboutmonth at 0x0000023389EF3E20>}


{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000023389FB4850>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\Stefan\\builtin1\\main.py', '__cached__': None, 'year': 2022, 'aboutmonth': <function aboutmonth at 0x0000023389EF3E20>}


We see first print(globals()) will contain global variable year with value 2023, but it will not print local variable month which is inside function aboutmonth

Then we change global variable year to 2022 using globals()['year']=2022

Hence second print(globals()) will contain global variable year with value 2022

Python match

Python match compares the value of an expression with patterns given in case blocks, when match exist value from that case block is returned, or command from that case block is executed. 

Example:

brand = input('Please enter car brand: ')

def discount_level(brand):

    match brand.upper():

        case 'FORD':

            return 0.1

        case 'RENAULT':

            return 0.05

        case 'BMW':

            return 0.08

        case _:

            return 0.03

print(f"Discount for {brand.upper()} is {discount_level(brand)} ")


#output sample

Please enter car brand: Renault

Discount for RENAULT is 0.05

Here we compare or match brand string (with capital, means brand.upper()  ) with patterns from case (FORD, RENAULT, BMW ). Anything else that is different than FORD, RENAULT, BMW will match the last case i.e. block "case _:". Character "_" it is like a wildcard.


In case block we can have one command or more commands, case block is "delimited" bassically according with indentation. Thus, in previous example, I modify a little bit and in case 'FORD' block I put at same indentation level two commands, for example now there is: 

brand = input('Please enter car brand: ')

def discount_level(brand):

    match brand.upper():

        case 'FORD':

            print('Based on the brand')

            return 0.1

        case 'RENAULT':

            return 0.05

        case 'BMW':

            return 0.08

        case _:

            return 0.03

print(f"Discount for {brand.upper()} is {discount_level(brand)} ")


#sample output for above:

Please enter car brand: Ford

Based on the brand

Discount for FORD is 0.1 


In the previous sample it matches brand with one of value from case statement. Nevertheless, in case statement we can have multiple values. For example, if we want to give a discount of 10% (i.e. 0.1) for brands: Ford, Skoda, Opel we can use "|" operator and example become: 

brand = input('Please enter car brand: ')

def discount_level(brand):

    match brand.upper():

        case 'FORD'|'SKODA'|'OPEL':

            return 0.1

        case 'RENAULT':

            return 0.05

        case 'BMW':

            return 0.08

        case _:

            return 0.03

print(f"Discount for {brand.upper()} is {discount_level(brand)} ")


#sample output for above:

Please enter car brand: Opel

Discount for OPEL is 0.1 


In examples till now we compared brand, i.e. a string, similar is working if we compare numbers, or even bool, but match statement can compare more complex structures. For classes or objects an example is: 

class CarFeature:

    numSpeed: int

    maxSpeed: int

    acc100: float

    def __init__(self, numSpeed, maxSpeed, acc100):

        self.numSpeed = numSpeed

        self.maxSpeed = maxSpeed

        self.acc100 = acc100


def car_q(carfeature):

    match carfeature:

        case CarFeature(numSpeed=6, maxSpeed = 250, acc100 = 9.9):

            print("High class car")

        case CarFeature(numSpeed=5, maxSpeed = 175, acc100 = 11.5):

            print("Entry level class car")

        case _:

            print("Middle level class car")


carfeature1 = CarFeature(6, 260, 9.8)

print(f"car 1 with numSpeed: {carfeature1.numSpeed}, maxSpeed: {carfeature1.maxSpeed}, acc100: {carfeature1.acc100} is")

car_q(carfeature1)


#Output of code: 

car 1 with numSpeed: 6, maxSpeed: 260, acc100: 9.8 is

Middle level class car

In this example we defined a class named CarFeature. Then we defined a function car_q that uses match statement which in this case compares or has in case "instances" of the CarFeature class. 

Then we created a carfeature1 instance of class CarFeature, and used carfeature1 to test car_q function.

This match example compares instances of classes or objects. Basically, match can compare any pattern that is according with pattern matching PEP 636 specifications.

Accessing API in Python

There are many internets API which offer data in json format. Such data can be easily used in python using python requests module. In the current post we will use requests python module toghether with Json format to find prognosed maximum temperature per day, for next 8 days based on openweathermap API. Documentation for requests module can be consulted in many links on internet, 

for example, here or in this site.

At the date of writing this short intro in accessing API and using output in JSON format, latest requests release can be found for example on community update link.

If not yet installed, python requests modul as usual can be installed via pip: 

python -m pip install requests

We will exemplify how to use requests and get JSON data for openweathermap.org API. 

openweathermap have many API, just checking on openweathermap website we will exemplify for "Current Weather Data" which have documentation at API doc 

Before doing something in Python for many of the presented endpoints we will need to get an API key, and understand API call. For API key, we need to create an account or profile on openweathermap.org site, after that in the profile it is a link where we can obtain an API key. This is easy, and let's presume we get it and now we have an API key.

For call current weather data API, based on documentation API call is 

https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}

In this URL:

  • endpoint is https://api.openweathermap.org/data/2.5/weather
  • parameters are:
  • lat for latitude
  • lon for longitude
  • appid is the API key discussed before
  • in  documentation exist other parameters like mode, units, lang

Parameters lat and lon can be obtained from internat, example from this site: https://www.latlong.net/, or from here https://www.gps-coordinates.net/, there are also some others. 

For lat 44.451209, lon 26.13391 and appid 70g04e4613056b159c2761a9d9e664d2 url for call is

https://api.openweathermap.org/data/2.5/onecall?lat=44.451209&lon=26.13391&appid=70g04e4613056b159c2761a9d9e664d2

Observation: appid is a fictive one here, you will need to obtain one from openweathermap site as mentioned prior. 

Loading it in browser we obtain:

Weather API In Browser

Figure 1: Weather API loaded In Browser

In this image it is a bunch of data, it looks difficult to use it effectively. Using python, we overcome this and we can extract or use data that we need. Simple call to this API using Python is in below code:

import requests

Weather_url = "https://api.openweathermap.org/data/2.5/onecall"

api_key = "70g04e4613056b159c2761a9d9e664d2"

weather_params = {

    "lat": 44.451209,

    "lon": 26.13391,

    "appid": api_key,

}

response = requests.get(Weather_url, params=weather_params)

We used get function from requests module, there is requests.get(.....)

Like parameters for get I used:

  • string Weather_url which is string with endpoint as mentioned in API doc
  • params which contain API parameters according with documentation. This "params" is a dictionary that contain parameters (lat, lon and appid ) means requests.get accept params like a dictionary with pairs key:value.

The output of the code is just "Process finished with exit code 0" and for the begining we can think it is not too useful. We can use supplimentary response.status_code it will give: 

print(response.status_code)

#output 

200

Here status_code  give well know response status code universal for any http request (example of other status code: 201, 401, 404 etc). For a complete list see: "List of HTTP status codes

In instruction: response = requests.get(Weather_url, params=weather_params)

response is an object, a class. If in GUI environment we just type response, intelisense will show a bunch of methods and variable for this class like below:  

Some methods from response module

Figure 2: Some methods from response module

Using response.json() will give in python output exact json data that we see in Figure 1, but this is displayed in a single line like:

{'lat': 44.4512, 'lon': 26.1339, 'timezone': 'Europe/Bucharest', 'timezone_offset': 10800.........text omitted ............ }

means:

Json output

Figure 3: Json output

This data still seems hard to analyze, however as we see there it seems similar with a dictionary, we can see structure of this in a Json viewer. 

There are many online Json viewers, I selected first Json data from Figure 1 using CTRL+A, press CTRL+C and then go to Json online https://jsonformatter.org/json-viewer viewer and press CTRL+V and there is:

Data In Json Viewer

Figure 4: Data in Json Viewer

We understand from here easy json structure where we see {} there is about dictionary, where is [] there is about list. 

Looking to Figure 4 if we need to access daily[0] list we will write

weather_1=response.json() # this is entire json data output

print(weather_1["daily"][0])

Expanding further there is: 

Maximum temperature for a day in Json output

Figure 5: Maximum temperature for a day in Json output

We see struture, hence for accessing daily max temperature for day 0 we will use 

weather_1=response.json() # this is entire json data output

print(weather_1["daily"][0]["temp"]["max"])

it will display 283.93 max temperature for daily[0]. 

Observation: above temperature is in Kelvin scale (to convert to celsius degtree we need to use "Kelvin value" - 273.15)


The code for find maximum temperature in next 8 days is:

import requests

Weather_Endpoint = "https://api.openweathermap.org/data/2.5/onecall"

api_key = "70g04e4613056b159c2761a9d9e664d2"

weather_params = {

    "lat": 44.451209,

    "lon": 26.13391,

    "appid": api_key,

}

response = requests.get(Weather_Endpoint, params=weather_params)

response.raise_for_status()

weather_1=response.json()

weather_2_daily = weather_1["daily"]

daily_max_temp=[]

for i in range(8):

    daily_max_temp.append(float(weather_2_daily[i]["temp"]["max"]))

    print(f"Maximum temperature in day {i} is {round(daily_max_temp[i]-273.15, 2)} Celsius degree")

print(f"Maximum daily temperature in next 8 days is {round(max(daily_max_temp)-273.15,2)} Celsius degree")


#output is: 

Maximum temperature in day 0 is 11.09 Celsius degree

Maximum temperature in day 1 is 14.41 Celsius degree

Maximum temperature in day 2 is 16.2 Celsius degree

Maximum temperature in day 3 is 17.99 Celsius degree

Maximum temperature in day 4 is 13.5 Celsius degree

Maximum temperature in day 5 is 13.01 Celsius degree

Maximum temperature in day 6 is 16.81 Celsius degree

Maximum temperature in day 7 is 16.82 Celsius degree

Maximum daily temperature in next 8 days is 17.99 Celsius degree

About the code: 

- weather_1 represent entire json output data

- weather_2_daily=weather_1["daily"] is a list based on Figure 4

- we defined an empty list with daily_max_temp=[]

- weather_2_daily[i]["temp"]["max"] is basicaly maximum daily temperature in day "i" in Kelvin degree.

Built in functions: next, bool

next(iterator)

Python built-in function next is used to retrieve next item from an iterator, if it reaches iterator end built-in exception StopIteration is raised. 

Example:

list1 = [23, True, 'yes']

myIterator = iter(list1)

#

item = next(myIterator)

print(f"First item is: {item}")

#

item = next(myIterator)

print(f"Item is: {item}")

#

item = next(myIterator)

print(f"Last item is: {item}")

item = next(myIterator)


#Output

First item is: 23

Item is: True

Last item is: yes

Traceback (most recent call last):

  File "test.py", line 9, in <module>

    item = next(myIterator)

StopIteration

In this example we create iterator myIterator from list1. Then we run next funtion trice using item = next(myIterator) and print item with a f string. myIterator have 3 items, after running trice next function we are at the end of it, once try to run the fourth time next function, StopIteration built-in exception is raised. 


class bool(x=False)

The method return a boolean value based on standard "truth testing procedure". Basically this procedure will return True if argument is a number (excepting 0), a string or True itself. It will return False if argument is False, 0 or None, empty. "Truth testing procedure" in python area is comprehensive described here


Examples:

myarg1=12

print(bool(myarg1))

# output: True


myarg2='string123'

print(bool(myarg2))

# output: True


myarg3=True

print(bool(myarg3))

# output: True


myarg4=False

print(bool(myarg4))

# output: False


myarg5=0

print(bool(myarg5))

# output: False


myarg6=None

print(bool(myarg6))

# output: False


print(bool())

# output: False

Built in functions: all, filter and slice

all(iterable)

Function accepts like argument an iterable structure (like list, tuple, dictionary, etc), function returns True if all elements of the iterable structure are true.

Example:

mylist1 = [1, 'two', 'xyz', 8.35, True]

mylist2 = [1, 'two', 'xyz', 8.35, 'yhg']

mylist3 = [1, 0, 'xyz', 8.35, 'test']

mylist4 = [1, 'tt', False, 8.35, 'test']


print(f'all(mylist1) give: {all(mylist1)}')

print(f'all(mylist2) give: {all(mylist2)}')

print(f'all(mylist3) give: {all(mylist3)}')

print(f'all(mylist4) give: {all(mylist4)}')


output: 

all(mylist1) give: True

all(mylist2) give: True

all(mylist3) give: False

all(mylist4) give: False

Here all(mylist1) and all(mylist2) return True because all elements of mylist1 and mylist2 are True (anything that is not False or 0 is considered true).

all(mylist3) return False because mylist3 contain 0 element. all(mylist4) return False because mylist4 contain False.


filter(function, iterable)

Python built-in filter function construct an itertor based on an iterable parameter like list, tuple, etc, taking from it only elements that fulfil function parameter condition. Description sounds a little bit complicated, but some examples show that filter function is simple. 

Let's presume we have list1 = [45, 12, 5, 7, 32, 20, 2, 18, 21, 9, 16]

We need to obtain from list1 a new list that should contain only numbers greater than 15. Code for this is:

list1 = [45, 12, 5, 7, 32, 20, 2, 18, 21, 9, 16]

# filter function for number greater than 15

def fg15(x):

    if x>15:

        return x

# apply filter function

result=filter(fg15, list1)

list2=list(result)

print(list2)

 

output:

[45, 32, 20, 18, 21, 16]

We observe here that list2 contains elements from list1 that are greater than 15 (which fulfil filter restriction).


class slice ([start], stop[, step]) 

Explanation of slice according with python documentation https://docs.python.org/3/library/functions.html#slice is a little bit complicated. 

Slice function returns a "slice object" representing a set of indices similar to range(start, stop, step). Step parameter is optional, if not specified it is 1. Start is optional, if it is not specified start is first element. It is easy to understand slice by examples:

list1 = (23, True, 5, 12, 'yes', 'cat', 'dog', 34)

slc1=slice(1,6,2)


print(slc1) # here slc1 is the slice objet

print(list1[slc1])

print(list1[1:6:2]) 


output: 

slice(1, 6, 2)

(True, 12, 'cat')

(True, 12, 'cat')


For

   The for statement iterates over a structure ("a sequence of something", list, tuple, set, dictionary, etc.)

A general syntax is like:

for ELEMENT in STRUCTURE:

statememn1

statement2

...


Example for iterating over a list:

mylist = [1, 'two', 'xyz', 8.35, True]

for element in mylist:

print(element)


#output

1

two

xyz

8.35

True


   We can use range() function in for to iterate over a sequence of numbers, or over a part of structure elements. For example, if we need to iterate/touch over first 2 elements:

mylist = [1, 'two', 'xyz', 8.35, True]

for i in range(2):

print(mylist[i])


#output

1

two

   General syntax for range function is range(start, stop, step=1), based on this we can iterate with other step different than 1, also iterate not only from the beginning of the structure but over a subset of elements, example:

mylist = [1, 'two', 'xyz', 8.35, True]

for i in range(1,3):

print(mylist[i])


#output

two

xyz

Here range function return values from start value till end value minus 1, i.e. range(1,3) give 1,2 values.

Tuples

   Tuples are python data structures similar to lists. A tuple is composed of values separated by commas and enclosed within parenthesis. Like comparison to remember that lists are enclosed in brackets.

Tuple example:

myTuple=('mnp', 5, 145.34, False, 'Blue sky')
print(myTuple)

#output
(False, 'Blue sky', 145.34, 5, 'mnp')


   Tuple elements are ordered and immutable (tuple is like a read-only list). Tuple elements are accessed similar like lists. Below are examples of accessing tuple elements:

myTuple=('mnp', 5, 145.34, False, 'Blue sky')


print(myTuple[1])     #accessing by index

#output

5


print(myTuple[2:4])     #accessing with slice notation

#output

(145.34, False)


print(myTuple[1:])     #accessing with slice notation

#output

(5, 145.34, False, 'Blue sky')


   Tuples elements are immutables (tuple is like a read-only list). If we try to modify an element from tuple similar like we do in lists case we will get an error. For example: 

myTuple = (5, 'test123', 23.54, False, 'xyz')

myTuple[0]=10


#output

Traceback (most recent call last):

  File "<pyshell#1>", line 1, in <module>

    myTuple[0]=10

TypeError: 'tuple' object does not support item assignment


   Even if tuple is immutable, a tuple can contain like elements a list, elements of which can be modified. For example:

tuple123 = (10, [12, 7.5, True], 34.54, 'abc')

tuple123[1][0]=11

print(tuple123)


#output

(10, [11, 7.5, True], 34.54, 'abc')

Here we see tuple123 contain like second element a list, i.e. [12, 7.5, True], means tuple123[1]= [12, 7.5, True]. There tuple123[1][0] access first element of list [12, 7.5, True]


In previous example we have a nested list in a tuple, or a tuple that contains elements like a list. 

Obvious we can have a tuple that contains other tuple(s) and so on..., nested tuples.