<jupyter_start><jupyter_text>The Iris Dataset  IntroductionOriginally introduced by biologist and statitician <NAME> in 1936 at UCI Machine Learning Repository, this dataset is largely considered to be the Hello World of machine learning datasets. It is very popular in the field of teaching and is often used to introduce people to machine learning and visualization of datasets.In 1936 botanist <NAME> was studying the structural variation of three related species of Iris flowers. He collected 50 samples from each species making up 150 total. For each sample he measured the sepal and petal length and width.The three species of Iris flower collected were the _Iris setosa, Iris virginica and Iris versicolor_. ![image of an Iris flower depicting the petal and sepal length, width](./images/iris_petal_sepal.png) **The data set contains:*** 3 classes of 50 instances each (the class denoting the species of Iris)* Measurements of the sepal and petal, length and width in centimetres for every sampleIn this notebook I will do my best to explain the dataset itself and show/discuss how to write a supervised learning algorithm to separate the three classes of iris based on the their characteristics. The question that we want to answer is _"Can we predict the species of Iris flower using only measurements?_  Inspecting the DatasetOur first step is to load and inspect the dataset so we can gain a greater understanding about the layout and additionally to confirm everything above is true.Let's import the dataset as a Panda dataframe and look at all 150 entries.<jupyter_code># Import pandas for data processing
import pandas as pd

# Load the dataset
irisDataset = pd.read_csv("https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv")
# Display the 150 entries
irisDataset
print(irisDataset.shape)<jupyter_output>(150, 5)<jupyter_text>- - -Each row represents the sample and each column represents the features. The first four columns list the sepal and petal length and width in centimentres while the fifth column identifies the species. Sometimes you will see the rows and columns reffered to under different names, these are listed below for your utility:* A row is an observation, sample, example, instance, record* A column is a feature, predictor, attribute, independent variable, input, regressor, covariate- - - To verify that we do indeed have 50 samples of each species let's check that with a simple pandas function.<jupyter_code>irisDataset['species'].value_counts()<jupyter_output><empty_output><jupyter_text>Additionally let's check their types so we know what we will be handling.<jupyter_code># Check data type of each of the columns
irisDataset.dtypes<jupyter_output><empty_output><jupyter_text>- - -We can also see if there is any other information we need to know about with the `info` function.<jupyter_code>print(irisDataset.info())<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
sepal_length    150 non-null float64
sepal_width     150 non-null float64
petal_length    150 non-null float64
petal_width     150 non-null float64
species         150 non-null object
dtypes: float64(4), object(1)
memory usage: 5.9+ KB
None<jupyter_text>- - -Let's create a summary of each attribute of the dataset with the `describe` function. This way we can view the central tendency, dispersion and shape of a dataset’s distribution.<jupyter_code>irisDataset.describe()<jupyter_output><empty_output><jupyter_text>- - - Two minor functions to note but they still have great utility, are `head` and `tail`. These provide us with the ability to eyeball the dataset.<jupyter_code>print(irisDataset.head(20))
print(irisDataset.tail(20))<jupyter_output>sepal_length  sepal_width  petal_length  petal_width    species
130           7.4          2.8           6.1          1.9  virginica
131           7.9          3.8           6.4          2.0  virginica
132           6.4          2.8           5.6          2.2  virginica
133           6.3          2.8           5.1          1.5  virginica
134           6.1          2.6           5.6          1.4  virginica
135           7.7          3.0           6.1          2.3  virginica
136           6.3          3.4           5.6          2.4  virginica
137           6.4          3.1           5.5          1.8  virginica
138           6.0          3.0           4.8          1.8  virginica
139           6.9          3.1           5.4          2.1  virginica
140           6.7          3.1           5.6          2.4  virginica
141           6.9          3.1           5.1          2.3  virginica
142           5.8          2.7           5.1          1.9  virginica
143           6.8          3.2    [...]<jupyter_text>- - - The `sample` function chooses n number of random samples from the dataset and displays them.<jupyter_code>irisDataset.sample(10)<jupyter_output><empty_output><jupyter_text>Lastly, let's check if there are any null values in the dataset. There are none.<jupyter_code>irisDataset.isnull().sum()<jupyter_output><empty_output><jupyter_text>Visualizing the DatasetNow that we've inspected the dataset, I think visualizing it will provide an extra level of clarity. I believe that seeing the distributions helps identify non-obvious trends in data that is provided without visual aid.We need to import some packages to help us with this:* Seaborn: A Python data visualization library based on matplotlib. * Matplotlib: A Python 2D plotting library<jupyter_code># Data Visualization imports
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
import warnings # current version of seaborn generates a bunch of warnings that will be ignore
warnings.filterwarnings('ignore')
sns.set(style='darkgrid', color_codes=True)

%matplotlib inline
# Plot a coloured scatter plot 
sns.FacetGrid(irisDataset, hue = 'species', size=8) \
    .map(plt.scatter, 'sepal_length','sepal_width') \
    .add_legend()
plt.title("Sepal Width vs Sepal Length")
plt.show()<jupyter_output><empty_output><jupyter_text>Let's take another look back at `irisDataset.describe()`It should be easier to see now that, for example, when it comes to sepal width the majority of the values are in and around 3 - 3.3<jupyter_code>irisDataset.describe()<jupyter_output><empty_output><jupyter_text>- - -The pairplot is very useful as it shows the bivariate relation between each pair of features<jupyter_code># Set the default Seaborn theme
sns.set()
sns.pairplot(data = irisDataset, hue='species', size=3)
plt.show()<jupyter_output><empty_output><jupyter_text>Something to take away from these distributions is how the values for _virginica_ and _versicolor_ are more similarily aligned than that of _setosa_ Let's visualize this further with the use of another multivariate visualization technique pandas has known as parallel_coordinates, again we see the trend clearly where _setosa_ typically has a shorter petal length and the petal width of the other two species generally appears to be longer.<jupyter_code># Parallel coordinates plot each feature on a separate column & then draws lines
# connecting the features for each data sample
from pandas.tools.plotting import parallel_coordinates
parallel_coordinates(irisDataset, "species")
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.06183456183456183, 'fraction_numerical': 0.03125853125853126, 'mean_word_length': 3.497851442602824, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '402737', 'license': 'MIT', 'n_tokens_mistral': 2169, 'n_tokens_neox': 2025, 'n_words': 873, 'path': 'iris-dataset.ipynb', 'repo_name': 'mattshiel/emerging-technologies', 'size': '7341'}