{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "id": "Q6ifg03dKPR4" }, "outputs": [], "source": [ "############################\n", "# BLOCK 1: IMPORTS\n", "############################\n", "\n", "# libraries!\n", "import numpy as np # numpy is Python's \"array\" library\n", "import pandas as pd # Pandas is Python's \"data\" library (\"dataframe\" == spreadsheet)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "0ghtg7ecRQ50" }, "outputs": [], "source": [ "#############################\n", "# BLOCK 2: VARIABLES LISTING\n", "#############################\n", "\n", "# for reference, as you work throughout, come back and list all the variable names\n", "# here along with what that variable holds\n", "\n", "# Variable: Contents\n", "# -------------------\n", "# [FILL IN VARS BELOW]\n", "#" ] }, { "cell_type": "code", "source": [ "####################################\n", "from sklearn.datasets import load_iris\n", "data = load_iris()\n", "df = pd.DataFrame(data.data, columns=data.feature_names)\n", "df" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 424 }, "id": "DjCaxH3BKJ_O", "outputId": "ab33e45d-d332-412e-db2a-88cc4c9528f4" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "0 5.1 3.5 1.4 0.2\n", "1 4.9 3.0 1.4 0.2\n", "2 4.7 3.2 1.3 0.2\n", "3 4.6 3.1 1.5 0.2\n", "4 5.0 3.6 1.4 0.2\n", ".. ... ... ... ...\n", "145 6.7 3.0 5.2 2.3\n", "146 6.3 2.5 5.0 1.9\n", "147 6.5 3.0 5.2 2.0\n", "148 6.2 3.4 5.4 2.3\n", "149 5.9 3.0 5.1 1.8\n", "\n", "[150 rows x 4 columns]" ], "text/html": [ "\n", "
\n", "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
45.03.61.40.2
...............
1456.73.05.22.3
1466.32.55.01.9
1476.53.05.22.0
1486.23.45.42.3
1495.93.05.11.8
\n", "

150 rows × 4 columns

\n", "
\n", "
\n", "\n", "
\n", " \n", "\n", " \n", "\n", " \n", "
\n", "\n", "\n", "
\n", " \n", " \n", " \n", "
\n", "\n", "
\n", "
\n" ], "application/vnd.google.colaboratory.intrinsic+json": { "type": "dataframe", "variable_name": "df", "summary": "{\n \"name\": \"df\",\n \"rows\": 150,\n \"fields\": [\n {\n \"column\": \"sepal length (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.8280661279778629,\n \"min\": 4.3,\n \"max\": 7.9,\n \"num_unique_values\": 35,\n \"samples\": [\n 6.2,\n 4.5,\n 5.6\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"sepal width (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.435866284936698,\n \"min\": 2.0,\n \"max\": 4.4,\n \"num_unique_values\": 23,\n \"samples\": [\n 2.3,\n 4.0,\n 3.5\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"petal length (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 1.7652982332594667,\n \"min\": 1.0,\n \"max\": 6.9,\n \"num_unique_values\": 43,\n \"samples\": [\n 6.7,\n 3.8,\n 3.7\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"petal width (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.7622376689603465,\n \"min\": 0.1,\n \"max\": 2.5,\n \"num_unique_values\": 22,\n \"samples\": [\n 0.2,\n 1.2,\n 1.3\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" } }, "metadata": {}, "execution_count": 9 } ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ANJhDRNPKPR5" }, "outputs": [], "source": [ "#############################\n", "# BLOCK 3: READING DATA\n", "#############################\n", "\n", "# let's read in our flower data...\n", "#\n", "#filename = 'iris.csv'\n", "#df = pd.read_csv(filename, header=0) # encoding=\"latin1\" et al.\n", "#print(f\"{filename}: file read into a pandas DataFrame.\")\n", "#df.head()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "8v3oVZYTKPR6", "colab": { "base_uri": "https://localhost:8080/", "height": 361 }, "outputId": "4110ac58-5c52-4cbf-a83f-16d9a7189ccb" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "0 5.1 3.5 1.4 0.2\n", "1 4.9 3.0 1.4 0.2\n", "2 4.7 3.2 1.3 0.2\n", "3 4.6 3.1 1.5 0.2\n", ".. ... ... ... ...\n", "146 6.3 2.5 5.0 1.9\n", "147 6.5 3.0 5.2 2.0\n", "148 6.2 3.4 5.4 2.3\n", "149 5.9 3.0 5.1 1.8\n", "\n", "[150 rows x 4 columns]" ], "text/html": [ "\n", "
\n", "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
05.13.51.40.2
14.93.01.40.2
24.73.21.30.2
34.63.11.50.2
...............
1466.32.55.01.9
1476.53.05.22.0
1486.23.45.42.3
1495.93.05.11.8
\n", "

150 rows × 4 columns

\n", "
\n", "
\n", "\n", "
\n", " \n", "\n", " \n", "\n", " \n", "
\n", "\n", "\n", "
\n", " \n", " \n", " \n", "
\n", "\n", "
\n", "
\n" ], "application/vnd.google.colaboratory.intrinsic+json": { "type": "dataframe", "variable_name": "df", "summary": "{\n \"name\": \"df\",\n \"rows\": 150,\n \"fields\": [\n {\n \"column\": \"sepal length (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.8280661279778629,\n \"min\": 4.3,\n \"max\": 7.9,\n \"num_unique_values\": 35,\n \"samples\": [\n 6.2,\n 4.5,\n 5.6\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"sepal width (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.435866284936698,\n \"min\": 2.0,\n \"max\": 4.4,\n \"num_unique_values\": 23,\n \"samples\": [\n 2.3,\n 4.0,\n 3.5\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"petal length (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 1.7652982332594667,\n \"min\": 1.0,\n \"max\": 6.9,\n \"num_unique_values\": 43,\n \"samples\": [\n 6.7,\n 3.8,\n 3.7\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"petal width (cm)\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.7622376689603465,\n \"min\": 0.1,\n \"max\": 2.5,\n \"num_unique_values\": 22,\n \"samples\": [\n 0.2,\n 1.2,\n 1.3\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" } }, "metadata": {}, "execution_count": 10 } ], "source": [ "#############################\n", "# BLOCK 4: SETTING OPTIONS\n", "#############################\n", "\n", "#\n", "# a dataframe is a \"spreadsheet in Python\"\n", "# (this one seems to have an extra column!)\n", "#\n", "pd.set_option('display.max_rows', 8) # None for no limit; default: 10\n", "pd.set_option('display.min_rows', 8) # None for no limit; default: 10\n", "# let's view it!\n", "df" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "aksGQcJ8KPR6", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "4cbdedf5-cabe-4263-c06c-26bbb8f509b1" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "\n", "RangeIndex: 150 entries, 0 to 149\n", "Data columns (total 4 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 sepal length (cm) 150 non-null float64\n", " 1 sepal width (cm) 150 non-null float64\n", " 2 petal length (cm) 150 non-null float64\n", " 3 petal width (cm) 150 non-null float64\n", "dtypes: float64(4)\n", "memory usage: 4.8 KB\n" ] } ], "source": [ "##############################\n", "# BLOCK 5: USING DF'S .info()\n", "##############################\n", "\n", "#\n", "# let's look at our pandas DataFrame's info (Aargh: that extra column!)\n", "#\n", "df.info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ADWpUqeKKPR7", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "76ac8d2f-0d98-4721-e0f2-b79b48736b00" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "\n", "RangeIndex: 150 entries, 0 to 149\n", "Data columns (total 4 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 sepal length (cm) 150 non-null float64\n", " 1 sepal width (cm) 150 non-null float64\n", " 2 petal length (cm) 150 non-null float64\n", " 3 petal width (cm) 150 non-null float64\n", "dtypes: float64(4)\n", "memory usage: 4.8 KB\n" ] } ], "source": [ "#############################\n", "# BLOCK 6: CLEANING DATA\n", "#############################\n", "\n", "#\n", "# let's drop that last column (dropping is usually by _name_):\n", "#\n", "# if you want a list of the column names use df.columns\n", "#col5name = df.columns[5] # get column name at index 5\n", "\n", "df_clean = df # drop by name is typical, but what else is possible?\n", "df_clean.info() # Is the bad last column gone?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9RAydRsiKPR7", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "18ec37ec-3a95-4ef9-c111-847ac8f6ecec" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "FEATURES: Index(['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)',\n", " 'petal width (cm)'],\n", " dtype='object')\n", "\n", "First feature: sepal length (cm)\n", "\n", "feature_name_to_index: {'sepal length (cm)': 0, 'sepal width (cm)': 1, 'petal length (cm)': 2, 'petal width (cm)': 3}\n" ] } ], "source": [ "##############################\n", "# BLOCK 7: FEATURE NAMES DICT\n", "##############################\n", "\n", "#\n", "# let's keep our column names in variables, for reference;\n", "# in machine learning contexts, these are referred to as \"features\"\n", "#\n", "features = df_clean.columns # \"list\" of columns\n", "print(f\"FEATURES: {features}\\n\")\n", " # It's a \"pandas\" list, called an Index\n", " # use it just as a Python list of strings:\n", "print(f\"First feature: {features[0]}\\n\")\n", "\n", "# let's create a dictionary to look up any column index by name\n", "feature_name_to_index = {}\n", "for i, name in enumerate(features):\n", " feature_name_to_index[name] = i # using the name (as key), assign the value (i)\n", "print(f\"feature_name_to_index: {feature_name_to_index}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "PWkPTOGnKPR8", "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "outputId": "f6a46e8f-0169-4646-864f-1b3ed749f238" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "\n", "RangeIndex: 150 entries, 0 to 149\n", "Data columns (total 4 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 sepal length (cm) 150 non-null float64\n", " 1 sepal width (cm) 150 non-null float64\n", " 2 petal length (cm) 150 non-null float64\n", " 3 petal width (cm) 150 non-null float64\n", "dtypes: float64(4)\n", "memory usage: 4.8 KB\n", "======================================================================\n", " sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)\n", "0 5.1 3.5 1.4 0.2\n", "1 4.9 3.0 1.4 0.2\n", "2 4.7 3.2 1.3 0.2\n", "3 4.6 3.1 1.5 0.2\n", ".. ... ... ... ...\n", "146 6.3 2.5 5.0 1.9\n", "147 6.5 3.0 5.2 2.0\n", "148 6.2 3.4 5.4 2.3\n", "149 5.9 3.0 5.1 1.8\n", "\n", "[150 rows x 4 columns]\n", "======================================================================\n" ] }, { "output_type": "error", "ename": "KeyError", "evalue": "'irisname'", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36mget_loc\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 3804\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3805\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_engine\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_loc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcasted_key\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3806\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32mindex.pyx\u001b[0m in \u001b[0;36mpandas._libs.index.IndexEngine.get_loc\u001b[0;34m()\u001b[0m\n", "\u001b[0;32mindex.pyx\u001b[0m in \u001b[0;36mpandas._libs.index.IndexEngine.get_loc\u001b[0;34m()\u001b[0m\n", "\u001b[0;32mpandas/_libs/hashtable_class_helper.pxi\u001b[0m in \u001b[0;36mpandas._libs.hashtable.PyObjectHashTable.get_item\u001b[0;34m()\u001b[0m\n", "\u001b[0;32mpandas/_libs/hashtable_class_helper.pxi\u001b[0m in \u001b[0;36mpandas._libs.hashtable.PyObjectHashTable.get_item\u001b[0;34m()\u001b[0m\n", "\u001b[0;31mKeyError\u001b[0m: 'irisname'", "\nThe above exception was the direct cause of the following exception:\n", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/tmp/ipykernel_6512/325098609.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;31m# or more to the point, grab that column and inspect:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 18\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"Irisname entries: {df_clean['irisname'].unique()}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 19\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;31m# also note how the last two rows in the df have problems, among others...\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 4100\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcolumns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnlevels\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4101\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_getitem_multilevel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 4102\u001b[0;31m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcolumns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_loc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4103\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_integer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindexer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4104\u001b[0m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mindexer\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/local/lib/python3.12/dist-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36mget_loc\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 3810\u001b[0m ):\n\u001b[1;32m 3811\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mInvalidIndexError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3812\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3813\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3814\u001b[0m \u001b[0;31m# If we have a listlike key, _check_indexing_error will raise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mKeyError\u001b[0m: 'irisname'" ] } ], "source": [ "##############################\n", "# BLOCK 8: INSPECTING DATA\n", "##############################\n", "\n", "#\n", "# let's look at our cleaned-up dataframe...\n", "#\n", "df_clean.info()\n", "print('=' * 70)\n", "\n", "#\n", "# Notice that the non-null count is _different_ for irisname!\n", "# Why? Show a table and inspect...\n", "print(df_clean)\n", "print('=' * 70)\n", "\n", "# or more to the point, grab that column and inspect:\n", "print(f\"Irisname entries: {df_clean['irisname'].unique()}\")\n", "\n", "# also note how the last two rows in the df have problems, among others...\n" ] }, { "cell_type": "code", "source": [ "df.columns" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "4B2An3iML1ay", "outputId": "5492db65-acd8-4c11-f669-742a79b6cb62" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "Index(['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)',\n", " 'petal width (cm)'],\n", " dtype='object')" ] }, "metadata": {}, "execution_count": 19 } ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "xM22NWdqKPR-", "scrolled": false }, "outputs": [], "source": [ "##############################\n", "# BLOCK 9: USING DF'S dropna\n", "##############################\n", "\n", "#\n", "# typically, after dropping columns that we don't want,\n", "# we drop rows with missing data (other approaches are possible, too)\n", "#\n", "df_clean = df_clean.dropna() # this removes all rows with nan items\n", "df_clean.info()\n", "print('=' * 70)\n", "df_clean\n", "\n", "#\n", "# notice that _all_ of the rows now have 144 non-null items\n", "# also, the first and last rows (among others) aren't valid data...\n", "# we'll handle that next" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "h0spkxGzKPR-" }, "outputs": [], "source": [ "################################\n", "# BLOCK 10: REMOVING BOGUS DATA\n", "################################\n", "\n", "# or more to the point, grab that column and inspect:\n", "print(f\"Irisname entries: {df_clean['irisname'].unique()}\")\n", "print(df_clean['irisname'] == 'alieniris') # what does this show?\n", "print(df_clean['irisname'] != 'alieniris') # what does this show?\n", "\n", "# define a final version of the DataFrame by pulling out the\n", "# bad alieniris data (remember that you can pass a boolean\n", "# Series to select data that you want)\n", "df_final = pass\n", "# ^^^^ YOU NEED TO WRITE CODE HERE...\n", "\n", "print(df_final.shape)\n", "df_final" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "EywtvRyMKPR-" }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 11: CONVERT SPECIES NAME TO INDEX\n", "##########################################\n", "\n", "# all of scikit-learn's ML routines need numbers, not strings\n", "# ... even for categories/classifications (like species!)\n", "# so, we will convert the flower-species to numbers:\n", "\n", "species_names = df_final['irisname'].unique()\n", "species_name_to_index = { species_names[i]:i for i in range(len(species_names))}\n", "print(species_name_to_index)\n", "print(type(species_name_to_index))\n", "\n", "def convertSpecies(species_name: str) -> int:\n", " ''' return the species index (a unique integer/category) '''\n", " #print(f\"converting {species_name}...\")\n", " return species_name_to_index[species_name]\n", "\n", "# Let's try it out...\n", "for name in species_names:\n", " print(f\"{name} maps to {convertSpecies(name)}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "NuKqemiiKPR_" }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 12: USING DF'S .apply\n", "##########################################\n", "\n", "#\n", "# we can \"apply\" our new convertSpecies function to a whole column\n", "#\n", "# (The following will issue a \"SettingWithCopyWarning\" here...)\n", "# see https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", "#\n", "# >>> ADD CODE HERE TO KEEP THE WARNING FROM HAPPENING <<<\n", "df_final['irisname'] = df_final['irisname'].apply(convertSpecies)\n", "\n", "# Don't run this twice! Why?! What's \"KeyError: 0\"?\n", "# (of course, you can always go back and re-establish definitions of df_final)\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "tWoVKJBGKPR_" }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 13: CONFIRMING FINAL DATAFRAME\n", "##########################################\n", "\n", "#\n", "# let's see it! (this is safe to run many times...)\n", "#\n", "df_final # print(df_final.tostring()) # for _all_ rows..." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qxpBs7NnKPR_" }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 14: CONVERTING TO NUMPY FORMAT\n", "##########################################\n", "\n", "#\n", "# let's convert our dataframe to a numpy array, named A\n", "# Our ML library, scikit-learn operates entirely on numpy arrays.\n", "#\n", "#A = df_final.values\n", "A = df_final.to_numpy() # better -- self-documenting!\n", "\n", "print(f\"type of A: {type(A)}\")\n", "print(df_final.head())\n", "print(f\"A[0] = {A[0]}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "bblbBuIiKPSA" }, "outputs": [], "source": [ "##################################################\n", "# BLOCK 15: CONVERTING NUMPY ARRAY TO ALL FLOATS\n", "##################################################\n", "\n", "#\n", "# let's convert to make sure it's all floating-point, so we can multiply and divide\n", "#\n", "A = A.astype('float64') # so many: www.tutorialspoint.com/numpy/numpy_data_types.htm\n", "A" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "wbns1qpJKPSA" }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 16: USING NUMPY'S .shape\n", "##########################################\n", "\n", "#\n", "# nice to have num_rows and num_cols variables handy...\n", "#\n", "num_rows, num_cols = A.shape\n", "print(f\"\\nThe dataset has {num_rows} rows and {num_cols} cols\")\n", "print(A)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ixiZhsuqKPSA", "scrolled": true }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 17: PRINTING FLOWER INFO\n", "##########################################\n", "\n", "# let's use all of our previously-defined variables, to reinforce names...\n", "\n", "# choose a row index (particular flower) arbitrarily:\n", "flower = 132\n", "print(f\"flower #{flower} data is {A[flower]}\")\n", "\n", "for i in range(len(features)):\n", " col_name = features[i]\n", " if col_name != 'irisname':\n", " print(f\" Its {col_name} is {A[flower][i]}\")\n", " else:\n", " species_num = int(A[flower][i])\n", " species_name = species_names[species_num]\n", " print(f\" Its {col_name} is {species_name} ({species_num})\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "izGld2tSKPSA" }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 18: WRITING OUR OWN 1-NN FUNCTION\n", "##########################################\n", "\n", "#\n", "# We don't have to use scikit-learn to implement NN!\n", "#\n", "\n", "#\n", "# data-driven predictive model (1-nearest-neighbor)\n", "#\n", "\n", "# Python functions are first-class objects!\n", "dist = np.linalg.norm # built in to numpy... but what does norm do?\n", "\n", "num_rows, num_cols = A.shape # data size\n", "\n", "def predictiveModel( features: list[float] ) -> str:\n", " \"\"\" input: a list of four features\n", " [ sepallen, sepalwid, petallen, petalwid ]\n", " output: the predicted species of iris, from\n", " setosa (0), versicolor (1), virginica (2)\n", " \"\"\"\n", " our_features = np.asarray(features) # make a numpy array\n", "\n", " closest_flower = A[0]\n", " closest_features = A[0,0:4]\n", " closest_distance = dist(our_features - closest_features)\n", "\n", " for i in range(1, num_rows, 1):\n", " current_flower = A[i]\n", " current_features = A[i,0:4]\n", " current_distance = dist(our_features - current_features)\n", "\n", " if current_distance < closest_distance:\n", " closest_distance = current_distance # remember closest!\n", " closest_flower = current_flower\n", "\n", " # done comparing with every flower in the dataset\n", " predicted_species = int(round(closest_flower[4])) # what type is closest_flower?\n", " name = species_names[predicted_species]\n", " return f\"{name} ({predicted_species})\"\n", "\n", "#\n", "# Try it!\n", "#\n", "# features = eval(input(\"Enter new features: \"))\n", "#\n", "features = [ 4.6, 3.6, 3.0, 1.2 ]\n", "result = predictiveModel( features )\n", "print(f\"I predict {result} from features {features}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9nhDlGbRKPSB" }, "outputs": [], "source": [ "##########################################\n", "# BLOCK 19: COMMENTS ON SCIKIT-LEARN kNN\n", "##########################################\n", "\n", "#\n", "# but, we don't have to write our own ... because\n", "#\n", "# we want knn for any k (not just k=1 as above)\n", "# we want an already-debugged algorithm!\n", "# we want to ask iris-related questions instead of implementation ones...\n", "#" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "64kSAiCvKPSB" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 20: DEFINIING FEATURES & LABELS FOR kNN\n", "################################################\n", "\n", "print(\"+++ Start of data definitions +++\\n\")\n", "\n", "X_all = A[:,0:4] # X (features) ... is all rows, columns 0, 1, 2, 3\n", "y_all = A[:,4] # y (labels) ... is all rows, column 4 only\n", " # (look back at slide 20)\n", "print(f\"X_all (just features) is \\n {X_all}\")\n", "print(f\"y_all (just labels) is \\n {y_all}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "2ChEk2CDKPSC" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 21: REWEIGHTING FEATURES\n", "################################################\n", "\n", "#\n", "# we can re-weight different features here...\n", "#\n", "\n", "col_weights = { # could be called feature weight...\n", " 'sepallen':1.0,\n", " 'sepalwid':1.0,\n", " 'petallen':1.0,\n", " 'petalwid':1.0,\n", "}\n", "\n", "for col_name in col_weights:\n", " i = feature_name_to_index[col_name] # get the column index, i, of the column name\n", " weight = col_weights[col_name] # from the dictionary above\n", " print(f\"Weighting {col_name} by {weight}\")\n", " # weighting == \"multiplying\"\n", " X_all[:,i] *= weight # multiply by the weight to give this column (\"feature\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "sTDi2mFnKPSC" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 22: PERMUTING THE DATA\n", "################################################\n", "\n", "#\n", "#\n", "# we scramble the data, to give a different TRAIN/TEST split each time...\n", "#\n", "indices = np.random.permutation(len(y_all)) # indices is a permutation-list\n", "\n", "# we scramble both X and y, necessarily with the same permutation\n", "X_labeled = X_all[indices] # we apply the _same_ permutation to each!\n", "y_labeled = y_all[indices] # again...\n", "print(X_labeled) # note that X_labeled and y_labeled are permuted identically\n", "print(y_labeled)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "_pD7IZR1KPSC" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 23: DEFINING TRAIN VS TEST SETS\n", "################################################\n", "\n", "#\n", "# We next separate into test data and training data ...\n", "# + We will train on the training data...\n", "# + We will _not_ look at the testing data when building the model\n", "#\n", "# Then, afterward, we will test on the testing data -- and see how well we do!\n", "#\n", "\n", "#\n", "# a common convention: train on 80%, test on 20% Let's define the TEST_PERCENT\n", "#\n", "num_rows = X_labeled.shape[0] # the number of labeled rows\n", "test_percent = 0.20\n", "test_size = int(test_percent * num_rows) # no harm in rounding down\n", "\n", "X_test = X_labeled[:test_size] # first section are for testing\n", "y_test = y_labeled[:test_size]\n", "\n", "X_train = X_labeled[test_size:] # all the rest are for training\n", "y_train = y_labeled[test_size:]\n", "\n", "num_train_rows = len(y_train)\n", "num_test_rows = len(y_test)\n", "print(f\"total rows: {num_rows}; training with {num_train_rows} rows; testing with {num_test_rows} rows\" )\n", "print(f\"\\t(sanity check: {num_train_rows} + {num_test_rows} = {num_train_rows + num_test_rows})\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "jvJMYC3eKPSD" }, "outputs": [], "source": [ "#######################################################\n", "# BLOCK 24: FIRST ATTEMPT TO BUILD & TRAIN A kNN MODEL\n", "#######################################################\n", "\n", "#\n", "# +++ This is the \"Model-building and Model-training Cell\"\n", "#\n", "# Create a kNN model and train it!\n", "#\n", "from sklearn.neighbors import KNeighborsClassifier\n", "\n", "k = 84 # we don't know what k to use, so we guess for now! (this will _not_ be a good value)\n", "knn_model = KNeighborsClassifier(n_neighbors = k) # here, k is the \"k\" in kNN\n", "\n", "# we train the model (it's one line!)\n", "knn_model.fit(X_train, y_train) # yay! trained!\n", "print(\"Created and trained a knn classifier with k =\", k)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "d3cB0xryKPSD" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 25: TEST THE kNN MODEL\n", "################################################\n", "\n", "#\n", "# +++ This is the \"Model-testing Cell\"\n", "#\n", "# Now, let's see how well we did on our \"held-out data\" (the testing data)\n", "#\n", "\n", "# We run our test set!\n", "predicted_labels = knn_model.predict(X_test)\n", "actual_labels = y_test\n", "\n", "# Let's print them so we can compare...\n", "print(\"Predicted labels:\", predicted_labels)\n", "print(\"Actual labels :\", actual_labels)\n", "\n", "# And, some overall results\n", "num_correct = sum(predicted_labels == actual_labels)\n", "total = len(actual_labels)\n", "print(f\"\\nResults on test set: {num_correct} correct out of {total} total.\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "liXBT5-IKPSD" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 26: PRETTY-PRINT PREDICTED LABELS\n", "################################################\n", "\n", "#\n", "# Let's print these more helpfully, in a vertical table\n", "#\n", "\n", "def compareLabels(predicted_labels: np.ndarray, actual_labels: np.ndarray) -> int:\n", " ''' a more neatly formatted comparison, returning the number correct '''\n", " num_labels = len(predicted_labels)\n", " num_correct = 0\n", "\n", " for i in range(num_labels):\n", " predicted = int(round(predicted_labels[i])) # round-to-int protects from float imprecision\n", " actual = int(round(actual_labels[i]))\n", " result = \"incorrect\"\n", " if predicted == actual: # if they match,\n", " result = \"\" # no longer incorrect\n", " num_correct += 1 # and we count a match!\n", "\n", " # note the justification formatting:\n", " # :>3d right justifies integers (d) to width 3\n", " # :<12s left justifies strings (s) to width 12\n", " print(f\"row {i:>3d} : \", end = \"\")\n", " print(f\"{species_names[predicted]:>12s} \", end = \"\")\n", " print(f\"{species_names[actual]:<12s} {result}\")\n", "\n", " print()\n", " print(f\"Correct: {num_correct} out of {num_labels}\")\n", " return num_correct\n", "\n", "#\n", "# let's try it out!\n", "#\n", "\n", "compareLabels(predicted_labels,actual_labels)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "h_ZigXq2KPSE" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 27: USE THE FIRST-ATTEMPT kNN MODEL\n", "################################################\n", "\n", "#\n", "# Ok! We have our knn model, we could just use it...\n", "#\n", "\n", "#\n", "# data-driven predictive model (k-nearest-neighbor), using scikit-learn\n", "#\n", "\n", "def predictiveModel( features: list[float] ) -> str:\n", " ''' input: a list of four features\n", " [ sepallen, sepalwid, petallen, petalwid ]\n", " output: the predicted species of iris, from\n", " setosa (0), versicolor (1), virginica (2)\n", " '''\n", " our_features = np.asarray([features]) # extra brackets needed\n", " predicted_species = knn_model.predict(our_features)\n", " print(f\"predicted_species = {predicted_species}\")\n", "\n", " predicted_species = int(round(predicted_species[0])) # unpack one element\n", " name = species_names[predicted_species]\n", " return f\"{name} ({predicted_species})\"\n", "\n", "#\n", "# Try it!\n", "#\n", "# features = eval(input(\"Enter new features: \"))\n", "#\n", "features = [6.7,3.3,5.7,2.1] # [5.8,2.7,4.1,1.0] [4.6,3.6,3.0,2.2] [6.7,3.3,5.7,2.1]\n", "result = predictiveModel( features )\n", "print(f\"I predict {result} from features {features}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "kPByHBBnKPSE" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 28: COMMENTS ON CHOICE OF BEST k\n", "################################################\n", "\n", "#\n", "# Except, we didn't really explore whether this was the BEST model we could build!\n", "#\n", "#\n", "# We used k = 84 (a neighborhood size of 84 flowers)\n", "# In a dataset of only 140ish flowers, with three species, this seems like a bad idea!\n", "#\n", "# Perhaps we should try ALL the neighborhood sizes in their own TRAIN/TEST split\n", "# and see which neighborhood size works the best, for irises, at least...\n", "#" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ZUmotr7hKPSE" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 29: USING CROSS VALIDATION\n", "################################################\n", "\n", "#\n", "# to do this, we use \"cross validation\"\n", "# (see slide 45)\n", "#\n", "\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "from sklearn.model_selection import cross_val_score\n", "\n", "#\n", "# cross-validation splits the training set into two pieces:\n", "# + model-building and model-validation. We'll use \"build\" and \"validate\"\n", "#\n", "\n", "max_k = 85\n", "all_accuracies = []\n", "\n", "for k in range(1, max_k, 1):\n", " knn_cv_model = KNeighborsClassifier(n_neighbors = k) # build knn_model for every k!\n", " cv_scores = cross_val_score( knn_cv_model, X_train, y_train, cv = 5 ) # 5 means 80/20 split\n", " this_cv_accuracy = cv_scores.mean() # mean() is numpy's built-in average function\n", " print(f\"k: {k:2d} cv accuracy: {this_cv_accuracy:7.4f}\")\n", " all_accuracies.append(this_cv_accuracy)\n", "\n", "# assign best value of k to best_k\n", "best_k = k # *** AT THE MOMENT THIS IS INCORRECT ***\n", "# you'll need to modify the loop above to find and remember the real best_k\n", "\n", "print(f\"best_k = {best_k} yields the highest average cv accuracy.\") # print the best one\n", "\n", "plt.figure(figsize=(10, 6))\n", "sns.lineplot(x=range(1,len(all_accuracies)+1), y=all_accuracies)\n", "plt.xlabel(\"k value (index)\")\n", "plt.ylabel(\"Cross-validated accuracy\")\n", "plt.title(\"kNN Accuracy vs k Value\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pJW6c8XdKPSF" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 30: RE-BUILD & RE-TRAIN USING BEST k\n", "################################################\n", "\n", "#\n", "# Now, we re-create and re-run the \"Model-building and -training Cell\"\n", "#\n", "# Now, using best_k instead of the original, randomly-guessed value How does it do?!\n", "#\n", "from sklearn.neighbors import KNeighborsClassifier\n", "knn_model_tuned = KNeighborsClassifier(n_neighbors = best_k) # here, we use the best_k\n", "\n", "# we train the model (one line!)\n", "knn_model_tuned.fit(X_train, y_train) # yay! trained!\n", "print(f\"Created + trained a knn classifier, now tuned with a (best) k of {best_k}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9h5-1TukKPSF" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 31: RE-TEST THE BEST-k MODEL\n", "################################################\n", "\n", "#\n", "# Re-create and re-run the \"Model-testing Cell\" How does it do with best_k?!\n", "#\n", "predicted_labels = knn_model_tuned.predict(X_test)\n", "actual_labels = y_test\n", "\n", "# Let's print them so we can compare...\n", "print(\"Predicted labels:\", predicted_labels)\n", "print(\"Actual labels:\", actual_labels)\n", "print()\n", "# and, we'll print our nicer table...\n", "compareLabels(predicted_labels,actual_labels)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "8dIjchI0RQ57" }, "outputs": [], "source": [ "################################################\n", "# BLOCK 32: TRYING DIFFERENT PERMUTATIONS\n", "################################################\n", "\n", "#\n", "# Before moving on, go back and choose a new permutation to give\n", "# new testing and training sets, and go back through the steps\n", "# for identifying the \"best\" k (starting at Block 22 and re-doing\n", "# up through Block 31).\n", "#\n", "# Repeat this several times.\n", "# Do you get the same value for k each time? Why or why not?\n", "#" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "h1fhLBYSKPSF" }, "outputs": [], "source": [ "####################################################\n", "# BLOCK 33: REBUILD & TRAIN USING BEST k & ALL DATA\n", "####################################################\n", "\n", "# Ok! Now we have tuned knn to use the \"best\" value of k...\n", "#\n", "# And, we should really use ALL available data to train our final predictive model\n", "# (not split into test and train as before)\n", "#\n", "\n", "knn_model_final = KNeighborsClassifier(n_neighbors=best_k) # here, we use the best_k\n", "knn_model_final.fit(X_all, y_all) # yay! trained!\n", "print(f\"Created + trained a 'final' knn classifier, with a (best) k of {best_k}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "AsC4oa2qKPSG" }, "outputs": [], "source": [ "####################################################\n", "# BLOCK 34: TRYING FINAL MODEL \"IN THE WILD\"\n", "####################################################\n", "\n", "#\n", "# final predictive model (k-nearest-neighbor), with tuned k + ALL data incorporated\n", "#\n", "\n", "def predictiveModel( features: list[float] ) -> None:\n", " ''' input: a list of four features\n", " [ sepallen, sepalwid, petallen, petalwid ]\n", " output: the predicted species of iris, from\n", " setosa (0), versicolor (1), virginica (2)\n", " '''\n", " our_features = np.asarray([features]) # extra brackets needed\n", " predicted_species = knn_model_final.predict(our_features)\n", "\n", " predicted_species = int(round(predicted_species[0])) # unpack one element\n", " name = species_names[predicted_species]\n", " return f\"{name} ({predicted_species})\"\n", "\n", "#\n", "# Try it on several!\n", "#\n", "# features = eval(input(\"Enter new features: \"))\n", "#\n", "features = [6.7,3.3,5.7,2.1] # [5.8,2.7,4.1,1.0] [4.6,3.6,3.0,2.2] [6.7,3.3,5.7,2.1]\n", "result = predictiveModel( features )\n", "print(f\"I predict {result} from features {features}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "UHNILKXiRQ58" }, "outputs": [], "source": [ "################################################################\n", "# BLOCK 35a: HOW DOES THE MODEL PERFORM ON MEAN OF EACH FLOWER?\n", "################################################################\n", "\n", "# let's recall the species names and their order in the list\n", "print(species_names)\n", "print('=' * 70)\n", "\n", "# and let's recall what the final DataFrame looks like, noting that\n", "# the irisname was converted to the corresponding index in species_names\n", "print(df_final)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "MlnIrLPWRQ58" }, "outputs": [], "source": [ "################################################################\n", "# BLOCK 35b: HOW DOES THE MODEL PERFORM ON MEAN OF EACH FLOWER?\n", "################################################################\n", "\n", "# let's grab the data from df_final corresponding to versicolor\n", "versicolor_data = df_final[ df_final['irisname'] == convertSpecies('versicolor') ]\n", "print(versicolor_data)\n", "print('=' * 70)\n", "\n", "# let's print the mean of each column\n", "print(versicolor_data.mean())\n", "print('=' * 70)\n", "\n", "# and let's grab the features means only (don't need the label) for versicolor\n", "versicolor_features_means = np.asarray(versicolor_data.mean()[:-1])\n", "print(versicolor_features_means)\n", "\n", "# now run the predictive model (see Block 34 above) and print a corresponding\n", "# message\n", "\n", "# >>> YOU ADD CODE HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "twR2L9IRRQ58" }, "outputs": [], "source": [ "################################################################\n", "# BLOCK 35c: HOW DOES THE MODEL PERFORM ON MEAN OF EACH FLOWER?\n", "################################################################\n", "\n", "# Automate the process used in Block 35b, across all species:\n", "#\n", "# Loop across species names, and for each species,\n", "# (a) pull that corresponding data from df_final\n", "# (b) compute the means of the features, storing as a numpy array\n", "# (c) call the predictive model using those features\n", "# (d) print a corresponding message\n", "\n", "# >> YOU ADD CODE HERE -- YOU SHOULD NEED NO MORE THAN 5 LINES OF CODE" ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.2" } }, "nbformat": 4, "nbformat_minor": 0 }