diff --git a/.gitattributes b/.gitattributes index bdb0cabc..cee6d0d8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,7 @@ -# Auto detect text files and perform LF normalization +# Auto detect the text files and perform LF normalization easily! * text=auto -# Custom for Visual Studio +# Custom for Visual Studio (Any Version) *.cs diff=csharp # Standard to msysgit diff --git a/BinaryToDecimal.py b/BinaryToDecimal.py index ac41308d..1c3096c8 100644 --- a/BinaryToDecimal.py +++ b/BinaryToDecimal.py @@ -1,25 +1,25 @@ # Python: Binary to Decimal Conversion # binToDec and decToBin functions are rendered obsolete by the universal convert function -def binToDec(binNum): +def binToDec(binNum): #function created to convert binary to decimal with parametere binNum decNum = 0 power = 0 - while binNum > 0: - decNum += 2 ** power * (binNum % 10) - binNum //= 10 - power += 1 + while binNum > 0: #loop will run till binNum is greater than 0 + decNum += 2 ** power * (binNum % 10) + binNum //= 10 # reducing binNum everytime by 1 digit + power += 1 # increasing power by 1 each loop return decNum -def decToBin(decNum): +def decToBin(decNum): #function created to convert decimal to binary with parametere decNum binNum = 0 power = 0 - while decNum > 0: + while decNum > 0:#loop will run till decNum is greater than 0 binNum += 10 ** power * (decNum % 2) - decNum //= 2 - power += 1 + decNum //= 2 # reducing decNum everytime by 1 digit + power += 1 # increasing power by 1 each loop return binNum -def convert(fromNum, fromBase, toBase): +def convert(fromNum, fromBase, toBase): #function for converting from any base to any other base toNum = 0 power = 0 while fromNum > 0: @@ -31,4 +31,4 @@ def convert(fromNum, fromBase, toBase): # print (str(binToDec(101011))) # print (str(decToBin(128))) print (str(convert(127, 10, 8))) # converts 127 in base 10 to base 8 -print (str(convert(101001, 2, 2))) \ No newline at end of file +print (str(convert(101001, 2, 2))) diff --git a/Contributing.txt b/Contributing.txt new file mode 100644 index 00000000..52d1fd31 --- /dev/null +++ b/Contributing.txt @@ -0,0 +1,21 @@ +Contributions are always welcome!!!! +If you want to contribute to this repository follow the below procedure - +1. Fork this repository +2. Clone the code to your local system and go through readme.md +3. You can create another branch to add further commits + +GIT COMMANDS FOR CONTRIBUTING - +1. To clone this repository +`git clone [code link]` +2.To create new branch +`git checkout -b [branch name] ` +3. To stage files +`git add .` +4.To commit changes +`git commit -m "commit message"` +5. To push changes +`git push [remote branch] [new branch]` + +HAPPY CONTRIBUTION!!!!!!!! + + \ No newline at end of file diff --git a/Date Time Timestamp/Date_Time_Timestamp.py b/Date Time Timestamp/Date_Time_Timestamp.py index 7897332c..cc533dcf 100644 --- a/Date Time Timestamp/Date_Time_Timestamp.py +++ b/Date Time Timestamp/Date_Time_Timestamp.py @@ -19,21 +19,21 @@ # get day of the week using date.weekday() # Monday is 0 from datetime import date -d1 = date.today() -print(d1) -print(d1.month, d1.day, d1.year) -print(d1.weekday()) +todays_date = date.today() +print(todays_date) +print(todays_date.month, todays_date.day, todays_date.year) +print(todays_date.weekday()) # ISO format is a string format, yyyy-mm-dd # --------------------------- # date_object.isoformat() does the same thing as str(date_object) from datetime import date -d1 = date.fromisoformat('2011-11-23') -print(d1) -print(str(d1)) -print(d1.isoformat()) -d1 +todays_date = date.fromisoformat('2011-11-23') +print(todays_date) +print(str(todays_date)) +print(todays_date.isoformat()) +todays_date # Comparison, addition and sutraction of dates # --------------------------- @@ -42,10 +42,10 @@ # The same comparison and add/subtract operations can be used with time objects. from datetime import date -d1 = date.today() +todays_date = date.today() d2 = date(2015, 5, 14) -print(d1 > d2) -print(d1 - d2) +print(todays_date > d2) +print(todays_date - d2) # Time # --------------------------- @@ -95,9 +95,9 @@ # A timedelta can also be multiplied or divided by an integer or float from datetime import timedelta, date, time -d1 = date(2011, 6, 15) +todays_date = date(2011, 6, 15) d2 = date(2012, 9, 18) -td = d2 - d1 +td = d2 - todays_date print(td, type(td)) print(td.total_seconds()) print(td * 3) @@ -130,4 +130,4 @@ start_time = time.process_time() # do some stuff end_time = time.process_time() -print('operation executed in ', end_time - start_time) \ No newline at end of file +print('operation executed in ', end_time - start_time) diff --git a/Intro to Python Data Structures/Some Basic Terminologies in Python Data Structure b/Intro to Python Data Structures/Some Basic Terminologies in Python Data Structure new file mode 100644 index 00000000..754c07a5 --- /dev/null +++ b/Intro to Python Data Structures/Some Basic Terminologies in Python Data Structure @@ -0,0 +1,31 @@ +##Data Structure Overview +Data structures are fundamental concepts of computer science which helps is writing efficient programs in any language. Python is a high-level, interpreted, interactive and object-oriented scripting language using which we can study the fundamentals of data structure in a simpler way as compared to other programming languages. + +In this chapter we are going to study a short overview of some frequently used data structures in general and how they are related to some specific python data types. There are also some data structures specific to python which is listed as another category. + +##General Data Structures +The various data structures in computer science are divided broadly into two categories shown below. We will discuss about each of the below data structures in detail in subsequent chapters. + +#Liner Data Structures +These are the data structures which store the data elements in a sequential manner. + +Array: It is a sequential arrangement of data elements paired with the index of the data element. +Linked List: Each data element contains a link to another element along with the data present in it. +Stack: It is a data structure which follows only to specific order of operation. LIFO(last in First Out) or FILO(First in Last Out). +Queue: It is similar to Stack but the order of operation is only FIFO(First In First Out). +Matrix: It is two dimensional data structure in which the data element is referred by a pair of indices. + +#Non-Liner Data Structures +These are the data structures in which there is no sequential linking of data elements. Any pair or group of data elements can be linked to each other and can be accessed without a strict sequence. + +Binary Tree: It is a data structure where each data element can be connected to maximum two other data elements and it starts with a root node. +Heap: It is a special case of Tree data structure where the data in the parent node is either strictly greater than/ equal to the child nodes or strictly less than it’s child nodes. +Hash Table: It is a data structure which is made of arrays associated with each other using a hash function. It retrieves values using keys rather than index from a data element. +Graph: .It is an arrangement of vertices and nodes where some of the nodes are connected to each other through links. + +#Python Specific Data Structures +These data structures are specific to python language and they give greater flexibility in storing different types of data and faster processing in python environment. + +List: It is similar to array with the exception that the data elements can be of different data types. You can have both numeric and string data in a python list. +Tuple: Tuples are similar to lists but they are immutable which means the values in a tuple cannot be modified they can only be read. +Dictionary: The dictionary contains Key-value pairs as its data elements. diff --git a/Iris Dataset/Iris_Dataset.ipynb b/Iris Dataset/Iris_Dataset.ipynb new file mode 100644 index 00000000..398f454e --- /dev/null +++ b/Iris Dataset/Iris_Dataset.ipynb @@ -0,0 +1,1174 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data Science\n", + "### Exploring the Iris Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load Data\n", + "Load the data from CSV file into a Pandas dataframe, and print the top few rows." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
idsepal_lengthsepal_widthpetal_lengthpetal_widthspecies
005.13.51.40.2Iris-setosa
114.93.01.40.2Iris-setosa
224.73.21.30.2Iris-setosa
334.63.11.50.2Iris-setosa
445.03.61.40.2Iris-setosa
\n", + "
" + ], + "text/plain": [ + " id sepal_length sepal_width petal_length petal_width species\n", + "0 0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 4 5.0 3.6 1.4 0.2 Iris-setosa" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data = pd.read_csv('iris.data')\n", + "data.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Customize columns\n", + "Drop the redundant id column, and rename Attribute columns to integers. Save column names for use later." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
0123species
05.13.51.40.2Iris-setosa
507.03.24.71.4Iris-versicolor
1006.33.36.02.5Iris-virginica
\n", + "
" + ], + "text/plain": [ + " 0 1 2 3 species\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "50 7.0 3.2 4.7 1.4 Iris-versicolor\n", + "100 6.3 3.3 6.0 2.5 Iris-virginica" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data = data.drop('id', 1)\n", + "cols = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']\n", + "data.rename(columns = {cols[0]:0, cols[1]:1, cols[2]:2, cols[3]:3}, inplace=True)\n", + "data.loc[::50]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Statistical Overview\n", + "Show shape of dataframe and statistical overview of attribute columns." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(150, 5)\n" + ] + }, + { + "data": { + "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", + "
0123
count150.000000150.000000150.000000150.000000
mean5.8433333.0540003.7586671.198667
std0.8280660.4335941.7644200.763161
min4.3000002.0000001.0000000.100000
25%5.1000002.8000001.6000000.300000
50%5.8000003.0000004.3500001.300000
75%6.4000003.3000005.1000001.800000
max7.9000004.4000006.9000002.500000
\n", + "
" + ], + "text/plain": [ + " 0 1 2 3\n", + "count 150.000000 150.000000 150.000000 150.000000\n", + "mean 5.843333 3.054000 3.758667 1.198667\n", + "std 0.828066 0.433594 1.764420 0.763161\n", + "min 4.300000 2.000000 1.000000 0.100000\n", + "25% 5.100000 2.800000 1.600000 0.300000\n", + "50% 5.800000 3.000000 4.350000 1.300000\n", + "75% 6.400000 3.300000 5.100000 1.800000\n", + "max 7.900000 4.400000 6.900000 2.500000" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(data.shape)\n", + "data.describe()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Iris-virginica 50\n", + "Iris-setosa 50\n", + "Iris-versicolor 50\n", + "Name: species, dtype: int64" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# same as data['species'].value_counts()\n", + "data.species.value_counts()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Histograms\n", + "Histograms are useful for showing how the data is distributed. They're ridiculously easy to use, but can only show two axes." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([ 9., 23., 14., 27., 16., 26., 18., 6., 5., 6.]),\n", + " array([4.3 , 4.66, 5.02, 5.38, 5.74, 6.1 , 6.46, 6.82, 7.18, 7.54, 7.9 ]),\n", + " )" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(data[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we give 4 columns of data to the Histogram maker, and it automatically color codes them." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([[ 0., 0., 0., 0., 0., 11., 48., 49., 31., 11.],\n", + " [ 0., 0., 11., 97., 38., 4., 0., 0., 0., 0.],\n", + " [ 0., 44., 6., 1., 10., 34., 30., 20., 5., 0.],\n", + " [50., 52., 45., 3., 0., 0., 0., 0., 0., 0.]]),\n", + " array([0.1 , 0.88, 1.66, 2.44, 3.22, 4. , 4.78, 5.56, 6.34, 7.12, 7.9 ]),\n", + " )" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist([data[0], data[1], data[2], data[3]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To add a Legend we need to add labels to the Histogram builder as a list of column names, and call the legend function." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAD4CAYAAAAXUaZHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAah0lEQVR4nO3deXCV9dn/8fclIEFFRIgUCRpQBEyCIQZZAmlcUHyCa1N/ZbAENypuqB0FrS1onY62jGtRJ27BecCKUUalalEfGcCiECAOS7BukQYQAwqIkLJ4/f7IIU0wgZwlOYebz2uG8Zx7vTjIh2++931fx9wdEREJliPiXYCIiMSewl1EJIAU7iIiAaRwFxEJIIW7iEgAtY53AQCdO3f21NTUeJchInJIWbp06SZ3T25o3UHD3cyeA0YC37h7emjZ8cBLQCpQAVzh7t+ZmQGPAv8D7ADGuvuyg50jNTWV0tLSpv1uREQEADP7qrF1TZmWKQZG7LdsEvCeu/cC3gu9B7gQ6BX6NQ54MtxiRUQkegcNd3efD3y73+JLgOmh19OBS+ssf8FrfAgcZ2ZdY1WsiIg0TaQXVLu4+4bQ66+BLqHX3YB/19muMrTsJ8xsnJmVmllpVVVVhGWIiEhDor6g6u5uZmH3MHD3IqAIIDs7Wz0QRBLM7t27qayspLq6Ot6lHPaSkpJISUmhTZs2Td4n0nDfaGZd3X1DaNrlm9DydUD3OtulhJaJyCGmsrKS9u3bk5qaSs29EhIP7s7mzZuprKykR48eTd4v0mmZ14HC0OtC4LU6y8dYjUHA1jrTNyJyCKmurqZTp04K9jgzMzp16hT2T1BNuRXyRSAP6GxmlcBk4AFglpldA3wFXBHa/E1qboP8jJpbIa8KqxoRSSgK9sQQyZ/DQcPd3Uc1surcBrZ14MawqxARkZhKiCdURSTxpU76e0yPV/FAfkyPJ/Wpt4zE1pQODf8SSTDz5s1j5MiRja4vLi7mpptuivl5i4uLWb9+fe371NRUNm3aFPPzKNxFRFrQ/uHeXBTuIpKwfvjhB/Lz8znjjDNIT0/npZdeYunSpfz85z/nzDPP5IILLmDDhpob8vLy8pgwYQKZmZmkp6ezePFiABYvXszgwYPp378/Q4YM4ZNPPgm7jqqqKn7xi18wYMAABgwYwAcffADAlClTuPrqq8nLy6Nnz5489thjtfv88Y9/pHfv3gwdOpRRo0YxdepUSkpKKC0tZfTo0WRmZrJz504AHn/8cbKyssjIyGDNmjXRfmyAwl1EEtjbb7/NiSeeyMcff8zKlSsZMWIEN998MyUlJSxdupSrr76a3/3ud7Xb79ixg7KyMp544gmuvvpqAPr06cOCBQtYvnw59913H3fffXfYdUyYMIHbbruNJUuW8Morr3DttdfWrluzZg3/+Mc/WLx4Mffeey+7d++u3e7jjz/mrbfeqm2MWFBQQHZ2NjNmzKCsrIx27doB0LlzZ5YtW8b48eOZOnVqNB9ZLV1QFZGElZGRwW9/+1smTpzIyJEj6dixIytXrmT48OEA7N27l65d/9u+atSompv7cnNz2bZtG1u2bOH777+nsLCQTz/9FDNj9+7dYdfx7rvvsnr16tr327ZtY/v27QDk5+fTtm1b2rZtywknnMDGjRv54IMPuOSSS0hKSiIpKYmLLrrogMe//PLLATjzzDN59dVXw66vIQp3EUlYp512GsuWLePNN9/knnvu4ZxzziEtLY1FixY1uP3+94ObGb///e85++yzmT17NhUVFeTl5YVdx48//siHH35IUlLST9a1bdu29nWrVq3Ys2dP2Mffd4xI92+Iwl1EmiQety6uX7+e448/niuvvJLjjjuOJ554gqqqKhYtWsTgwYPZvXs3//rXv0hLSwPgpZde4uyzz2bhwoV06NCBDh06sHXrVrp1q+lfWFxcHFEd559/Po8//jh33HEHAGVlZWRmZja6fU5ODr/5zW+466672LNnD3PmzGHcuHEAtG/fnu+//z6iOsKhcBeRhLVixQruuOMOjjjiCNq0acOTTz5J69atueWWW9i6dSt79uzh1ltvrQ33pKQk+vfvz+7du3nuuecAuPPOOyksLOT+++8nPz+yf6Aee+wxbrzxRvr168eePXvIzc3lqaeeanT7AQMGcPHFF9OvXz+6dOlCRkYGHTrU3BI8duxYrr/+etq1a9foTyCxYDUPlcZXdna265uYAqKxe9qnbG3ZOiRq5eXl9O3bN95lNFleXh5Tp04lOzs73qUAsH37do455hh27NhBbm4uRUVFZGVlRXy8hv48zGypuzf4G9bIXUSkGYwbN47Vq1dTXV1NYWFhVMEeCYW7iATCvHnzItrv+eef59FHH623LCcn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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist([data[0], data[1], data[2], data[3]], label=[cols[0],cols[1],cols[2],cols[3]])\n", + "plt.legend()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or we can make 4 separate calls to the Histogram builder and get 4 overlapping plots." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([41., 8., 1., 7., 8., 33., 6., 23., 9., 14.]),\n", + " array([0.1 , 0.34, 0.58, 0.82, 1.06, 1.3 , 1.54, 1.78, 2.02, 2.26, 2.5 ]),\n", + " )" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(data[0])\n", + "plt.hist(data[1]) \n", + "plt.hist(data[2])\n", + "plt.hist(data[3])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use alpha to control the opacity of plots. alpha of 1 is opague. alpha of 0 is transparent." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([41., 8., 1., 7., 8., 33., 6., 23., 9., 14.]),\n", + " array([0.1 , 0.34, 0.58, 0.82, 1.06, 1.3 , 1.54, 1.78, 2.02, 2.26, 2.5 ]),\n", + " )" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(data[0])\n", + "plt.hist(data[1], alpha=1) \n", + "plt.hist(data[2], alpha=0.6)\n", + "plt.hist(data[3], alpha=0.5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also plot the 4 columns on separate subplots to make it more readable. This is very readable, but beware that each plot automatically scales its axes to the data." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(2, 2, figsize=(8, 4))\n", + "ax[0, 0].hist(data[0])\n", + "ax[0, 1].hist(data[1])\n", + "ax[1, 0].hist(data[2])\n", + "ax[1, 1].hist(data[3])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding titles to the previous plot makes it more readable." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(2, 2, figsize=(8, 6))\n", + "ax[0, 0].hist(data[0])\n", + "ax[0, 1].hist(data[1])\n", + "ax[1, 0].hist(data[2])\n", + "ax[1, 1].hist(data[3])\n", + "ax[0, 0].set_title(cols[0])\n", + "ax[0, 1].set_title(cols[1])\n", + "ax[1, 0].set_title(cols[2])\n", + "ax[1, 1].set_title(cols[3])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Scatter Plots\n", + "These are probably more useful for this dataset because they can show clusters by species. The most basic scatter plot does not distinguish species." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(\n", + " data[0], \n", + " data[1],)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding color coding by species allows us to see clustering for 2 attributes for each species. Here setosa is secluded, but virginica and versicolor overlap." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "colors = {'Iris-setosa':'red', 'Iris-virginica':'blue', 'Iris-versicolor':'green'}\n", + "plt.scatter(\n", + " data[2], \n", + " data[3], \n", + " c=data['species'].map(colors))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding labels to the x and y axes is useful, but we can see the data for virginica and versicolor still overlap. If we could find 1 attribute where there's no overlap for these 2 species then we could use those to definitively distinguish them. But unfortunately all 4 attributes have some overlap." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'petal_length')" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(\n", + " data[0], \n", + " data[2], \n", + " c=data['species'].map(colors))\n", + "plt.xlabel(cols[0])\n", + "plt.ylabel(cols[2])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we add a title to the plot, and show attributes 1 and 3. " + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Iris Data Scatter Plot')" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(\n", + " data[1], \n", + " data[3], \n", + " c=data['species'].map(colors))\n", + "plt.xlabel(cols[1])\n", + "plt.ylabel(cols[3])\n", + "plt.title('Iris Data Scatter Plot')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Correlation\n", + "We can see the correlation between attributes. A correlation close to 1 helps us distinguish between species. Low correlation doesn't help us." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
0123
01.000000-0.1093690.8717540.817954
1-0.1093691.000000-0.420516-0.356544
20.871754-0.4205161.0000000.962757
30.817954-0.3565440.9627571.000000
\n", + "
" + ], + "text/plain": [ + " 0 1 2 3\n", + "0 1.000000 -0.109369 0.871754 0.817954\n", + "1 -0.109369 1.000000 -0.420516 -0.356544\n", + "2 0.871754 -0.420516 1.000000 0.962757\n", + "3 0.817954 -0.356544 0.962757 1.000000" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.corr()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Box and Whisker Plots\n", + "Box plots show the distribution of data over an attribute by showing the 25th, 50th (median) and 75th percentiles. Again, the simplest plots are not very useful, but when we add labels and color coding the plots are revealing." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'whiskers': [,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ],\n", + " 'caps': [,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ],\n", + " 'boxes': [,\n", + " ,\n", + " ,\n", + " ],\n", + " 'medians': [,\n", + " ,\n", + " ,\n", + " ],\n", + " 'fliers': [,\n", + " ,\n", + " ,\n", + " ],\n", + " 'means': []}" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.boxplot([data[0], data[1], data[2], data[3]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This shows a boxplot for one attribute, sorted by species. For this attribute we can see a big overlap between the 3 species, so it's not very useful for distinguishing. An iris with 5.5 or 6.0 for this attribute could be any of the 3 species." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAEcCAYAAADA5t+tAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAfPklEQVR4nO3de5gcRb3/8feHJGhIYgDR5U5AECPhBwdWAY2eRRA1KOgxCHlEBOMJoCeIV4IgoOfgA6I/D4gaI9EQ0cgRRZFghCMZAS9IuF+C/BACIdxvgQ1RE/j+/uhabYbdndnMTGZ36/N6nnm2p6qmqrpr5zs91T3digjMzCwfG7S7A2Zmtn458JuZZcaB38wsMw78ZmaZceA3M8uMA7+ZWWYc+K1lJIWkHdvdj3aS1CXpgX7yh+Q2kvR5See1ux+2bhz4MyBpmaTVkrolPSVpoaRt2t2vHpKOlHRNu/th9YuIL0fER9vdD1s3Dvz5eE9EjAW2AB4BvtHm/rSMpJHt7oPZYObAn5mI+CtwEfD6njRJ4yXNl/SYpPsknSxpA0mbSnpA0ntSubGS7pZ0RHo+T9JsSVdIelbSbyVt11u7/bQxEZgN7JO+kTzdx+u3l3RVaud/JX1T0gUpb0KaMpku6X7gylT3yamtR1Pb41P5l0y/pG9F+6fl0yRdJOnC1N4NknYrld1S0k/Tutwr6bhS3ui0XZ6SdAfwhjqGZYqkeyQ9Lums1PcNJT0paddS3a+W9JykV/WyfXZM239lqufCUl5IOq66jVL+RyQtTX3+dXkMJe2SxvdJSY9I+nxpG11QKre3pN9LelrSzZK6SnlHprafTdvrg3VsE2uliPBjmD+AZcD+aXkj4Hxgfil/PvALYBwwAbgLmJ7yDgAeBl4NfBe4qPS6ecCzwFuBlwFnA9eU8gPYsY42jiy/ro91+APwVWBDYDLwDHBBypuQ2poPjAFGAx8B7gZ2AMYCPwN+kMp3AQ/0s41OA9YAU4FRwGeAe9PyBsD1wCmpLzsA9wDvSK89A7ga2BTYBrituq2qdgNYnMpvm7bLR1Pet4AzS2U/Afyyj3oWACel/r0cmFxnGwen7TQRGAmcDPw+5Y0DHgI+neocB+xV2kY9238r4AlgSmr/7en5q9J4PAPsnMpuAezS7vdE7o+2d8CP9TDIRVDrBp5OAe1BYNeUNwL4O/D6UvmjgUrp+TeAW4EVwCtL6fOAH5eejwWeB7ZJzwPYsVYb1Aj8KVitBTYqpV3ASwP/DqX83wAfKz3fOa37SOoL/H8s5W2QAuBbgL2A+6teeyLw/bR8D/DOUt6M6raqXhtV5T8G/CYt7wXcDyg9XwJ8oI965gNzgK0H2MavSB/ApXV9DtgOmAbc2Ed7p5W2/wmkD9VS/q+BD1ME/qeB9wOj2/1e8KN4eKonH++NiI0p9tz+A/itpM2BzSj2ZO8rlb2PYi+uxxxgEjAvIp6oqnd5z0JEdANPAltWlamnjf5sCTwZEc/11m4faVv20t5IoKPONsvr9QLwQKpzO2DLNKXxdJqa+nyp3i2r+lHuQ822UvktU7vXUgThLkmvo/gQvaSPOj4HCPiTpNslfaSeNtL6nF1alydTPVtRfGP5Sx393w44pGqbTAa2iIhVwKHAMcBDKk4seF0ddVoLOfBnJiKej4ifUeyZTwYep9gTLs/Nb0uxd4+kERSBfz7wMb301MN/nB0kaSzFdMKDVWX6bYNij7Q/DwGbStqot3bLq1dafrCX9tZSHNheRTHl1dPvERTTEmXl9doA2DrVuRy4NyI2Lj3GRcSUUl/Lfdu2xrpVr8u2vHj7nQ8cDnyIYprtr71VEBEPR8S/R8SWFN+mvlU1Vn21sRw4ump9RkfE71PeDnX0fznFHn+5jjERcUbq268j4u0U0zx3UkwZWhs58GdGhYOBTYClEfE88D/A6ZLGpQN7n6KYSoFibzYo5szPAuanQNljiqTJkjYE/pNiiuRFe+N1tPEIsHWq4yUi4j6KaY7T0kHPfYD31FjVBcAn00HhscCXgQsjYi3FHPfLJR0oaRTFvPbLql6/p6R/U3GG0InAK4BFwI+BkZJOSAdyR0iaJKnnIO7/ACdK2kTS1sDMGv0E+Gwqvw3FPP6FpbwLgPdRBP/5fVUg6ZDUHsBTFGP2Qh1tzE793SXVM17SISnvUmALScdLelkau716af4C4D2S3pG2x8tVHEDfWlKHpIMljQH+RjHl+EIvddj61O65Jj9a/6CYv15N8aZ7luKA4wdL+ZtQvHkfo9h7O4Vip2BPiiDSc4B2BPA74KT0fB5F4Lgi1X0VsH2p3vLB3V7bSHkbAgspphke72MdXkNx0PRZivn7OcDclDchtTWyVH6D1Mby1OYFwCal/CMp9s4fpTh4u4wXz/FfRBEcn039+jXFMYyeA8sLKQ56PwX8kRcfPJ9PMa99B/BZas/xH0dxbOAJ4GvAiKoy/5v6p37q+QrFN6huiumZGfW2QfFt4ta0XsuB75XyJqXt/VRa31mlbXRBqdxewG/TtnosbZ9tKfbyfwusTNukQulYjx/tefQcNDIbMEnzKILayW1o+0Lgzog4tQV1n0bxgXV42lN9CpgUEXel/B8AKyJiVrPb7qM/3wMeXNftLCmAnSLi7ub2zIYqT/XYkCDpDZJek85xfyfFaYg/Xw9NvxZY2xP0k5uBXdZD20iaAPwbMHd9tGd5cOC3oWJzimmCbuAc4NiIuHE9tDuWYgqkbCXFOe0tJek/KablzoqIe1vdnuXDUz1m/ZD0L8DvIqJ8FtCnga6IqHWA2WxQ8h6/Wf/uojiLZ6dS2m7A7W3qj1nDvMdvVoOkH1OcGfNRYHfgMuBNEeHgb0OS9/jNavsYxfV/HqX4fcCxDvo2lHmP38wsM97jNzPLjAO/mVlmHPjNzDLjwG9mlhkHfjOzzLTtptSbbbZZTJgwoV3NrzerVq1izJgx7e6GNYHHcvjIZSyvv/76xyPiJfdorivwS/okxY9XguLyrUdF6YYQkl5GcSnaPSku+3poRCzrr84JEyawZMmSuldgqKpUKnR1dbW7G9YEHsvhI5exlNTrHeBqTvVI2oriWt6dETGJ4prsh1UVmw48FRE7Al8Hzmysu2Zm1ir1zvGPBEanuxFtxEtvrXcwxS3ioLiBxX6S1JwumplZM9Wc6omIFZK+CtxPcRenyyPi8qpiW5Fu5hwRayWtBF5Jca/Vf5A0A5gB0NHRQaVSaXgFBrvu7u4s1jMHHsvhI/exrBn4JW1CsUe/PcWt034i6fCIuKD/V75URMyhuGUenZ2dkcMcWy5ziTnwWA4fuY9lPVM9+wP3RsRjEbEG+BnwpqoyK4BtANJ00HiKg7xmZjbI1BP47wf2lrRRmrffD1haVeYS4MNpeSpwZfjqb2Zmg1LNwB8R11IcsL2B4lTODYA5kr4k6aBUbC7wSkl3A58C1stNqM3MbODqOo8/Ik4FTq1KPqWU/1fgkCb2y8zMWqRtv9w1M2uVZp1NPlxnrH2tHjMbdiKi38d2J1xas8xwDfrgwG9mlh0HfjOzzDjwm5llxoHfzCwzDvxmZplx4Dczy4wDv5lZZhz4zcwy48BvZpYZB34zs8w48JuZZcaB38wsMw78ZmaZceA3M8uMA7+ZWWYc+M3MMlMz8EvaWdJNpcczko6vKtMlaWWpzCl91WdmZu1V89aLEfFnYHcASSOAFcDFvRS9OiLe3dzumZlZsw10qmc/4C8RcV8rOmNmZq030JutHwYs6CNvH0k3Aw8Cn4mI26sLSJoBzADo6OigUqkMsPmhp7u7O4v1zIHHcnjJeSxV7w2FJW1IEdR3iYhHqvJeAbwQEd2SpgBnR8RO/dXX2dkZS5YsWcduDx2VSoWurq52d8OawGM5fEyYtZBlZxzY7m60nKTrI6KzOn0gUz3vAm6oDvoAEfFMRHSn5cuAUZI2W+femplZywwk8E+jj2keSZtLUlp+Y6r3ica7Z2ZmzVbXHL+kMcDbgaNLaccARMRsYCpwrKS1wGrgsKh3DsnMzNarugJ/RKwCXlmVNru0fC5wbnO7ZmZmreBf7pqZZcaB38wsMw78ZmaZceA3M8uMA7+ZWWYc+M3MMuPAb2aWGQd+M7PMOPCbmWXGgd/MLDMO/GZmmXHgNzPLjAO/mVlmHPjNzDLjwG9mlhkHfjOzzDjwm5llxoHfzCwzNQO/pJ0l3VR6PCPp+KoyknSOpLsl3SJpj9Z12czMGlHznrsR8WdgdwBJI4AVwMVVxd4F7JQeewHfTn/NzGyQGehUz37AXyLivqr0g4H5UfgjsLGkLZrSQzMza6qBBv7DgAW9pG8FLC89fyClmZnZIFNzqqeHpA2Bg4AT17UxSTOAGQAdHR1UKpV1rWrI6O7uzmI9h7p99923aXUtXry4aXVZ6+T8vqw78FPM498QEY/0krcC2Kb0fOuU9iIRMQeYA9DZ2RldXV0DaH5oqlQq5LCeQ11E1CwzYdZClp1x4HrojbXcooVZvy8HMtUzjd6neQAuAY5IZ/fsDayMiIca7p2ZmTVdXXv8ksYAbweOLqUdAxARs4HLgCnA3cBzwFFN76mZmTVFXYE/IlYBr6xKm11aDuDjze2amZm1wkDm+M3M2m63L17OytVrGq5nwqyFDb1+/OhR3HzqAQ33ox0c+M1sSFm5ek3DB9mbcdJFox8c7eRr9ZiZZcaB38wsMw78ZmaZceA3M8uMA7+ZWWYc+M3MMuPAb2aWGQd+M7PMOPCbmWXGgd/MLDMO/GZmmXHgNzPLjAO/mVlmHPjNzDLjwG9mlhkHfjOzzNQV+CVtLOkiSXdKWippn6r8LkkrJd2UHqe0prtmZtaoeu/AdTawKCKmStoQ2KiXMldHxLub1zUzM2uFmoFf0njgrcCRABHxd+Dvre2WmZm1Sj1TPdsDjwHfl3SjpPMkjeml3D6Sbpb0K0m7NLebZmbWLPVM9YwE9gBmRsS1ks4GZgFfKJW5AdguIrolTQF+DuxUXZGkGcAMgI6ODiqVSoPdH/y6u7uzWM9ceCzbb9zEWex6/qzGKzq/0X5ApdLbPvAQEBH9PoDNgWWl528BFtZ4zTJgs/7K7LnnnpGDxYsXt7sL1iTbnXBpu7tg0ZxxaMb7cij8PwBLopf4W3OqJyIeBpZL2jkl7QfcUS4jaXNJSstvpJhCeqIZH0xmZtZc9Z7VMxP4YTqj5x7gKEnHAETEbGAqcKyktcBq4LD0aWNmZoNMXYE/Im4COquSZ5fyzwXObWK/zMysRfzLXTOzzDjwm5llxoHfzCwzDvxmZplx4Dczy4wDv5lZZuo9j99sSNvti5ezcvWahuuZMGthQ68fP3oUN596QMP9MGuEA79lYeXqNSw748CG6qhUKnR1dTVUR6MfHGbN4KkeM7PMOPCbmWXGUz1mNuQ0ZcpsUePHa4YqB34zG1IaPVYDxQdHM+oZqjzVY2aWGQd+M7PMOPCbmWXGgd/MLDMO/GZmmXHgNzPLjAO/mVlm6gr8kjaWdJGkOyUtlbRPVb4knSPpbkm3SNqjNd01M7NG1fsDrrOBRRExVdKGwEZV+e8CdkqPvYBvp79mZjbI1NzjlzQeeCswFyAi/h4RT1cVOxiYH4U/AhtL2qLpvTUzs4bVs8e/PfAY8H1JuwHXA5+IiFWlMlsBy0vPH0hpD5UrkjQDmAHQ0dFBpVJZ954PEd3d3Vms51DQ6Dg0ayz9/zA45DwO9QT+kcAewMyIuFbS2cAs4AsDbSwi5gBzADo7O6PRa5sPBc24hrs1waKFDY9DU8ayCf2wJsh8HOo5uPsA8EBEXJueX0TxQVC2Atim9HzrlGZmZoNMzcAfEQ8DyyXtnJL2A+6oKnYJcEQ6u2dvYGVEPISZmQ069Z7VMxP4YTqj5x7gKEnHAETEbOAyYApwN/AccFQL+mpmZk1QV+CPiJuAzqrk2aX8AD7exH6ZmVmL+EYsloVxE2ex6/mzGq/o/Eb7AZDvDUBscHDgtyw8u/SMhu+41Iyzeppyy0CzBvlaPWZmmXHgNzPLjAO/mVlmPMffAElNqac4KcrMbP3wHn8DIqLmY7sTLq1ZxsxsfXLgNzPLjAO/mVlmHPjNzDLjwG9mlhkHfjOzzDjwm5llxoHfzCwzDvxmZplx4Dczy4wv2WDZaMolkRc1Vsf40aMa74PVVM/lVHRm7XqG6y/rHfgtC41eix+KD45m1GOtVytgN+PeCkNZXYFf0jLgWeB5YG1EdFbldwG/AO5NST+LiC81r5tmZtYsA9nj3zciHu8n/+qIeHejHTIzs9bywV0zs8zUG/gDuFzS9ZJm9FFmH0k3S/qVpF2a1D8zM2uyeqd6JkfECkmvBq6QdGdEXFXKvwHYLiK6JU0Bfg7sVF1J+tCYAdDR0UGlUmms90NELuuZA4/l8NDd3Z31WGqgpytJOg3ojoiv9lNmGdDZ3zGBzs7OWLJkyYDaHop8Jsjw4bEcPnI5q0fS9dUn40AdUz2Sxkga17MMHADcVlVmc6UTZyW9MdX7RDM6bmZmzVXPVE8HcHGK6yOBH0XEIknHAETEbGAqcKyktcBq4LAYrr98MDMb4moG/oi4B9itl/TZpeVzgXOb2zUzM2sFn85pZpYZB34zs8w48JuZZcaB38wsMw78ZmaZceA3M8uMA7+ZWWYc+M3MMuPAb2aWGQd+M7PMOPCbmWXGN1vvx25fvJyVq9c0XM+EWQsbev340aO4+dQDGu6HmRk48Pdr5eo1DV9/vRnX/W70g8PMrMxTPWZmmXHgNzPLjAO/mVlmHPjNzDLjwG9mlpm6Ar+kZZJulXSTpCW95EvSOZLulnSLpD2a31UzM2uGgZzOuW9EPN5H3ruAndJjL+Db6a+ZmQ0yzZrqORiYH4U/AhtL2qJJdZuZWRPVG/gDuFzS9ZJm9JK/FbC89PyBlGZmZoNMvVM9kyNihaRXA1dIujMirhpoY+lDYwZAR0cHlUploFWsV+MmzmLX82c1XtH5jfYDKpUxjffDGjbY/2etPt3d3VmPZV2BPyJWpL+PSroYeCNQDvwrgG1Kz7dOadX1zAHmAHR2dkajlzJotWdnnTFoLtnQ9eHG6rAmWLSw4bG0waEZ78uhrOZUj6Qxksb1LAMHALdVFbsEOCKd3bM3sDIiHmp6b83MGrBgwQImTZrEfvvtx6RJk1iwYEG7u9QW9ezxdwAXS+op/6OIWCTpGICImA1cBkwB7gaeA45qTXfNzNbNggULOOmkk5g7dy7PP/88I0aMYPr06QBMmzatzb1bv2oG/oi4B9itl/TZpeUAPt7crpmZNc/pp5/O3Llz2Xffff8x1TN37lxmzpzpwG+Wo/SNtna5M2uXKfaDbLBZunQpkydPflHa5MmTWbp0aZt61D6+ZIMZRbCu9Vi8eHFd5WxwmjhxItdcc82L0q655homTpzYph61jwO/mWXhpJNOYvr06SxevJi1a9eyePFipk+fzkknndTurq13nuoxsyz0zOPPnDmTpUuXMnHiRE4//fTs5vfBgd/MMjJt2jSmTZvm8/jb3QEzM1u/vMdfQ1NudL6osTrGjx7VeB/MzBIH/n40erkGKD44mlGPmVmzeKrHzCwzDvxmZplx4Dczy4wDv5lZZhz4zcwy48BvZpYZB34zs8w48JuZZcaB38wsMw78ZmaZceA3M8tM3YFf0ghJN0q6tJe8IyU9Jumm9Phoc7tpZmbNMpCLtH0CWAq8oo/8CyPiPxrvkpmZtVJde/yStgYOBM5rbXfMzKzV6t3j/2/gc8C4fsq8X9JbgbuAT0bE8uoCkmYAMwA6OjqoVCoD6+0Qlct6Dnfd3d0ey2Ei97GsGfglvRt4NCKul9TVR7FfAgsi4m+SjgbOB95WXSgi5gBzADo7OyOLW58tWpj1Ld6Gk9xv1zec5D6W9Uz1vBk4SNIy4MfA2yRdUC4QEU9ExN/S0/OAPZvaSzMza5qagT8iToyIrSNiAnAYcGVEHF4uI2mL0tODKA4Cm5nZILTOt16U9CVgSURcAhwn6SBgLfAkcGRzumdmZs02oMAfERWgkpZPKaWfCJzYzI6ZmVlr+Je7ZmaZceA3M8uMA7+ZWWYc+M3MMuPAb2aWmXU+ndNAUn3lzuw/PyKa0Bszs/p4j78BEVHzsXjx4pplzMzWJwd+M7PMOPCbmWXGgd/MLDMO/GZmmXHgNzPLjAO/mVlmHPjNzDLjwG9mlhm16wdEkh4D7mtL4+vXZsDj7e6ENYXHcvjIZSy3i4hXVSe2LfDnQtKSiOhsdz+scR7L4SP3sfRUj5lZZhz4zcwy48DfenPa3QFrGo/l8JH1WHqO38wsM97jNzPLTNaBX1J3P3m/b2G7n29V3cNVu8aqHpK2lHTROr62Iinbs0ug9WMr6UuS9h/gaw6SNKtGmXUe93bLeqpHUndEjK1KGxkRa9d3u9a/do1Vq9uTVAE+ExFL6iw/IiKeb2Yf2q2N78Nhty3rlfUefw9JXZKulnQJcEdK605/t5B0laSbJN0m6S29vH4XSX9KZW6RtFNKP7yU/h1JIySdAYxOaT9M5T6V6r5N0vEpbYykhZJuTumHpvRTJF2X0uao3vs/DhONjJWk8ZLuk7RBej5G0nJJoyS9RtIiSden+l+XysyTNFvStcBXJP1rqv8mSTdKGidpgqTbUvkRkr6a2r9F0syUvl8qf6uk70l6WS/rNi3l3yb984adkrolfU3SzcA+Ldmwg0ALx3aepKkpfZmkMyXdABwiaYqkO9O4nyPp0lTuSEnnpuV5Ke/3ku4p1VXPuA/O92s9tw8crg+gO/3tAlYB2/eS92ngpLQ8AhjXSz3fAD6YljcERgMTgV8Co1L6t4AjynWn5T2BW4ExwFjgduBfgPcD3y2VG5/+blpK+wHwnnZvxyE2Vr8A9k3LhwLnpeXfADul5b2AK9PyPOBSYER6/kvgzWl5LMV9qycAt6W0Y4GLgJE94wW8HFgOvDalzQeOT8sVoBPYErgfeFWq80rgvalMAB9o9xgM4bGdB0xNy8uAz6XlnnHZPj1fAFyalo8Ezi29/icUO8qvB+5O6f2Oe/lvWh4071fv8f/TnyLi3l7SrwOOknQasGtEPNtLmT8An5d0AsVPpFcD+1EE9esk3ZSe79DLaycDF0fEqojoBn4GvIXiw+Dtae/kLRGxMpXfV9K1km4F3gbsss5rPHQ1MlYXUgQFgMOACyWNBd4E/CSN1XeALUqv+Un8c0rgd8D/lXQcsHG8dDpif+A7PekR8SSwM3BvRNyVypwPvLXqdW8AKhHxWHrtD0tlngd+2tuGGIaaOrZ9tNGT/jrgnlJ7C/rp188j4oWIuAPo6CW/t3GHQfp+deD/p1W9JUbEVRRvwBXAPElHSHpf6et+Z0T8CDgIWA1cJultgIDzI2L39Ng5Ik6rtzMpSOxB8QHwX+kr48spvjlMjYhdge9S7LXkZp3HCrgEeKekTSk+mK+keB88XRqr3SNiYm/tRcQZwEcpvtX9rmdKqMX+GvnMRTd7bOtuo4a/lZbrmq4ZzO9XB/4aJG0HPBIR3wXOA/aIiItLAWKJpB0o9hzOofi6+X8opg6mSnp1qmfTVBfAGkmj0vLVwHslbSRpDPA+4GpJWwLPRcQFwFkUHwI9/zSPp73UqS3fAENIPWOVvlVdB5xN8bX++Yh4BrhX0iGpHknarY82XhMRt0bEmame6sB/BXC0pJGp/KbAn4EJknZMZT4E/LbqdX8C/lXSZpJGANN6KZOtdR3bGtX+GdhB0oT0/NC+i9bU27gP2vfryHZ3YAjoAj4raQ3QDRzRS5kPAB9KZR4GvhwRT0o6Gbg8HXBaA3yc4oqkc4BbJN0QER+UNI/ijQ/FvOSNkt4BnCXphfTaYyPiaUnfBW5L7VzXonUeqrqoPVZQfNX/SSrf44PAt9OYjQJ+DNzcy2uPl7Qv8ALF8Zhf8eJpofOA11KM7xqK4zTnSjqKYippJMW4zS5XGhEPqTh9cDHFHuXCiPhFvSuegS7WfWx7FRGrJX0MWCRpFY29n/oa90H5fs36dE4zy5uksRHRnc62+Sbw/yLi6+3uV6t5qsfMcvbv6YD+7cB4igP7w573+M3MMuM9fjOzzDjwm5llxoHfzCwzDvw27KRrqKxOB+1a3dZlkjZeh9edJelhSZ9pRb/M+uPz+G24+ktE7N7qRiJiyjq+7rPp3HGz9c57/Dasqe+rnC6T9BUVV8P8U8+vaiW9StJP0xUVr5P05pQ+VtL3U/lbJL2/VM9mabm3q7GOUHF1x9vSaz/Zrm1h1sN7/DbcvRN4MCIOhOLyvaW8lRGxq6QjgP8G3k3xc/+vR8Q1krYFfk1xpdUv9JRP9WxSbkTSRIqf/L85ItZI+hbFr4FvB7aKiEmp3ICnhcyazYHfhrtbga+puL79pRFxdSlvQelvz6819wder39eNv0V6Tor+1Nc8RGAiHiqqp3y1VihuIjboxSXcd5B0jeAhcDlTVovs3XmwG/DWkTcJWkPYArFVU5/ExFf6skuF01/NwD2joi/lutR7ftn9FyN9cSXZBQXfHsHcAzFdZ0+MuAVMWsiz/HbsNbHVU57HFr6+4e0fDkws/T6ngPEV1BcZK8n/UVTPfRxNdY0/79BRPwUOLmqfbO28B6/DXe7UnWV01LeJpJuobjW+rSUdhzwzZQ+EriKYk/9v1L6bRQ3RvkixU1zAIiIO/q4Gutq4PspDeAl3wjM1jdfq8eGnXR99Ut7Dqj2UWYZ0BkRj6+nbvXWh9Mobi341Xb1wfLkqR4bjp4Hxq+PH3CtK0lnAYezbneDMmuI9/jNzDLjPX4zs8w48JuZZcaB38wsMw78ZmaZceA3M8uMA7+ZWWb+P5U47ahYR72rAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "data.boxplot(column=[0], by=['species'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's tricky to do subplots, but worth it. We can see setosa has smaller petals than the other 2 species. And versicolor has, on average, smaller sepals and smaller petals than virginica; but there is some overlap." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'petal_width')" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(2, 2, figsize=(8, 6))\n", + "A = [data[0][data.species == 'Iris-setosa'], data[0][data.species == 'Iris-virginica'], data[0][data.species == 'Iris-versicolor']]\n", + "B = [data[1][data.species == 'Iris-setosa'], data[1][data.species == 'Iris-virginica'], data[1][data.species == 'Iris-versicolor']]\n", + "C = [data[2][data.species == 'Iris-setosa'], data[2][data.species == 'Iris-virginica'], data[2][data.species == 'Iris-versicolor']]\n", + "D = [data[3][data.species == 'Iris-setosa'], data[3][data.species == 'Iris-virginica'], data[3][data.species == 'Iris-versicolor']]\n", + "\n", + "ax[0, 0].boxplot(A, widths = 0.7)\n", + "ax[0, 0].set_title(cols[0])\n", + "ax[0, 1].boxplot(B, widths = 0.7)\n", + "ax[0, 1].set_title(cols[1])\n", + "ax[1, 0].boxplot(C, widths = 0.7)\n", + "ax[1, 0].set_title(cols[2])\n", + "ax[1, 1].boxplot(D, widths = 0.7)\n", + "ax[1, 1].set_title(cols[3])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This plot does an awsome job of showing distributions of all 4 attributes for all 3 species. 12 box plots in 1 graph! The color coding makes it more readable. " + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/ipykernel_launcher.py:21: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "def set_color(bp):\n", + " plt.setp(bp['boxes'][0], color='blue')\n", + " plt.setp(bp['boxes'][1], color='red')\n", + " plt.setp(bp['boxes'][2], color='green')\n", + "\n", + "A = [data[0][data.species == 'Iris-setosa'], data[0][data.species == 'Iris-virginica'], data[0][data.species == 'Iris-versicolor']]\n", + "B = [data[1][data.species == 'Iris-setosa'], data[1][data.species == 'Iris-virginica'], data[1][data.species == 'Iris-versicolor']]\n", + "C = [data[2][data.species == 'Iris-setosa'], data[2][data.species == 'Iris-virginica'], data[2][data.species == 'Iris-versicolor']]\n", + "D = [data[3][data.species == 'Iris-setosa'], data[3][data.species == 'Iris-virginica'], data[3][data.species == 'Iris-versicolor']]\n", + "\n", + "# add this to remove outlier symbols: 0, '',\n", + "bp = plt.boxplot(A, 0, '', positions = [1, 2, 3], widths = 0.7)\n", + "set_color(bp)\n", + "bp = plt.boxplot(B, 0, '', positions = [5, 6, 7], widths = 0.7)\n", + "set_color(bp)\n", + "bp = plt.boxplot(C, 0, '', positions = [9, 10, 11], widths = 0.7)\n", + "set_color(bp)\n", + "bp = plt.boxplot(D, 0, '', positions = [13, 14, 15], widths = 0.7)\n", + "set_color(bp)\n", + "\n", + "ax = plt.axes()\n", + "ax.set_xticks([2, 6, 10, 14])\n", + "ax.set_xticklabels(cols)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Iris Dataset/KNN-IrisData.ipynb b/Iris Dataset/KNN-IrisData.ipynb new file mode 100644 index 00000000..d49be354 --- /dev/null +++ b/Iris Dataset/KNN-IrisData.ipynb @@ -0,0 +1,629 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Classification \n", + "predict which group a new target object belongs to by comparing it to identified objects. The identified, or labeled objects are called the training set." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## KNN - K-Nearest Neighbors\n", + "Find the k nearest objects to the target object using some distance metric. Then these k nearest neighbors get to vote on the identity of the target object. \n", + "For example, if k=5, we find the 5 nearest objects in our training set. If three of them are apples, one is a pear and one is an orange then we predict our target object is an apple. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
idsepal_lengthsepal_widthpetal_lengthpetal_widthspecies
005.13.51.40.2Iris-setosa
114.93.01.40.2Iris-setosa
224.73.21.30.2Iris-setosa
334.63.11.50.2Iris-setosa
445.03.61.40.2Iris-setosa
\n", + "
" + ], + "text/plain": [ + " id sepal_length sepal_width petal_length petal_width species\n", + "0 0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 4 5.0 3.6 1.4 0.2 Iris-setosa" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train = pd.read_csv('iris.data')\n", + "train.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Rename columns of training set, and add a column for distance." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
0123speciesdistance
05.13.51.40.2Iris-setosa9999
14.93.01.40.2Iris-setosa9999
24.73.21.30.2Iris-setosa9999
34.63.11.50.2Iris-setosa9999
45.03.61.40.2Iris-setosa9999
\n", + "
" + ], + "text/plain": [ + " 0 1 2 3 species distance\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa 9999\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa 9999\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa 9999\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa 9999\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa 9999" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train = train.drop('id', 1)\n", + "cols = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']\n", + "train.rename(columns = {cols[0]:0, cols[1]:1, cols[2]:2, cols[3]:3}, inplace=True)\n", + "train['distance'] = 9999\n", + "train.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an unidentified Target instance, then we will try to predict its species using knn." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0 7.0\n", + "1 3.1\n", + "2 5.6\n", + "3 1.9\n", + "dtype: float64" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "target = pd.Series([7.0, 3.1, 5.6, 1.9])\n", + "target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Distance\n", + "There are a variety of ways to measure [distance](https://towardsdatascience.com/9-distance-measures-in-data-science-918109d069fa). If there are many attributes, we may use a subset of the attributes to compare objects. \n", + "We'll use Euclidean distance, similar to Pythagorean Theorem but scaled to more attributes. \n", + "We compute the distance of every training instance from the target." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \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", + "
0123speciesdistance
05.13.51.40.2Iris-setosa4.929503
105.43.71.50.2Iris-setosa4.756049
205.43.41.70.2Iris-setosa4.555217
304.83.11.60.2Iris-setosa4.871345
405.03.51.30.3Iris-setosa5.020956
507.03.24.71.4Iris-versicolor1.034408
605.02.03.51.0Iris-versicolor3.229551
705.93.24.81.8Iris-versicolor1.367479
805.52.43.81.1Iris-versicolor2.572936
905.52.64.41.2Iris-versicolor2.104757
1006.33.36.02.5Iris-virginica1.024695
1106.53.25.12.0Iris-virginica0.721110
1206.93.25.72.3Iris-virginica0.435890
1307.42.86.11.9Iris-virginica0.707107
1406.73.15.62.4Iris-virginica0.583095
\n", + "
" + ], + "text/plain": [ + " 0 1 2 3 species distance\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa 4.929503\n", + "10 5.4 3.7 1.5 0.2 Iris-setosa 4.756049\n", + "20 5.4 3.4 1.7 0.2 Iris-setosa 4.555217\n", + "30 4.8 3.1 1.6 0.2 Iris-setosa 4.871345\n", + "40 5.0 3.5 1.3 0.3 Iris-setosa 5.020956\n", + "50 7.0 3.2 4.7 1.4 Iris-versicolor 1.034408\n", + "60 5.0 2.0 3.5 1.0 Iris-versicolor 3.229551\n", + "70 5.9 3.2 4.8 1.8 Iris-versicolor 1.367479\n", + "80 5.5 2.4 3.8 1.1 Iris-versicolor 2.572936\n", + "90 5.5 2.6 4.4 1.2 Iris-versicolor 2.104757\n", + "100 6.3 3.3 6.0 2.5 Iris-virginica 1.024695\n", + "110 6.5 3.2 5.1 2.0 Iris-virginica 0.721110\n", + "120 6.9 3.2 5.7 2.3 Iris-virginica 0.435890\n", + "130 7.4 2.8 6.1 1.9 Iris-virginica 0.707107\n", + "140 6.7 3.1 5.6 2.4 Iris-virginica 0.583095" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train['distance'] = ((train.loc[:,0]-target[0])**2 + (train.loc[:,1]-target[1])**2 + (train.loc[:,2]-target[2])**2 + (train.loc[:,3]-target[3])**2) ** 0.5\n", + "train.loc[::10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We sort the training records by distance, and add the species of the (k=7) items nearest to the target to a list." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Iris-virginica',\n", + " 'Iris-virginica',\n", + " 'Iris-virginica',\n", + " 'Iris-virginica',\n", + " 'Iris-virginica',\n", + " 'Iris-virginica',\n", + " 'Iris-virginica']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "k = 7\n", + "train = train.sort_values('distance', ascending=True)\n", + "knn = list(train.head(k).species)\n", + "knn" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We use mode to get the most popular of the knn list. In this example the whole knn list is Iris-virginica, so our prediction is obvious. But sometimes the list of nearest neighbors will be a variety, and the mode tells us our prediction." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iris-virginica\n" + ] + } + ], + "source": [ + "from statistics import mode\n", + "print(mode(knn))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To check our prediction, we plot the training set on a scatter plot, then plot our target. Here we can see our target is surrounded by Iris-virginica instances, so our prediction is probably correct." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Iris Data Scatter Plot')" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "colors = {'Iris-setosa':'red', 'Iris-virginica':'blue', 'Iris-versicolor':'green'}\n", + "plt.scatter(\n", + " train[2], \n", + " train[3], \n", + " c=train['species'].map(colors))\n", + "plt.scatter(target[2], target[3], c='orange')\n", + "plt.xlabel(cols[2])\n", + "plt.ylabel(cols[3])\n", + "plt.title('Iris Data Scatter Plot')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Iris Dataset/iris.data b/Iris Dataset/iris.data new file mode 100644 index 00000000..835f8b44 --- /dev/null +++ b/Iris Dataset/iris.data @@ -0,0 +1,151 @@ +id,sepal_length,sepal_width,petal_length,petal_width,species +0,5.1,3.5,1.4,0.2,Iris-setosa +1,4.9,3.0,1.4,0.2,Iris-setosa +2,4.7,3.2,1.3,0.2,Iris-setosa +3,4.6,3.1,1.5,0.2,Iris-setosa +4,5.0,3.6,1.4,0.2,Iris-setosa +5,5.4,3.9,1.7,0.4,Iris-setosa +6,4.6,3.4,1.4,0.3,Iris-setosa +7,5.0,3.4,1.5,0.2,Iris-setosa +8,4.4,2.9,1.4,0.2,Iris-setosa +9,4.9,3.1,1.5,0.1,Iris-setosa +10,5.4,3.7,1.5,0.2,Iris-setosa +11,4.8,3.4,1.6,0.2,Iris-setosa +12,4.8,3.0,1.4,0.1,Iris-setosa +13,4.3,3.0,1.1,0.1,Iris-setosa +14,5.8,4.0,1.2,0.2,Iris-setosa +15,5.7,4.4,1.5,0.4,Iris-setosa +16,5.4,3.9,1.3,0.4,Iris-setosa +17,5.1,3.5,1.4,0.3,Iris-setosa +18,5.7,3.8,1.7,0.3,Iris-setosa +19,5.1,3.8,1.5,0.3,Iris-setosa +20,5.4,3.4,1.7,0.2,Iris-setosa +21,5.1,3.7,1.5,0.4,Iris-setosa +22,4.6,3.6,1.0,0.2,Iris-setosa +23,5.1,3.3,1.7,0.5,Iris-setosa +24,4.8,3.4,1.9,0.2,Iris-setosa +25,5.0,3.0,1.6,0.2,Iris-setosa +26,5.0,3.4,1.6,0.4,Iris-setosa +27,5.2,3.5,1.5,0.2,Iris-setosa +28,5.2,3.4,1.4,0.2,Iris-setosa +29,4.7,3.2,1.6,0.2,Iris-setosa +30,4.8,3.1,1.6,0.2,Iris-setosa +31,5.4,3.4,1.5,0.4,Iris-setosa +32,5.2,4.1,1.5,0.1,Iris-setosa +33,5.5,4.2,1.4,0.2,Iris-setosa +34,4.9,3.1,1.5,0.1,Iris-setosa +35,5.0,3.2,1.2,0.2,Iris-setosa +36,5.5,3.5,1.3,0.2,Iris-setosa +37,4.9,3.1,1.5,0.1,Iris-setosa +38,4.4,3.0,1.3,0.2,Iris-setosa +39,5.1,3.4,1.5,0.2,Iris-setosa +40,5.0,3.5,1.3,0.3,Iris-setosa +41,4.5,2.3,1.3,0.3,Iris-setosa +42,4.4,3.2,1.3,0.2,Iris-setosa +43,5.0,3.5,1.6,0.6,Iris-setosa +44,5.1,3.8,1.9,0.4,Iris-setosa +45,4.8,3.0,1.4,0.3,Iris-setosa +46,5.1,3.8,1.6,0.2,Iris-setosa +47,4.6,3.2,1.4,0.2,Iris-setosa +48,5.3,3.7,1.5,0.2,Iris-setosa +49,5.0,3.3,1.4,0.2,Iris-setosa +50,7.0,3.2,4.7,1.4,Iris-versicolor +51,6.4,3.2,4.5,1.5,Iris-versicolor +52,6.9,3.1,4.9,1.5,Iris-versicolor +53,5.5,2.3,4.0,1.3,Iris-versicolor +54,6.5,2.8,4.6,1.5,Iris-versicolor +55,5.7,2.8,4.5,1.3,Iris-versicolor +56,6.3,3.3,4.7,1.6,Iris-versicolor +57,4.9,2.4,3.3,1.0,Iris-versicolor +58,6.6,2.9,4.6,1.3,Iris-versicolor +59,5.2,2.7,3.9,1.4,Iris-versicolor +60,5.0,2.0,3.5,1.0,Iris-versicolor +61,5.9,3.0,4.2,1.5,Iris-versicolor +62,6.0,2.2,4.0,1.0,Iris-versicolor +63,6.1,2.9,4.7,1.4,Iris-versicolor +64,5.6,2.9,3.6,1.3,Iris-versicolor +65,6.7,3.1,4.4,1.4,Iris-versicolor +66,5.6,3.0,4.5,1.5,Iris-versicolor +67,5.8,2.7,4.1,1.0,Iris-versicolor +68,6.2,2.2,4.5,1.5,Iris-versicolor +69,5.6,2.5,3.9,1.1,Iris-versicolor +70,5.9,3.2,4.8,1.8,Iris-versicolor +71,6.1,2.8,4.0,1.3,Iris-versicolor +72,6.3,2.5,4.9,1.5,Iris-versicolor +73,6.1,2.8,4.7,1.2,Iris-versicolor +74,6.4,2.9,4.3,1.3,Iris-versicolor +75,6.6,3.0,4.4,1.4,Iris-versicolor +76,6.8,2.8,4.8,1.4,Iris-versicolor +77,6.7,3.0,5.0,1.7,Iris-versicolor +78,6.0,2.9,4.5,1.5,Iris-versicolor +79,5.7,2.6,3.5,1.0,Iris-versicolor +80,5.5,2.4,3.8,1.1,Iris-versicolor +81,5.5,2.4,3.7,1.0,Iris-versicolor +82,5.8,2.7,3.9,1.2,Iris-versicolor +83,6.0,2.7,5.1,1.6,Iris-versicolor +84,5.4,3.0,4.5,1.5,Iris-versicolor +85,6.0,3.4,4.5,1.6,Iris-versicolor +86,6.7,3.1,4.7,1.5,Iris-versicolor +87,6.3,2.3,4.4,1.3,Iris-versicolor +88,5.6,3.0,4.1,1.3,Iris-versicolor +89,5.5,2.5,4.0,1.3,Iris-versicolor +90,5.5,2.6,4.4,1.2,Iris-versicolor +91,6.1,3.0,4.6,1.4,Iris-versicolor +92,5.8,2.6,4.0,1.2,Iris-versicolor +93,5.0,2.3,3.3,1.0,Iris-versicolor +94,5.6,2.7,4.2,1.3,Iris-versicolor +95,5.7,3.0,4.2,1.2,Iris-versicolor +96,5.7,2.9,4.2,1.3,Iris-versicolor +97,6.2,2.9,4.3,1.3,Iris-versicolor +98,5.1,2.5,3.0,1.1,Iris-versicolor +99,5.7,2.8,4.1,1.3,Iris-versicolor +100,6.3,3.3,6.0,2.5,Iris-virginica +101,5.8,2.7,5.1,1.9,Iris-virginica +102,7.1,3.0,5.9,2.1,Iris-virginica +103,6.3,2.9,5.6,1.8,Iris-virginica +104,6.5,3.0,5.8,2.2,Iris-virginica +105,7.6,3.0,6.6,2.1,Iris-virginica +106,4.9,2.5,4.5,1.7,Iris-virginica +107,7.3,2.9,6.3,1.8,Iris-virginica +108,6.7,2.5,5.8,1.8,Iris-virginica +109,7.2,3.6,6.1,2.5,Iris-virginica +110,6.5,3.2,5.1,2.0,Iris-virginica +111,6.4,2.7,5.3,1.9,Iris-virginica +112,6.8,3.0,5.5,2.1,Iris-virginica +113,5.7,2.5,5.0,2.0,Iris-virginica +114,5.8,2.8,5.1,2.4,Iris-virginica +115,6.4,3.2,5.3,2.3,Iris-virginica +116,6.5,3.0,5.5,1.8,Iris-virginica +117,7.7,3.8,6.7,2.2,Iris-virginica +118,7.7,2.6,6.9,2.3,Iris-virginica +119,6.0,2.2,5.0,1.5,Iris-virginica +120,6.9,3.2,5.7,2.3,Iris-virginica +121,5.6,2.8,4.9,2.0,Iris-virginica +122,7.7,2.8,6.7,2.0,Iris-virginica +123,6.3,2.7,4.9,1.8,Iris-virginica +124,6.7,3.3,5.7,2.1,Iris-virginica +125,7.2,3.2,6.0,1.8,Iris-virginica +126,6.2,2.8,4.8,1.8,Iris-virginica +127,6.1,3.0,4.9,1.8,Iris-virginica +128,6.4,2.8,5.6,2.1,Iris-virginica +129,7.2,3.0,5.8,1.6,Iris-virginica +130,7.4,2.8,6.1,1.9,Iris-virginica +131,7.9,3.8,6.4,2.0,Iris-virginica +132,6.4,2.8,5.6,2.2,Iris-virginica +133,6.3,2.8,5.1,1.5,Iris-virginica +134,6.1,2.6,5.6,1.4,Iris-virginica +135,7.7,3.0,6.1,2.3,Iris-virginica +136,6.3,3.4,5.6,2.4,Iris-virginica +137,6.4,3.1,5.5,1.8,Iris-virginica +138,6.0,3.0,4.8,1.8,Iris-virginica +139,6.9,3.1,5.4,2.1,Iris-virginica +140,6.7,3.1,5.6,2.4,Iris-virginica +141,6.9,3.1,5.1,2.3,Iris-virginica +142,5.8,2.7,5.1,1.9,Iris-virginica +143,6.8,3.2,5.9,2.3,Iris-virginica +144,6.7,3.3,5.7,2.5,Iris-virginica +145,6.7,3.0,5.2,2.3,Iris-virginica +146,6.3,2.5,5.0,1.9,Iris-virginica +147,6.5,3.0,5.2,2.0,Iris-virginica +148,6.2,3.4,5.4,2.3,Iris-virginica +149,5.9,3.0,5.1,1.8,Iris-virginica diff --git a/LinkedLists/CircularLinkedList.py b/LinkedLists/CircularLinkedList.py index b6733be7..48a5a9df 100644 --- a/LinkedLists/CircularLinkedList.py +++ b/LinkedLists/CircularLinkedList.py @@ -16,7 +16,7 @@ def get_data (self): def set_data (self, d): self.data = d - def to_string (self): + def __str__(self): return "Node value: " + str(self.data) class CircularLinkedList (object): @@ -71,10 +71,10 @@ def print_list (self): if self.root is None: return this_node = self.root - print (this_node.to_string()) + print (this_node) while this_node.get_next() != self.root: this_node = this_node.get_next() - print (this_node.to_string()) + print (this_node) def main(): myList = CircularLinkedList() @@ -87,10 +87,10 @@ def main(): print("Find 12", myList.find(12)) cur = myList.root - print (cur.to_string()) + print (cur) for i in range(8): cur = cur.get_next(); - print (cur.to_string()) + print (cur) print("size="+str(myList.get_size())) myList.print_list() diff --git a/Object Oriented Programming/building our first class.py b/Object Oriented Programming/building our first class.py new file mode 100644 index 00000000..51411d5e --- /dev/null +++ b/Object Oriented Programming/building our first class.py @@ -0,0 +1,20 @@ +#Today we will learn how to create a class and other attributes of class +#Below is the method how classes are defined +class Student: + pass + +#Below is the method to create object , Here Varun and rohan are two objects of Class Student +Varun = Student() +larry = Student() + +# Now after creating objects we can use them to call variables +Varun.name = "Harry" +Varun.std = 12 +Varun.section = 1 +larry.std = 9 +larry.subjects = ["hindi", "physics"] +print(Varun.section, larry.subjects) + + + + diff --git a/Pandas/Pandas - Change Column Names.ipynb b/Pandas/Pandas - Change Column Names.ipynb new file mode 100644 index 00000000..aa84e79c --- /dev/null +++ b/Pandas/Pandas - Change Column Names.ipynb @@ -0,0 +1,364 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pandas - Change Column Names" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ABCDLabel
05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa
..................
1456.73.05.22.3Iris-virginica
1466.32.55.01.9Iris-virginica
1476.53.05.22.0Iris-virginica
1486.23.45.42.3Iris-virginica
1495.93.05.11.8Iris-virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " A B C D Label\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('iris.data', names=['A','B','C','D','Label'])\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "axis=1 tells Pandas it's column names. \n", + "inplace=True tells Pandas to save the changes to our DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
aabbCDLabel
05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa
..................
1456.73.05.22.3Iris-virginica
1466.32.55.01.9Iris-virginica
1476.53.05.22.0Iris-virginica
1486.23.45.42.3Iris-virginica
1495.93.05.11.8Iris-virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " aa bb C D Label\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.rename({'A':'aa', 'B':'bb'}, axis=1, inplace=True)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pandas/Pandas - Delete Columns from DataFrame.ipynb b/Pandas/Pandas - Delete Columns from DataFrame.ipynb new file mode 100644 index 00000000..28293203 --- /dev/null +++ b/Pandas/Pandas - Delete Columns from DataFrame.ipynb @@ -0,0 +1,757 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pandas - Delete Columns from a DataFrame" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ABCDLabel
05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa
..................
1456.73.05.22.3Iris-virginica
1466.32.55.01.9Iris-virginica
1476.53.05.22.0Iris-virginica
1486.23.45.42.3Iris-virginica
1495.93.05.11.8Iris-virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " A B C D Label\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('iris.data', names=['A','B','C','D','Label'])\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1) to drop a single column\n, and saving it permanently ", + "df.drop('col_name', axis=1,inplace =True) \n", + "To save changes you must either set df = df.drop(), or add inplace=True." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
ACDLabel
05.11.40.2Iris-setosa
14.91.40.2Iris-setosa
24.71.30.2Iris-setosa
34.61.50.2Iris-setosa
45.01.40.2Iris-setosa
...............
1456.75.22.3Iris-virginica
1466.35.01.9Iris-virginica
1476.55.22.0Iris-virginica
1486.25.42.3Iris-virginica
1495.95.11.8Iris-virginica
\n", + "

150 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " A C D Label\n", + "0 5.1 1.4 0.2 Iris-setosa\n", + "1 4.9 1.4 0.2 Iris-setosa\n", + "2 4.7 1.3 0.2 Iris-setosa\n", + "3 4.6 1.5 0.2 Iris-setosa\n", + "4 5.0 1.4 0.2 Iris-setosa\n", + ".. ... ... ... ...\n", + "145 6.7 5.2 2.3 Iris-virginica\n", + "146 6.3 5.0 1.9 Iris-virginica\n", + "147 6.5 5.2 2.0 Iris-virginica\n", + "148 6.2 5.4 2.3 Iris-virginica\n", + "149 5.9 5.1 1.8 Iris-virginica\n", + "\n", + "[150 rows x 4 columns]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.drop('B', axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ABCDLabel
05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa
..................
1456.73.05.22.3Iris-virginica
1466.32.55.01.9Iris-virginica
1476.53.05.22.0Iris-virginica
1486.23.45.42.3Iris-virginica
1495.93.05.11.8Iris-virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " A B C D Label\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2) to drop multiple axes by name\n", + "df.drop(['col_name1', 'col_name2'], axis=1, inplace=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
BCD
03.51.40.2
13.01.40.2
23.21.30.2
33.11.50.2
43.61.40.2
............
1453.05.22.3
1462.55.01.9
1473.05.22.0
1483.45.42.3
1493.05.11.8
\n", + "

150 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " B C D\n", + "0 3.5 1.4 0.2\n", + "1 3.0 1.4 0.2\n", + "2 3.2 1.3 0.2\n", + "3 3.1 1.5 0.2\n", + "4 3.6 1.4 0.2\n", + ".. ... ... ...\n", + "145 3.0 5.2 2.3\n", + "146 2.5 5.0 1.9\n", + "147 3.0 5.2 2.0\n", + "148 3.4 5.4 2.3\n", + "149 3.0 5.1 1.8\n", + "\n", + "[150 rows x 3 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.drop(['A','Label'], axis=1, inplace=True)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3) to drop multiple axes by numerical column index\n", + "df.drop(df.columns[[idx1, idx2]], axis=1, inplace=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
C
01.4
11.4
21.3
31.5
41.4
......
1455.2
1465.0
1475.2
1485.4
1495.1
\n", + "

150 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " C\n", + "0 1.4\n", + "1 1.4\n", + "2 1.3\n", + "3 1.5\n", + "4 1.4\n", + ".. ...\n", + "145 5.2\n", + "146 5.0\n", + "147 5.2\n", + "148 5.4\n", + "149 5.1\n", + "\n", + "[150 rows x 1 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.drop(df.columns[[0, 2]], axis=1, inplace=True)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pandas/Pandas - Delete NaN Rows from DataFrame.ipynb b/Pandas/Pandas - Delete NaN Rows from DataFrame.ipynb new file mode 100644 index 00000000..79d4b0af --- /dev/null +++ b/Pandas/Pandas - Delete NaN Rows from DataFrame.ipynb @@ -0,0 +1,655 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pandas - Delete NaN Rows from DataFrame" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[StackOverflow Thread](https://stackoverflow.com/questions/13413590/how-to-drop-rows-of-pandas-dataframe-whose-value-in-a-certain-column-is-nan)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
012
0-1.358720-0.4939670.258351
10.3383470.498426-0.050406
20.821865-0.376314-1.504425
3-0.5518760.6945950.540055
4-0.493108-0.5702550.160218
5-0.705264-1.9409840.321970
60.2571330.642613-0.416996
7-1.391762-1.689991-1.804575
81.459479-0.731590-0.061360
91.314401-1.666592-1.778455
10-0.353425-0.654705-0.155042
11-0.898696-0.7568020.539142
\n", + "
" + ], + "text/plain": [ + " 0 1 2\n", + "0 -1.358720 -0.493967 0.258351\n", + "1 0.338347 0.498426 -0.050406\n", + "2 0.821865 -0.376314 -1.504425\n", + "3 -0.551876 0.694595 0.540055\n", + "4 -0.493108 -0.570255 0.160218\n", + "5 -0.705264 -1.940984 0.321970\n", + "6 0.257133 0.642613 -0.416996\n", + "7 -1.391762 -1.689991 -1.804575\n", + "8 1.459479 -0.731590 -0.061360\n", + "9 1.314401 -1.666592 -1.778455\n", + "10 -0.353425 -0.654705 -0.155042\n", + "11 -0.898696 -0.756802 0.539142" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.DataFrame(np.random.randn(12,3))\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
012
0NaNNaNNaN
10.3383470.498426-0.050406
2NaN-0.376314-1.504425
3-0.551876NaN0.540055
4NaN-0.570255NaN
5-0.705264-1.9409840.321970
6NaNNaN-0.416996
7-1.391762-1.689991-1.804575
8NaN-0.731590NaN
91.314401NaN-1.778455
10NaN-0.654705-0.155042
11-0.898696-0.7568020.539142
\n", + "
" + ], + "text/plain": [ + " 0 1 2\n", + "0 NaN NaN NaN\n", + "1 0.338347 0.498426 -0.050406\n", + "2 NaN -0.376314 -1.504425\n", + "3 -0.551876 NaN 0.540055\n", + "4 NaN -0.570255 NaN\n", + "5 -0.705264 -1.940984 0.321970\n", + "6 NaN NaN -0.416996\n", + "7 -1.391762 -1.689991 -1.804575\n", + "8 NaN -0.731590 NaN\n", + "9 1.314401 NaN -1.778455\n", + "10 NaN -0.654705 -0.155042\n", + "11 -0.898696 -0.756802 0.539142" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.iloc[::2,0] = np.nan\n", + "df.iloc[::3,1] = np.nan\n", + "df.iloc[::4,2] = np.nan\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**- Drop all rows that have *any* NaN values**" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
012
10.3383470.498426-0.050406
5-0.705264-1.9409840.321970
7-1.391762-1.689991-1.804575
11-0.898696-0.7568020.539142
\n", + "
" + ], + "text/plain": [ + " 0 1 2\n", + "1 0.338347 0.498426 -0.050406\n", + "5 -0.705264 -1.940984 0.321970\n", + "7 -1.391762 -1.689991 -1.804575\n", + "11 -0.898696 -0.756802 0.539142" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.dropna()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**- drop only if *all* columns are NaN**" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
012
10.3383470.498426-0.050406
2NaN-0.376314-1.504425
3-0.551876NaN0.540055
4NaN-0.570255NaN
5-0.705264-1.9409840.321970
6NaNNaN-0.416996
7-1.391762-1.689991-1.804575
8NaN-0.731590NaN
91.314401NaN-1.778455
10NaN-0.654705-0.155042
11-0.898696-0.7568020.539142
\n", + "
" + ], + "text/plain": [ + " 0 1 2\n", + "1 0.338347 0.498426 -0.050406\n", + "2 NaN -0.376314 -1.504425\n", + "3 -0.551876 NaN 0.540055\n", + "4 NaN -0.570255 NaN\n", + "5 -0.705264 -1.940984 0.321970\n", + "6 NaN NaN -0.416996\n", + "7 -1.391762 -1.689991 -1.804575\n", + "8 NaN -0.731590 NaN\n", + "9 1.314401 NaN -1.778455\n", + "10 NaN -0.654705 -0.155042\n", + "11 -0.898696 -0.756802 0.539142" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.dropna(how='all')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**- Drop only if NaN in a specific column**" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
012
10.3383470.498426-0.050406
2NaN-0.376314-1.504425
3-0.551876NaN0.540055
5-0.705264-1.9409840.321970
6NaNNaN-0.416996
7-1.391762-1.689991-1.804575
91.314401NaN-1.778455
10NaN-0.654705-0.155042
11-0.898696-0.7568020.539142
\n", + "
" + ], + "text/plain": [ + " 0 1 2\n", + "1 0.338347 0.498426 -0.050406\n", + "2 NaN -0.376314 -1.504425\n", + "3 -0.551876 NaN 0.540055\n", + "5 -0.705264 -1.940984 0.321970\n", + "6 NaN NaN -0.416996\n", + "7 -1.391762 -1.689991 -1.804575\n", + "9 1.314401 NaN -1.778455\n", + "10 NaN -0.654705 -0.155042\n", + "11 -0.898696 -0.756802 0.539142" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.dropna(subset=[2])" + ] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pandas/Pandas - Iterate Rows of a DataFrame.ipynb b/Pandas/Pandas - Iterate Rows of a DataFrame.ipynb new file mode 100644 index 00000000..e911a4be --- /dev/null +++ b/Pandas/Pandas - Iterate Rows of a DataFrame.ipynb @@ -0,0 +1,723 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pandas - Iterate Rows of a DataFrame " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01234
05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa
..................
1456.73.05.22.3Iris-virginica
1466.32.55.01.9Iris-virginica
1476.53.05.22.0Iris-virginica
1486.23.45.42.3Iris-virginica
1495.93.05.11.8Iris-virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " 0 1 2 3 4\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('iris.data', header=None)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a List of one Column\n", + "Use a list comprehension." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1.4,\n", + " 1.4,\n", + " 1.3,\n", + " 1.5,\n", + " 1.4,\n", + " 1.7,\n", + " 1.4,\n", + " 1.5,\n", + " 1.4,\n", + " 1.5,\n", + " 1.5,\n", + " 1.6,\n", + " 1.4,\n", + " 1.1,\n", + " 1.2,\n", + " 1.5,\n", + " 1.3,\n", + " 1.4,\n", + " 1.7,\n", + " 1.5,\n", + " 1.7,\n", + " 1.5,\n", + " 1.0,\n", + " 1.7,\n", + " 1.9,\n", + " 1.6,\n", + " 1.6,\n", + " 1.5,\n", + " 1.4,\n", + " 1.6,\n", + " 1.6,\n", + " 1.5,\n", + " 1.5,\n", + " 1.4,\n", + " 1.5,\n", + " 1.2,\n", + " 1.3,\n", + " 1.5,\n", + " 1.3,\n", + " 1.5,\n", + " 1.3,\n", + " 1.3,\n", + " 1.3,\n", + " 1.6,\n", + " 1.9,\n", + " 1.4,\n", + " 1.6,\n", + " 1.4,\n", + " 1.5,\n", + " 1.4,\n", + " 4.7,\n", + " 4.5,\n", + " 4.9,\n", + " 4.0,\n", + " 4.6,\n", + " 4.5,\n", + " 4.7,\n", + " 3.3,\n", + " 4.6,\n", + " 3.9,\n", + " 3.5,\n", + " 4.2,\n", + " 4.0,\n", + " 4.7,\n", + " 3.6,\n", + " 4.4,\n", + " 4.5,\n", + " 4.1,\n", + " 4.5,\n", + " 3.9,\n", + " 4.8,\n", + " 4.0,\n", + " 4.9,\n", + " 4.7,\n", + " 4.3,\n", + " 4.4,\n", + " 4.8,\n", + " 5.0,\n", + " 4.5,\n", + " 3.5,\n", + " 3.8,\n", + " 3.7,\n", + " 3.9,\n", + " 5.1,\n", + " 4.5,\n", + " 4.5,\n", + " 4.7,\n", + " 4.4,\n", + " 4.1,\n", + " 4.0,\n", + " 4.4,\n", + " 4.6,\n", + " 4.0,\n", + " 3.3,\n", + " 4.2,\n", + " 4.2,\n", + " 4.2,\n", + " 4.3,\n", + " 3.0,\n", + " 4.1,\n", + " 6.0,\n", + " 5.1,\n", + " 5.9,\n", + " 5.6,\n", + " 5.8,\n", + " 6.6,\n", + " 4.5,\n", + " 6.3,\n", + " 5.8,\n", + " 6.1,\n", + " 5.1,\n", + " 5.3,\n", + " 5.5,\n", + " 5.0,\n", + " 5.1,\n", + " 5.3,\n", + " 5.5,\n", + " 6.7,\n", + " 6.9,\n", + " 5.0,\n", + " 5.7,\n", + " 4.9,\n", + " 6.7,\n", + " 4.9,\n", + " 5.7,\n", + " 6.0,\n", + " 4.8,\n", + " 4.9,\n", + " 5.6,\n", + " 5.8,\n", + " 6.1,\n", + " 6.4,\n", + " 5.6,\n", + " 5.1,\n", + " 5.6,\n", + " 6.1,\n", + " 5.6,\n", + " 5.5,\n", + " 4.8,\n", + " 5.4,\n", + " 5.6,\n", + " 5.1,\n", + " 5.1,\n", + " 5.9,\n", + " 5.7,\n", + " 5.2,\n", + " 5.0,\n", + " 5.2,\n", + " 5.4,\n", + " 5.1]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "col2 = [x for x in df[2]]\n", + "col2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Iterate Rows with Index and each Row as a List\n", + "**DO NOT** try to change data in the df this way, but it is convenient for iterating. \n", + "Itertuples is supposed to be much faster than Iterrows for large datasets." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + "5 5.4 3.9 1.7 0.4 Iris-setosa\n", + "6 4.6 3.4 1.4 0.3 Iris-setosa\n", + "7 5.0 3.4 1.5 0.2 Iris-setosa\n", + "8 4.4 2.9 1.4 0.2 Iris-setosa\n", + "9 4.9 3.1 1.5 0.1 Iris-setosa\n", + "10 5.4 3.7 1.5 0.2 Iris-setosa\n", + "11 4.8 3.4 1.6 0.2 Iris-setosa\n", + "12 4.8 3.0 1.4 0.1 Iris-setosa\n", + "13 4.3 3.0 1.1 0.1 Iris-setosa\n", + "14 5.8 4.0 1.2 0.2 Iris-setosa\n", + "15 5.7 4.4 1.5 0.4 Iris-setosa\n", + "16 5.4 3.9 1.3 0.4 Iris-setosa\n", + "17 5.1 3.5 1.4 0.3 Iris-setosa\n", + "18 5.7 3.8 1.7 0.3 Iris-setosa\n", + "19 5.1 3.8 1.5 0.3 Iris-setosa\n", + "20 5.4 3.4 1.7 0.2 Iris-setosa\n", + "21 5.1 3.7 1.5 0.4 Iris-setosa\n", + "22 4.6 3.6 1.0 0.2 Iris-setosa\n", + "23 5.1 3.3 1.7 0.5 Iris-setosa\n", + "24 4.8 3.4 1.9 0.2 Iris-setosa\n", + "25 5.0 3.0 1.6 0.2 Iris-setosa\n", + "26 5.0 3.4 1.6 0.4 Iris-setosa\n", + "27 5.2 3.5 1.5 0.2 Iris-setosa\n", + "28 5.2 3.4 1.4 0.2 Iris-setosa\n", + "29 4.7 3.2 1.6 0.2 Iris-setosa\n", + "30 4.8 3.1 1.6 0.2 Iris-setosa\n", + "31 5.4 3.4 1.5 0.4 Iris-setosa\n", + "32 5.2 4.1 1.5 0.1 Iris-setosa\n", + "33 5.5 4.2 1.4 0.2 Iris-setosa\n", + "34 4.9 3.1 1.5 0.1 Iris-setosa\n", + "35 5.0 3.2 1.2 0.2 Iris-setosa\n", + "36 5.5 3.5 1.3 0.2 Iris-setosa\n", + "37 4.9 3.1 1.5 0.1 Iris-setosa\n", + "38 4.4 3.0 1.3 0.2 Iris-setosa\n", + "39 5.1 3.4 1.5 0.2 Iris-setosa\n", + "40 5.0 3.5 1.3 0.3 Iris-setosa\n", + "41 4.5 2.3 1.3 0.3 Iris-setosa\n", + "42 4.4 3.2 1.3 0.2 Iris-setosa\n", + "43 5.0 3.5 1.6 0.6 Iris-setosa\n", + "44 5.1 3.8 1.9 0.4 Iris-setosa\n", + "45 4.8 3.0 1.4 0.3 Iris-setosa\n", + "46 5.1 3.8 1.6 0.2 Iris-setosa\n", + "47 4.6 3.2 1.4 0.2 Iris-setosa\n", + "48 5.3 3.7 1.5 0.2 Iris-setosa\n", + "49 5.0 3.3 1.4 0.2 Iris-setosa\n", + "50 7.0 3.2 4.7 1.4 Iris-versicolor\n", + "51 6.4 3.2 4.5 1.5 Iris-versicolor\n", + "52 6.9 3.1 4.9 1.5 Iris-versicolor\n", + "53 5.5 2.3 4.0 1.3 Iris-versicolor\n", + "54 6.5 2.8 4.6 1.5 Iris-versicolor\n", + "55 5.7 2.8 4.5 1.3 Iris-versicolor\n", + "56 6.3 3.3 4.7 1.6 Iris-versicolor\n", + "57 4.9 2.4 3.3 1.0 Iris-versicolor\n", + "58 6.6 2.9 4.6 1.3 Iris-versicolor\n", + "59 5.2 2.7 3.9 1.4 Iris-versicolor\n", + "60 5.0 2.0 3.5 1.0 Iris-versicolor\n", + "61 5.9 3.0 4.2 1.5 Iris-versicolor\n", + "62 6.0 2.2 4.0 1.0 Iris-versicolor\n", + "63 6.1 2.9 4.7 1.4 Iris-versicolor\n", + "64 5.6 2.9 3.6 1.3 Iris-versicolor\n", + "65 6.7 3.1 4.4 1.4 Iris-versicolor\n", + "66 5.6 3.0 4.5 1.5 Iris-versicolor\n", + "67 5.8 2.7 4.1 1.0 Iris-versicolor\n", + "68 6.2 2.2 4.5 1.5 Iris-versicolor\n", + "69 5.6 2.5 3.9 1.1 Iris-versicolor\n", + "70 5.9 3.2 4.8 1.8 Iris-versicolor\n", + "71 6.1 2.8 4.0 1.3 Iris-versicolor\n", + "72 6.3 2.5 4.9 1.5 Iris-versicolor\n", + "73 6.1 2.8 4.7 1.2 Iris-versicolor\n", + "74 6.4 2.9 4.3 1.3 Iris-versicolor\n", + "75 6.6 3.0 4.4 1.4 Iris-versicolor\n", + "76 6.8 2.8 4.8 1.4 Iris-versicolor\n", + "77 6.7 3.0 5.0 1.7 Iris-versicolor\n", + "78 6.0 2.9 4.5 1.5 Iris-versicolor\n", + "79 5.7 2.6 3.5 1.0 Iris-versicolor\n", + "80 5.5 2.4 3.8 1.1 Iris-versicolor\n", + "81 5.5 2.4 3.7 1.0 Iris-versicolor\n", + "82 5.8 2.7 3.9 1.2 Iris-versicolor\n", + "83 6.0 2.7 5.1 1.6 Iris-versicolor\n", + "84 5.4 3.0 4.5 1.5 Iris-versicolor\n", + "85 6.0 3.4 4.5 1.6 Iris-versicolor\n", + "86 6.7 3.1 4.7 1.5 Iris-versicolor\n", + "87 6.3 2.3 4.4 1.3 Iris-versicolor\n", + "88 5.6 3.0 4.1 1.3 Iris-versicolor\n", + "89 5.5 2.5 4.0 1.3 Iris-versicolor\n", + "90 5.5 2.6 4.4 1.2 Iris-versicolor\n", + "91 6.1 3.0 4.6 1.4 Iris-versicolor\n", + "92 5.8 2.6 4.0 1.2 Iris-versicolor\n", + "93 5.0 2.3 3.3 1.0 Iris-versicolor\n", + "94 5.6 2.7 4.2 1.3 Iris-versicolor\n", + "95 5.7 3.0 4.2 1.2 Iris-versicolor\n", + "96 5.7 2.9 4.2 1.3 Iris-versicolor\n", + "97 6.2 2.9 4.3 1.3 Iris-versicolor\n", + "98 5.1 2.5 3.0 1.1 Iris-versicolor\n", + "99 5.7 2.8 4.1 1.3 Iris-versicolor\n", + "100 6.3 3.3 6.0 2.5 Iris-virginica\n", + "101 5.8 2.7 5.1 1.9 Iris-virginica\n", + "102 7.1 3.0 5.9 2.1 Iris-virginica\n", + "103 6.3 2.9 5.6 1.8 Iris-virginica\n", + "104 6.5 3.0 5.8 2.2 Iris-virginica\n", + "105 7.6 3.0 6.6 2.1 Iris-virginica\n", + "106 4.9 2.5 4.5 1.7 Iris-virginica\n", + "107 7.3 2.9 6.3 1.8 Iris-virginica\n", + "108 6.7 2.5 5.8 1.8 Iris-virginica\n", + "109 7.2 3.6 6.1 2.5 Iris-virginica\n", + "110 6.5 3.2 5.1 2.0 Iris-virginica\n", + "111 6.4 2.7 5.3 1.9 Iris-virginica\n", + "112 6.8 3.0 5.5 2.1 Iris-virginica\n", + "113 5.7 2.5 5.0 2.0 Iris-virginica\n", + "114 5.8 2.8 5.1 2.4 Iris-virginica\n", + "115 6.4 3.2 5.3 2.3 Iris-virginica\n", + "116 6.5 3.0 5.5 1.8 Iris-virginica\n", + "117 7.7 3.8 6.7 2.2 Iris-virginica\n", + "118 7.7 2.6 6.9 2.3 Iris-virginica\n", + "119 6.0 2.2 5.0 1.5 Iris-virginica\n", + "120 6.9 3.2 5.7 2.3 Iris-virginica\n", + "121 5.6 2.8 4.9 2.0 Iris-virginica\n", + "122 7.7 2.8 6.7 2.0 Iris-virginica\n", + "123 6.3 2.7 4.9 1.8 Iris-virginica\n", + "124 6.7 3.3 5.7 2.1 Iris-virginica\n", + "125 7.2 3.2 6.0 1.8 Iris-virginica\n", + "126 6.2 2.8 4.8 1.8 Iris-virginica\n", + "127 6.1 3.0 4.9 1.8 Iris-virginica\n", + "128 6.4 2.8 5.6 2.1 Iris-virginica\n", + "129 7.2 3.0 5.8 1.6 Iris-virginica\n", + "130 7.4 2.8 6.1 1.9 Iris-virginica\n", + "131 7.9 3.8 6.4 2.0 Iris-virginica\n", + "132 6.4 2.8 5.6 2.2 Iris-virginica\n", + "133 6.3 2.8 5.1 1.5 Iris-virginica\n", + "134 6.1 2.6 5.6 1.4 Iris-virginica\n", + "135 7.7 3.0 6.1 2.3 Iris-virginica\n", + "136 6.3 3.4 5.6 2.4 Iris-virginica\n", + "137 6.4 3.1 5.5 1.8 Iris-virginica\n", + "138 6.0 3.0 4.8 1.8 Iris-virginica\n", + "139 6.9 3.1 5.4 2.1 Iris-virginica\n", + "140 6.7 3.1 5.6 2.4 Iris-virginica\n", + "141 6.9 3.1 5.1 2.3 Iris-virginica\n", + "142 5.8 2.7 5.1 1.9 Iris-virginica\n", + "143 6.8 3.2 5.9 2.3 Iris-virginica\n", + "144 6.7 3.3 5.7 2.5 Iris-virginica\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n" + ] + } + ], + "source": [ + "for i, row in df.iterrows():\n", + " print(i, row[0], row[1], row[2], row[3], row[4])" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + "5 5.4 3.9 1.7 0.4 Iris-setosa\n", + "6 4.6 3.4 1.4 0.3 Iris-setosa\n", + "7 5.0 3.4 1.5 0.2 Iris-setosa\n", + "8 4.4 2.9 1.4 0.2 Iris-setosa\n", + "9 4.9 3.1 1.5 0.1 Iris-setosa\n", + "10 5.4 3.7 1.5 0.2 Iris-setosa\n", + "11 4.8 3.4 1.6 0.2 Iris-setosa\n", + "12 4.8 3.0 1.4 0.1 Iris-setosa\n", + "13 4.3 3.0 1.1 0.1 Iris-setosa\n", + "14 5.8 4.0 1.2 0.2 Iris-setosa\n", + "15 5.7 4.4 1.5 0.4 Iris-setosa\n", + "16 5.4 3.9 1.3 0.4 Iris-setosa\n", + "17 5.1 3.5 1.4 0.3 Iris-setosa\n", + "18 5.7 3.8 1.7 0.3 Iris-setosa\n", + "19 5.1 3.8 1.5 0.3 Iris-setosa\n", + "20 5.4 3.4 1.7 0.2 Iris-setosa\n", + "21 5.1 3.7 1.5 0.4 Iris-setosa\n", + "22 4.6 3.6 1.0 0.2 Iris-setosa\n", + "23 5.1 3.3 1.7 0.5 Iris-setosa\n", + "24 4.8 3.4 1.9 0.2 Iris-setosa\n", + "25 5.0 3.0 1.6 0.2 Iris-setosa\n", + "26 5.0 3.4 1.6 0.4 Iris-setosa\n", + "27 5.2 3.5 1.5 0.2 Iris-setosa\n", + "28 5.2 3.4 1.4 0.2 Iris-setosa\n", + "29 4.7 3.2 1.6 0.2 Iris-setosa\n", + "30 4.8 3.1 1.6 0.2 Iris-setosa\n", + "31 5.4 3.4 1.5 0.4 Iris-setosa\n", + "32 5.2 4.1 1.5 0.1 Iris-setosa\n", + "33 5.5 4.2 1.4 0.2 Iris-setosa\n", + "34 4.9 3.1 1.5 0.1 Iris-setosa\n", + "35 5.0 3.2 1.2 0.2 Iris-setosa\n", + "36 5.5 3.5 1.3 0.2 Iris-setosa\n", + "37 4.9 3.1 1.5 0.1 Iris-setosa\n", + "38 4.4 3.0 1.3 0.2 Iris-setosa\n", + "39 5.1 3.4 1.5 0.2 Iris-setosa\n", + "40 5.0 3.5 1.3 0.3 Iris-setosa\n", + "41 4.5 2.3 1.3 0.3 Iris-setosa\n", + "42 4.4 3.2 1.3 0.2 Iris-setosa\n", + "43 5.0 3.5 1.6 0.6 Iris-setosa\n", + "44 5.1 3.8 1.9 0.4 Iris-setosa\n", + "45 4.8 3.0 1.4 0.3 Iris-setosa\n", + "46 5.1 3.8 1.6 0.2 Iris-setosa\n", + "47 4.6 3.2 1.4 0.2 Iris-setosa\n", + "48 5.3 3.7 1.5 0.2 Iris-setosa\n", + "49 5.0 3.3 1.4 0.2 Iris-setosa\n", + "50 7.0 3.2 4.7 1.4 Iris-versicolor\n", + "51 6.4 3.2 4.5 1.5 Iris-versicolor\n", + "52 6.9 3.1 4.9 1.5 Iris-versicolor\n", + "53 5.5 2.3 4.0 1.3 Iris-versicolor\n", + "54 6.5 2.8 4.6 1.5 Iris-versicolor\n", + "55 5.7 2.8 4.5 1.3 Iris-versicolor\n", + "56 6.3 3.3 4.7 1.6 Iris-versicolor\n", + "57 4.9 2.4 3.3 1.0 Iris-versicolor\n", + "58 6.6 2.9 4.6 1.3 Iris-versicolor\n", + "59 5.2 2.7 3.9 1.4 Iris-versicolor\n", + "60 5.0 2.0 3.5 1.0 Iris-versicolor\n", + "61 5.9 3.0 4.2 1.5 Iris-versicolor\n", + "62 6.0 2.2 4.0 1.0 Iris-versicolor\n", + "63 6.1 2.9 4.7 1.4 Iris-versicolor\n", + "64 5.6 2.9 3.6 1.3 Iris-versicolor\n", + "65 6.7 3.1 4.4 1.4 Iris-versicolor\n", + "66 5.6 3.0 4.5 1.5 Iris-versicolor\n", + "67 5.8 2.7 4.1 1.0 Iris-versicolor\n", + "68 6.2 2.2 4.5 1.5 Iris-versicolor\n", + "69 5.6 2.5 3.9 1.1 Iris-versicolor\n", + "70 5.9 3.2 4.8 1.8 Iris-versicolor\n", + "71 6.1 2.8 4.0 1.3 Iris-versicolor\n", + "72 6.3 2.5 4.9 1.5 Iris-versicolor\n", + "73 6.1 2.8 4.7 1.2 Iris-versicolor\n", + "74 6.4 2.9 4.3 1.3 Iris-versicolor\n", + "75 6.6 3.0 4.4 1.4 Iris-versicolor\n", + "76 6.8 2.8 4.8 1.4 Iris-versicolor\n", + "77 6.7 3.0 5.0 1.7 Iris-versicolor\n", + "78 6.0 2.9 4.5 1.5 Iris-versicolor\n", + "79 5.7 2.6 3.5 1.0 Iris-versicolor\n", + "80 5.5 2.4 3.8 1.1 Iris-versicolor\n", + "81 5.5 2.4 3.7 1.0 Iris-versicolor\n", + "82 5.8 2.7 3.9 1.2 Iris-versicolor\n", + "83 6.0 2.7 5.1 1.6 Iris-versicolor\n", + "84 5.4 3.0 4.5 1.5 Iris-versicolor\n", + "85 6.0 3.4 4.5 1.6 Iris-versicolor\n", + "86 6.7 3.1 4.7 1.5 Iris-versicolor\n", + "87 6.3 2.3 4.4 1.3 Iris-versicolor\n", + "88 5.6 3.0 4.1 1.3 Iris-versicolor\n", + "89 5.5 2.5 4.0 1.3 Iris-versicolor\n", + "90 5.5 2.6 4.4 1.2 Iris-versicolor\n", + "91 6.1 3.0 4.6 1.4 Iris-versicolor\n", + "92 5.8 2.6 4.0 1.2 Iris-versicolor\n", + "93 5.0 2.3 3.3 1.0 Iris-versicolor\n", + "94 5.6 2.7 4.2 1.3 Iris-versicolor\n", + "95 5.7 3.0 4.2 1.2 Iris-versicolor\n", + "96 5.7 2.9 4.2 1.3 Iris-versicolor\n", + "97 6.2 2.9 4.3 1.3 Iris-versicolor\n", + "98 5.1 2.5 3.0 1.1 Iris-versicolor\n", + "99 5.7 2.8 4.1 1.3 Iris-versicolor\n", + "100 6.3 3.3 6.0 2.5 Iris-virginica\n", + "101 5.8 2.7 5.1 1.9 Iris-virginica\n", + "102 7.1 3.0 5.9 2.1 Iris-virginica\n", + "103 6.3 2.9 5.6 1.8 Iris-virginica\n", + "104 6.5 3.0 5.8 2.2 Iris-virginica\n", + "105 7.6 3.0 6.6 2.1 Iris-virginica\n", + "106 4.9 2.5 4.5 1.7 Iris-virginica\n", + "107 7.3 2.9 6.3 1.8 Iris-virginica\n", + "108 6.7 2.5 5.8 1.8 Iris-virginica\n", + "109 7.2 3.6 6.1 2.5 Iris-virginica\n", + "110 6.5 3.2 5.1 2.0 Iris-virginica\n", + "111 6.4 2.7 5.3 1.9 Iris-virginica\n", + "112 6.8 3.0 5.5 2.1 Iris-virginica\n", + "113 5.7 2.5 5.0 2.0 Iris-virginica\n", + "114 5.8 2.8 5.1 2.4 Iris-virginica\n", + "115 6.4 3.2 5.3 2.3 Iris-virginica\n", + "116 6.5 3.0 5.5 1.8 Iris-virginica\n", + "117 7.7 3.8 6.7 2.2 Iris-virginica\n", + "118 7.7 2.6 6.9 2.3 Iris-virginica\n", + "119 6.0 2.2 5.0 1.5 Iris-virginica\n", + "120 6.9 3.2 5.7 2.3 Iris-virginica\n", + "121 5.6 2.8 4.9 2.0 Iris-virginica\n", + "122 7.7 2.8 6.7 2.0 Iris-virginica\n", + "123 6.3 2.7 4.9 1.8 Iris-virginica\n", + "124 6.7 3.3 5.7 2.1 Iris-virginica\n", + "125 7.2 3.2 6.0 1.8 Iris-virginica\n", + "126 6.2 2.8 4.8 1.8 Iris-virginica\n", + "127 6.1 3.0 4.9 1.8 Iris-virginica\n", + "128 6.4 2.8 5.6 2.1 Iris-virginica\n", + "129 7.2 3.0 5.8 1.6 Iris-virginica\n", + "130 7.4 2.8 6.1 1.9 Iris-virginica\n", + "131 7.9 3.8 6.4 2.0 Iris-virginica\n", + "132 6.4 2.8 5.6 2.2 Iris-virginica\n", + "133 6.3 2.8 5.1 1.5 Iris-virginica\n", + "134 6.1 2.6 5.6 1.4 Iris-virginica\n", + "135 7.7 3.0 6.1 2.3 Iris-virginica\n", + "136 6.3 3.4 5.6 2.4 Iris-virginica\n", + "137 6.4 3.1 5.5 1.8 Iris-virginica\n", + "138 6.0 3.0 4.8 1.8 Iris-virginica\n", + "139 6.9 3.1 5.4 2.1 Iris-virginica\n", + "140 6.7 3.1 5.6 2.4 Iris-virginica\n", + "141 6.9 3.1 5.1 2.3 Iris-virginica\n", + "142 5.8 2.7 5.1 1.9 Iris-virginica\n", + "143 6.8 3.2 5.9 2.3 Iris-virginica\n", + "144 6.7 3.3 5.7 2.5 Iris-virginica\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n" + ] + } + ], + "source": [ + "for row in df.itertuples(name=None): \n", + " print(row[0], row[1], row[2], row[3], row[4], row[5])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pandas/Pandas Reorder Columns in DataFrame.ipynb b/Pandas/Pandas Reorder Columns in DataFrame.ipynb new file mode 100644 index 00000000..0f030051 --- /dev/null +++ b/Pandas/Pandas Reorder Columns in DataFrame.ipynb @@ -0,0 +1,420 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pandas - Reorder Columns\n", + "Swap two columns, or change the order of columns" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ABCDLabel
05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa
..................
1456.73.05.22.3Iris-virginica
1466.32.55.01.9Iris-virginica
1476.53.05.22.0Iris-virginica
1486.23.45.42.3Iris-virginica
1495.93.05.11.8Iris-virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " A B C D Label\n", + "0 5.1 3.5 1.4 0.2 Iris-setosa\n", + "1 4.9 3.0 1.4 0.2 Iris-setosa\n", + "2 4.7 3.2 1.3 0.2 Iris-setosa\n", + "3 4.6 3.1 1.5 0.2 Iris-setosa\n", + "4 5.0 3.6 1.4 0.2 Iris-setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 3.0 5.2 2.3 Iris-virginica\n", + "146 6.3 2.5 5.0 1.9 Iris-virginica\n", + "147 6.5 3.0 5.2 2.0 Iris-virginica\n", + "148 6.2 3.4 5.4 2.3 Iris-virginica\n", + "149 5.9 3.0 5.1 1.8 Iris-virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('iris.data', names=['A','B','C','D','Label'])\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1) get a list of the column names." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['A', 'B', 'C', 'D', 'Label']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "titles = list(df.columns)\n", + "titles" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2) Swap or move whatever columns you want in the list." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['A', 'C', 'B', 'D', 'Label']" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "titles[1], titles[2] = titles[2], titles[1]\n", + "titles" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "3) Reassign the columns in the DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ACBDLabel
05.11.43.50.2Iris-setosa
14.91.43.00.2Iris-setosa
24.71.33.20.2Iris-setosa
34.61.53.10.2Iris-setosa
45.01.43.60.2Iris-setosa
..................
1456.75.23.02.3Iris-virginica
1466.35.02.51.9Iris-virginica
1476.55.23.02.0Iris-virginica
1486.25.43.42.3Iris-virginica
1495.95.13.01.8Iris-virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " A C B D Label\n", + "0 5.1 1.4 3.5 0.2 Iris-setosa\n", + "1 4.9 1.4 3.0 0.2 Iris-setosa\n", + "2 4.7 1.3 3.2 0.2 Iris-setosa\n", + "3 4.6 1.5 3.1 0.2 Iris-setosa\n", + "4 5.0 1.4 3.6 0.2 Iris-setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 5.2 3.0 2.3 Iris-virginica\n", + "146 6.3 5.0 2.5 1.9 Iris-virginica\n", + "147 6.5 5.2 3.0 2.0 Iris-virginica\n", + "148 6.2 5.4 3.4 2.3 Iris-virginica\n", + "149 5.9 5.1 3.0 1.8 Iris-virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = df[titles]\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pandas/Python Pandas Input-Output.ipynb b/Pandas/Python Pandas Input-Output.ipynb new file mode 100644 index 00000000..4fc3f862 --- /dev/null +++ b/Pandas/Python Pandas Input-Output.ipynb @@ -0,0 +1,762 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Pandas I/O\n", + "### Creating DataFrames, Reading and Writing to CSV & JSON files \n", + "[Documentation](https://pandas.pydata.org/docs/index.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import random" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating DataFrames from Lists and Dicts\n", + "▶ New DataFrame from a **List** \n", + "Pandas automatically assigns numerical row indexes." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
0
00.027684
10.174996
20.743153
30.628041
40.658552
\n", + "
" + ], + "text/plain": [ + " 0\n", + "0 0.027684\n", + "1 0.174996\n", + "2 0.743153\n", + "3 0.628041\n", + "4 0.658552" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data1 = [random.random() for i in range(10000)]\n", + "df = pd.DataFrame(data1)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "▶ New DataFrame from a **2D List** \n", + "Column names default to integers. Each subList is a row." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
01
0A28
1B78
2C85
3D65
4E98
\n", + "
" + ], + "text/plain": [ + " 0 1\n", + "0 A 28\n", + "1 B 78\n", + "2 C 85\n", + "3 D 65\n", + "4 E 98" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data2 = [[i, random.randint(10,99)] for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']\n", + "df = pd.DataFrame(data2)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "▶ New DataFrame from a **Dictionary** \n", + "Dict Keys become column names" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
ModelPriceSize
0T571.4257 inches
1T611.4861 inches
2T641.7364 inches
3T651.9565 inches
\n", + "
" + ], + "text/plain": [ + " Model Price Size\n", + "0 T57 1.42 57 inches\n", + "1 T61 1.48 61 inches\n", + "2 T64 1.73 64 inches\n", + "3 T65 1.95 65 inches" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data3 = {\n", + " 'Model':['T57','T61','T64','T65'],\n", + " 'Price':[1.42,1.48,1.73,1.95],\n", + " 'Size':['57 inches','61 inches','64 inches','65 inches']}\n", + "df = pd.DataFrame(data3)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Change previous example to use Model number as index. " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
PriceSize
T571.4257 inches
T611.4861 inches
T641.7364 inches
T651.9565 inches
\n", + "
" + ], + "text/plain": [ + " Price Size\n", + "T57 1.42 57 inches\n", + "T61 1.48 61 inches\n", + "T64 1.73 64 inches\n", + "T65 1.95 65 inches" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.DataFrame(\n", + " {'Price':data3['Price'],'Size':data3['Size']}, \n", + " index=data3['Model'])\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "▶ New DataFrame from a List of Dictionaries \n", + "Note, missing Length is populated with NaN (not a number)." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
HtLenWt
06345.02.6
129NaN1.7
23771.04.2
\n", + "
" + ], + "text/plain": [ + " Ht Len Wt\n", + "0 63 45.0 2.6\n", + "1 29 NaN 1.7\n", + "2 37 71.0 4.2" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data4 = [\n", + " {'Ht':63, 'Len':45, 'Wt':2.6}, \n", + " {'Ht':29, 'Wt':1.7},\n", + " {'Ht':37, 'Len':71, 'Wt':4.2}]\n", + "df = pd.DataFrame(data4)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reading & Writing DataFrames to CSV Files\n", + "[Documentation](https://pandas.pydata.org/docs/user_guide/io.html#csv-text-files) of numerous optional parameters. \n", + "\n", + "▶ Write DataFrame to CSV file " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.DataFrame(data4)\n", + "df.to_csv('outfile.csv', index=False) #, sep=';')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "▶ Read CSV file into DataFrame \n", + "Missing numerical data are given value NaN by default." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
HtLenWt
06345.02.6
129NaN1.7
23771.04.2
\n", + "
" + ], + "text/plain": [ + " Ht Len Wt\n", + "0 63 45.0 2.6\n", + "1 29 NaN 1.7\n", + "2 37 71.0 4.2" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('outfile.csv')\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "▶ Convert DataFrame to_string" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "' Ht Len Wt\\n0 63 45.0 2.6\\n1 29 NaN 1.7\\n2 37 71.0 4.2'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.DataFrame(data4)\n", + "d4str = df.to_string()\n", + "d4str" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reading & Writing DataFrames to JSON files\n", + "[Documentation](https://pandas.pydata.org/docs/user_guide/io.html#csv-text-files) of numerous optional parameters. \n", + "\n", + "▶ Convert DataFrame to **JSON** string \n", + "No argument - json by columns is default, {column -> {index -> value}}" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'{\"Ht\":{\"0\":63,\"1\":29,\"2\":37},\"Len\":{\"0\":45.0,\"1\":null,\"2\":71.0},\"Wt\":{\"0\":2.6,\"1\":1.7,\"2\":4.2}}'" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data4_json = df.to_json()\n", + "data4_json" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use orient='index' to structure the json by rows, {index -> {column -> value}}. \n", + "You can also strip out the row indices by using orient='records'." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'{\"0\":{\"Ht\":63,\"Len\":45.0,\"Wt\":2.6},\"1\":{\"Ht\":29,\"Len\":null,\"Wt\":1.7},\"2\":{\"Ht\":37,\"Len\":71.0,\"Wt\":4.2}}'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data4_json = df.to_json(orient='index')\n", + "data4_json" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "▶ Write to a text file in JSON format." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "data4_json = df.to_json('outjson.txt')\n", + "data4_json" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "▶ Read same JSON data back in to a DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
HtLenWt
06345.02.6
129NaN1.7
23771.04.2
\n", + "
" + ], + "text/plain": [ + " Ht Len Wt\n", + "0 63 45.0 2.6\n", + "1 29 NaN 1.7\n", + "2 37 71.0 4.2" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data4 = pd.read_json('outjson.txt')\n", + "data4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pandas/Python Pandas Time Series Data.ipynb b/Pandas/Python Pandas Time Series Data.ipynb new file mode 100644 index 00000000..3db1b4b4 --- /dev/null +++ b/Pandas/Python Pandas Time Series Data.ipynb @@ -0,0 +1,856 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Pandas Time Series Data\n", + "[Documentation](https://pandas.pydata.org/docs/user_guide/timeseries.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import datetime\n", + "import random" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Data Formats Supported\n", + "Pandas datetime64 can interpret strings, Python datetime, and Numpy datetime64 objects. \n", + "Also note, a list of pd.datetime64 objects are automatically converted to a DatetimeIndex." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "DatetimeIndex(['2020-06-01', '2020-06-02', '2020-06-03', '2020-06-04',\n", + " '2020-06-05'],\n", + " dtype='datetime64[ns]', freq=None)" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a1 = pd.to_datetime([\n", + " '6/1/2020', \n", + " '6-2-2020',\n", + " datetime.datetime(2020, 6, 3),\n", + " np.datetime64('2020-06-04'),\n", + " np.datetime64('2020-06-05')])\n", + "a1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pass in a format argument for custom formatted dates (case matters)." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "DatetimeIndex(['2020-06-14', '2020-06-15'], dtype='datetime64[ns]', freq=None)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a2 = pd.to_datetime(['2020/14/06', '2020/15/06'], format='%Y/%d/%m')\n", + "a2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hours and Minutes too? No problem." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "DatetimeIndex(['2020-08-06 14:05:00', '2020-09-06 06:45:00'], dtype='datetime64[ns]', freq=None)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a3 = pd.to_datetime(\n", + " ['2020/6/8 14.05', '2020/6/9 06.45'], format='%Y/%d/%m %H.%M')\n", + "a3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating a datetime sequence with fixed intervals\n", + "freq parameters: \n", + " D=days, W=weeks, M=months, B=business days, BW=bus weeks, BM=bus months" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DatetimeIndex(['2020-06-01', '2020-06-02', '2020-06-03', '2020-06-04',\n", + " '2020-06-05', '2020-06-06', '2020-06-07', '2020-06-08',\n", + " '2020-06-09', '2020-06-10', '2020-06-11', '2020-06-12',\n", + " '2020-06-13', '2020-06-14', '2020-06-15', '2020-06-16',\n", + " '2020-06-17', '2020-06-18', '2020-06-19', '2020-06-20',\n", + " '2020-06-21', '2020-06-22', '2020-06-23', '2020-06-24',\n", + " '2020-06-25', '2020-06-26', '2020-06-27', '2020-06-28',\n", + " '2020-06-29', '2020-06-30'],\n", + " dtype='datetime64[ns]', freq='D')\n" + ] + }, + { + "data": { + "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", + "
M
2020-06-070.970080
2020-06-140.809867
2020-06-180.917428
2020-06-200.945739
2020-06-260.815245
\n", + "
" + ], + "text/plain": [ + " M\n", + "2020-06-07 0.970080\n", + "2020-06-14 0.809867\n", + "2020-06-18 0.917428\n", + "2020-06-20 0.945739\n", + "2020-06-26 0.815245" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b1 = [random.random() for i in range(30)]\n", + "b2 = pd.date_range('2020-06-01', periods=30, freq='1d')\n", + "print(b2)\n", + "df = pd.DataFrame({'M':b1}, index=b2)\n", + "#df.loc['2020-06-18':]\n", + "df[df['M'] > 0.8]" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
0
2020-07-120.581691
2020-07-190.611492
2020-07-260.933940
\n", + "
" + ], + "text/plain": [ + " 0\n", + "2020-07-12 0.581691\n", + "2020-07-19 0.611492\n", + "2020-07-26 0.933940" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b3 = np.random.rand(52)\n", + "b4 = pd.date_range('2020-06-01', periods=52, freq='W')\n", + "df = pd.DataFrame(b3, index=b4)\n", + "df['2020-07-10':'2020-07-28']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternative to periods, you can give start and stop dates." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "DatetimeIndex(['2020-06-30', '2020-07-31', '2020-08-31', '2020-09-30',\n", + " '2020-10-31', '2020-11-30', '2020-12-31'],\n", + " dtype='datetime64[ns]', freq='M')" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b3 = pd.date_range('2020-06-30', '2020-12-31', freq='M')\n", + "b3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Dates Index to/from CSV file\n", + "Create DataFrame with Dates as Index, Write it to a CSV file, then Read in the CSV data and put the dates as Index" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
alphabeta
2020-05-2910.4026
2020-05-308.9226
2020-05-315.0912
2020-06-013.8727
2020-06-023.9324
2020-06-034.7916
2020-06-049.1216
\n", + "
" + ], + "text/plain": [ + " alpha beta\n", + "2020-05-29 10.40 26\n", + "2020-05-30 8.92 26\n", + "2020-05-31 5.09 12\n", + "2020-06-01 3.87 27\n", + "2020-06-02 3.93 24\n", + "2020-06-03 4.79 16\n", + "2020-06-04 9.12 16" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d1 = np.round(6 + 4 * np.random.randn(7), decimals=2)\n", + "d2 = np.random.randint(12, 30, size=7)\n", + "d3 = pd.Series(pd.date_range('2020-05-29', periods=7, freq='1d'))\n", + "df = pd.DataFrame({'alpha':d1, 'beta':d2}, index=d3)\n", + "\n", + "df.to_csv('file01.csv')\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n" + ] + }, + { + "data": { + "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", + "
alphabeta
2020-05-2910.4026
2020-05-308.9226
2020-05-315.0912
\n", + "
" + ], + "text/plain": [ + " alpha beta\n", + "2020-05-29 10.40 26\n", + "2020-05-30 8.92 26\n", + "2020-05-31 5.09 12" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('file01.csv', index_col=0)\n", + "print(type(df.index[2]))\n", + "df.index = pd.to_datetime(df.index, format='%Y/%m/%d')\n", + "print(type(df.index[2]))\n", + "df[:'2020/05/31']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Constructing Dates from Multiple Columns\n", + "You have Month, Day and Year in separate fields, and need to combine them into a single Datetime field." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2017 12 7 0.970109923902562\n" + ] + } + ], + "source": [ + "yyyy = [random.randint(1995,2020) for i in range(100)]\n", + "mm = [random.randint(1,12) for i in range(100)]\n", + "dd = [random.randint(1,28) for i in range(100)]\n", + "data = [random.random() for i in range(100)]\n", + "print(yyyy[5], mm[5], dd[5], data[5])" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
01
02016-10-180.282307
12007-09-090.004984
22016-12-120.652762
32017-04-140.199284
42013-03-230.163154
\n", + "
" + ], + "text/plain": [ + " 0 1\n", + "0 2016-10-18 0.282307\n", + "1 2007-09-09 0.004984\n", + "2 2016-12-12 0.652762\n", + "3 2017-04-14 0.199284\n", + "4 2013-03-23 0.163154" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df1 = pd.DataFrame({'year': yyyy,'month': mm, 'day': dd})\n", + "df1 = pd.to_datetime(df1) \n", + "df2 = pd.Series(data)\n", + "df = pd.concat([df1, df2], axis=1)\n", + "df[:5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Pivot (Transpose) Rows & Columns\n", + "You normally want dates as the row index, not the column headers. \n", + "Flip the rows and columns using T." + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "data": { + "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", + "
0
2016-10-18 00:00:000.282307
2007-09-09 00:00:000.004984
2016-12-12 00:00:000.652762
2017-04-14 00:00:000.199284
2013-03-23 00:00:000.163154
\n", + "
" + ], + "text/plain": [ + " 0\n", + "2016-10-18 00:00:00 0.282307\n", + "2007-09-09 00:00:00 0.004984\n", + "2016-12-12 00:00:00 0.652762\n", + "2017-04-14 00:00:00 0.199284\n", + "2013-03-23 00:00:00 0.163154" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv('pivot.csv')\n", + "df = df.T\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Date Arithmetic" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Thursday'" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "appointment = pd.Timestamp('2020-06-04')\n", + "appointment.day_name()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Uh oh! my appointment is delayed 2 days. \n", + "Here are 3 different ways to add 2 days to the date." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Saturday'" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "appointment = pd.Timestamp('2020-06-04')\n", + "appointment += pd.Timedelta('2 days')\n", + "appointment.day_name()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Saturday'" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "appointment = pd.Timestamp('2020-06-04')\n", + "appointment += pd.Timedelta(days=2)\n", + "appointment.day_name()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Date offsets: Day, Hour, Minute, Second, Milli, Micro, Nano " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Saturday'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "appointment = pd.Timestamp('2020-06-04')\n", + "appointment += pd.offsets.Day(2)\n", + "appointment.day_name()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "NO, it's delayed 2 business days. " + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Monday'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "appointment = pd.Timestamp('2020-06-04')\n", + "appointment += pd.offsets.BDay(2)\n", + "appointment.day_name()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Pandas/file01.csv b/Pandas/file01.csv new file mode 100644 index 00000000..229e74ef --- /dev/null +++ b/Pandas/file01.csv @@ -0,0 +1,8 @@ +,alpha,beta +2020-05-29,8.78,24 +2020-05-30,13.0,25 +2020-05-31,0.44,25 +2020-06-01,1.94,28 +2020-06-02,5.4,20 +2020-06-03,5.68,21 +2020-06-04,2.64,16 diff --git a/Pandas/iris.data b/Pandas/iris.data new file mode 100644 index 00000000..5c4316cd --- /dev/null +++ b/Pandas/iris.data @@ -0,0 +1,151 @@ +5.1,3.5,1.4,0.2,Iris-setosa +4.9,3.0,1.4,0.2,Iris-setosa +4.7,3.2,1.3,0.2,Iris-setosa +4.6,3.1,1.5,0.2,Iris-setosa +5.0,3.6,1.4,0.2,Iris-setosa +5.4,3.9,1.7,0.4,Iris-setosa +4.6,3.4,1.4,0.3,Iris-setosa +5.0,3.4,1.5,0.2,Iris-setosa +4.4,2.9,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.4,3.7,1.5,0.2,Iris-setosa +4.8,3.4,1.6,0.2,Iris-setosa +4.8,3.0,1.4,0.1,Iris-setosa +4.3,3.0,1.1,0.1,Iris-setosa +5.8,4.0,1.2,0.2,Iris-setosa +5.7,4.4,1.5,0.4,Iris-setosa +5.4,3.9,1.3,0.4,Iris-setosa +5.1,3.5,1.4,0.3,Iris-setosa +5.7,3.8,1.7,0.3,Iris-setosa +5.1,3.8,1.5,0.3,Iris-setosa +5.4,3.4,1.7,0.2,Iris-setosa +5.1,3.7,1.5,0.4,Iris-setosa +4.6,3.6,1.0,0.2,Iris-setosa +5.1,3.3,1.7,0.5,Iris-setosa +4.8,3.4,1.9,0.2,Iris-setosa +5.0,3.0,1.6,0.2,Iris-setosa +5.0,3.4,1.6,0.4,Iris-setosa +5.2,3.5,1.5,0.2,Iris-setosa +5.2,3.4,1.4,0.2,Iris-setosa +4.7,3.2,1.6,0.2,Iris-setosa +4.8,3.1,1.6,0.2,Iris-setosa +5.4,3.4,1.5,0.4,Iris-setosa +5.2,4.1,1.5,0.1,Iris-setosa +5.5,4.2,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.0,3.2,1.2,0.2,Iris-setosa +5.5,3.5,1.3,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +4.4,3.0,1.3,0.2,Iris-setosa +5.1,3.4,1.5,0.2,Iris-setosa +5.0,3.5,1.3,0.3,Iris-setosa +4.5,2.3,1.3,0.3,Iris-setosa +4.4,3.2,1.3,0.2,Iris-setosa +5.0,3.5,1.6,0.6,Iris-setosa +5.1,3.8,1.9,0.4,Iris-setosa +4.8,3.0,1.4,0.3,Iris-setosa +5.1,3.8,1.6,0.2,Iris-setosa +4.6,3.2,1.4,0.2,Iris-setosa +5.3,3.7,1.5,0.2,Iris-setosa +5.0,3.3,1.4,0.2,Iris-setosa +7.0,3.2,4.7,1.4,Iris-versicolor +6.4,3.2,4.5,1.5,Iris-versicolor +6.9,3.1,4.9,1.5,Iris-versicolor +5.5,2.3,4.0,1.3,Iris-versicolor +6.5,2.8,4.6,1.5,Iris-versicolor +5.7,2.8,4.5,1.3,Iris-versicolor +6.3,3.3,4.7,1.6,Iris-versicolor +4.9,2.4,3.3,1.0,Iris-versicolor +6.6,2.9,4.6,1.3,Iris-versicolor +5.2,2.7,3.9,1.4,Iris-versicolor +5.0,2.0,3.5,1.0,Iris-versicolor +5.9,3.0,4.2,1.5,Iris-versicolor +6.0,2.2,4.0,1.0,Iris-versicolor +6.1,2.9,4.7,1.4,Iris-versicolor +5.6,2.9,3.6,1.3,Iris-versicolor +6.7,3.1,4.4,1.4,Iris-versicolor +5.6,3.0,4.5,1.5,Iris-versicolor +5.8,2.7,4.1,1.0,Iris-versicolor +6.2,2.2,4.5,1.5,Iris-versicolor +5.6,2.5,3.9,1.1,Iris-versicolor +5.9,3.2,4.8,1.8,Iris-versicolor +6.1,2.8,4.0,1.3,Iris-versicolor +6.3,2.5,4.9,1.5,Iris-versicolor +6.1,2.8,4.7,1.2,Iris-versicolor +6.4,2.9,4.3,1.3,Iris-versicolor +6.6,3.0,4.4,1.4,Iris-versicolor +6.8,2.8,4.8,1.4,Iris-versicolor +6.7,3.0,5.0,1.7,Iris-versicolor +6.0,2.9,4.5,1.5,Iris-versicolor +5.7,2.6,3.5,1.0,Iris-versicolor +5.5,2.4,3.8,1.1,Iris-versicolor +5.5,2.4,3.7,1.0,Iris-versicolor +5.8,2.7,3.9,1.2,Iris-versicolor +6.0,2.7,5.1,1.6,Iris-versicolor +5.4,3.0,4.5,1.5,Iris-versicolor +6.0,3.4,4.5,1.6,Iris-versicolor +6.7,3.1,4.7,1.5,Iris-versicolor +6.3,2.3,4.4,1.3,Iris-versicolor +5.6,3.0,4.1,1.3,Iris-versicolor +5.5,2.5,4.0,1.3,Iris-versicolor +5.5,2.6,4.4,1.2,Iris-versicolor +6.1,3.0,4.6,1.4,Iris-versicolor +5.8,2.6,4.0,1.2,Iris-versicolor +5.0,2.3,3.3,1.0,Iris-versicolor +5.6,2.7,4.2,1.3,Iris-versicolor +5.7,3.0,4.2,1.2,Iris-versicolor +5.7,2.9,4.2,1.3,Iris-versicolor +6.2,2.9,4.3,1.3,Iris-versicolor +5.1,2.5,3.0,1.1,Iris-versicolor +5.7,2.8,4.1,1.3,Iris-versicolor +6.3,3.3,6.0,2.5,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +7.1,3.0,5.9,2.1,Iris-virginica +6.3,2.9,5.6,1.8,Iris-virginica +6.5,3.0,5.8,2.2,Iris-virginica +7.6,3.0,6.6,2.1,Iris-virginica +4.9,2.5,4.5,1.7,Iris-virginica +7.3,2.9,6.3,1.8,Iris-virginica +6.7,2.5,5.8,1.8,Iris-virginica +7.2,3.6,6.1,2.5,Iris-virginica +6.5,3.2,5.1,2.0,Iris-virginica +6.4,2.7,5.3,1.9,Iris-virginica +6.8,3.0,5.5,2.1,Iris-virginica +5.7,2.5,5.0,2.0,Iris-virginica +5.8,2.8,5.1,2.4,Iris-virginica +6.4,3.2,5.3,2.3,Iris-virginica +6.5,3.0,5.5,1.8,Iris-virginica +7.7,3.8,6.7,2.2,Iris-virginica +7.7,2.6,6.9,2.3,Iris-virginica +6.0,2.2,5.0,1.5,Iris-virginica +6.9,3.2,5.7,2.3,Iris-virginica +5.6,2.8,4.9,2.0,Iris-virginica +7.7,2.8,6.7,2.0,Iris-virginica +6.3,2.7,4.9,1.8,Iris-virginica +6.7,3.3,5.7,2.1,Iris-virginica +7.2,3.2,6.0,1.8,Iris-virginica +6.2,2.8,4.8,1.8,Iris-virginica +6.1,3.0,4.9,1.8,Iris-virginica +6.4,2.8,5.6,2.1,Iris-virginica +7.2,3.0,5.8,1.6,Iris-virginica +7.4,2.8,6.1,1.9,Iris-virginica +7.9,3.8,6.4,2.0,Iris-virginica +6.4,2.8,5.6,2.2,Iris-virginica +6.3,2.8,5.1,1.5,Iris-virginica +6.1,2.6,5.6,1.4,Iris-virginica +7.7,3.0,6.1,2.3,Iris-virginica +6.3,3.4,5.6,2.4,Iris-virginica +6.4,3.1,5.5,1.8,Iris-virginica +6.0,3.0,4.8,1.8,Iris-virginica +6.9,3.1,5.4,2.1,Iris-virginica +6.7,3.1,5.6,2.4,Iris-virginica +6.9,3.1,5.1,2.3,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +6.8,3.2,5.9,2.3,Iris-virginica +6.7,3.3,5.7,2.5,Iris-virginica +6.7,3.0,5.2,2.3,Iris-virginica +6.3,2.5,5.0,1.9,Iris-virginica +6.5,3.0,5.2,2.0,Iris-virginica +6.2,3.4,5.4,2.3,Iris-virginica +5.9,3.0,5.1,1.8,Iris-virginica + diff --git a/Pandas/outfile.csv b/Pandas/outfile.csv new file mode 100644 index 00000000..ba5d7289 --- /dev/null +++ b/Pandas/outfile.csv @@ -0,0 +1,4 @@ +Ht,Len,Wt +63,45.0,2.6 +29,,1.7 +37,71.0,4.2 diff --git a/Pandas/outjson.txt b/Pandas/outjson.txt new file mode 100644 index 00000000..0967acb0 --- /dev/null +++ b/Pandas/outjson.txt @@ -0,0 +1 @@ +{"0":{"Ht":63,"Len":45.0,"Wt":2.6},"1":{"Ht":29,"Len":null,"Wt":1.7},"2":{"Ht":37,"Len":71.0,"Wt":4.2}} \ No newline at end of file diff --git a/Pandas/pivot.csv b/Pandas/pivot.csv new file mode 100644 index 00000000..0c603dc6 --- /dev/null +++ b/Pandas/pivot.csv @@ -0,0 +1,2 @@ +2016-10-18 00:00:00,2007-09-09 00:00:00,2016-12-12 00:00:00,2017-04-14 00:00:00,2013-03-23 00:00:00,2017-12-07 00:00:00,2008-06-05 00:00:00,2004-12-06 00:00:00,1995-11-05 00:00:00,1996-09-12 00:00:00,2001-05-23 00:00:00,1997-07-08 00:00:00,1995-05-01 00:00:00,2008-11-06 00:00:00,2020-12-07 00:00:00,1998-02-03 00:00:00,1996-12-20 00:00:00,1998-04-25 00:00:00,2019-03-09 00:00:00,2019-08-25 00:00:00,2015-12-01 00:00:00,2004-04-08 00:00:00,2015-04-19 00:00:00,2013-12-23 00:00:00,2008-07-17 00:00:00,2016-02-16 00:00:00,2004-05-08 00:00:00,2000-10-26 00:00:00,1999-04-27 00:00:00,2014-06-23 00:00:00,2014-04-02 00:00:00,1999-06-05 00:00:00,1998-10-20 00:00:00,2013-01-24 00:00:00,2006-07-27 00:00:00,2002-08-20 00:00:00,2013-11-07 00:00:00,2006-07-01 00:00:00,2004-11-23 00:00:00,2008-09-07 00:00:00,1996-08-19 00:00:00,2016-01-27 00:00:00,2002-09-26 00:00:00,1996-09-09 00:00:00,1998-10-09 00:00:00,2000-07-19 00:00:00,2008-11-19 00:00:00,2014-03-11 00:00:00,1996-07-15 00:00:00,2000-02-05 00:00:00,1998-06-24 00:00:00,1998-01-23 00:00:00,1998-05-06 00:00:00,2003-08-05 00:00:00,2013-08-02 00:00:00,1996-03-07 00:00:00,1995-03-25 00:00:00,2012-10-06 00:00:00,2004-07-27 00:00:00,1999-08-05 00:00:00,2009-06-04 00:00:00,2007-07-27 00:00:00,2002-07-03 00:00:00,2011-06-07 00:00:00,2012-08-19 00:00:00,2018-03-22 00:00:00,1996-09-02 00:00:00,2008-09-02 00:00:00,2006-09-14 00:00:00,2007-07-11 00:00:00,2009-07-16 00:00:00,2016-06-24 00:00:00,2008-10-07 00:00:00,1997-06-13 00:00:00,2017-02-17 00:00:00,2009-05-09 00:00:00,1995-12-28 00:00:00,2014-05-25 00:00:00,1996-03-24 00:00:00,1996-11-12 00:00:00,2011-07-12 00:00:00,2009-11-24 00:00:00,2003-02-05 00:00:00,2010-07-06 00:00:00,1996-12-13 00:00:00,2014-10-11 00:00:00,2008-03-26 00:00:00,2019-07-07 00:00:00,2015-12-13 00:00:00,1997-08-21 00:00:00,2016-10-05 00:00:00,2016-10-08 00:00:00,2005-03-27 00:00:00,2011-03-08 00:00:00,2015-03-14 00:00:00,2001-10-11 00:00:00,1996-07-03 00:00:00,2006-10-22 00:00:00,2004-03-22 00:00:00,1998-12-07 00:00:00 +0.2823066951673592,0.004983503360937558,0.6527617484109105,0.19928401502972315,0.16315370812362973,0.970109923902562,0.28902358319246113,0.3869769040495181,0.036043163595530725,0.8466446865018183,0.3029305402508473,0.9333588096128297,0.1519465926874476,0.9927748105073949,0.4651284520015794,0.14707391568333994,0.08982833065821505,0.5883453931565746,0.3494752580177175,0.10167526699057972,0.07941368601234156,0.9358293552727159,0.10740538848773118,0.4506715669567083,0.8387140420947164,0.5746907600075374,0.758976559783973,0.3110498538520595,0.9993881318470451,0.26265671090461906,0.6470895524293089,0.49971727121051435,0.8195258715074762,0.3630891873905159,0.11926782337362651,0.555536083920244,0.8190498637543558,0.40175480684114895,0.7158884358768607,0.3076511179082977,0.06309063694263983,0.5979927629277495,0.7614082398079934,0.34115186547855936,0.5709798851222291,0.9855403495879589,0.7253074001190444,0.4685492447308346,0.03796109649032342,0.16599775387020776,0.7730834960205076,0.04807532952934723,0.9967131145813193,0.7619403019670993,0.4326634641827285,0.43819600412852544,0.8915384234633204,0.7388190145903542,0.1504441063873443,0.11645793742178479,0.8849805306825719,0.8209440808963199,0.03756126787686931,0.2921962688201817,0.637006806437786,0.21496659424673736,0.0673283796900469,0.2679415763216668,0.845924613974428,0.35520559789032924,0.9358371834432343,0.12177533426329734,0.7385219285657647,0.09006868872192064,0.21716948989174056,0.212482450203213,0.26463884587482933,0.4639594087198322,0.473534405458537,0.31034018086435244,0.4868968278642336,0.7276362315420386,0.5856335537301501,0.3848357918705628,0.5045424488044008,0.3669372132755703,0.5223717711718852,0.07330274927032765,0.12129741612938838,0.4463446916302444,0.06560636427124344,0.5628053006445556,0.6800242556861632,0.13053686078804783,0.9666542996125932,0.21805040691134103,0.920335829229451,0.5715463228495896,0.2984664705574499,0.28766845010273867 diff --git a/Primes.py b/Primes.py index 196644d3..3bbf14eb 100644 --- a/Primes.py +++ b/Primes.py @@ -2,7 +2,7 @@ max = int(input("Find primes up to what number? : ")) primeList = [] - +#for loop for checking each number for x in range(2, max + 1): isPrime = True index = 0 @@ -43,4 +43,4 @@ x += 1 -print(primeList) \ No newline at end of file +print(primeList) diff --git a/Python Bisect.ipynb b/Python Bisect.ipynb new file mode 100644 index 00000000..1390432d --- /dev/null +++ b/Python Bisect.ipynb @@ -0,0 +1,267 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Bisect Module\n", + "Used to find the insertion point for adding an item to a sorted list. \n", + "Advantage: it's fast. Runs in O(log n). \n", + "[Documentation](https://docs.python.org/3/library/bisect.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import bisect" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### bisect_left\n", + "Finds the insertion point for an item in a sorted list, or the spot just left of any matches. \n", + "Works for list of ints, list of floats, list of strings." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "3\n", + "2\n" + ] + } + ], + "source": [ + "a = [24, 33, 41, 41, 45, 50, 53, 59, 62, 66, 70]\n", + "i = bisect.bisect_left(a, 41)\n", + "print(i)\n", + "\n", + "b = [1.3, 2.2, 3.4, 4.6, 5.5, 6.9, 7.2, 8.4]\n", + "j = bisect.bisect_left(b, 4.1)\n", + "print(j)\n", + "\n", + "c = ['aaa', 'bbb', 'ccc', 'ddd']\n", + "k = bisect.bisect_left(c, 'bug')\n", + "print(k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If list is unsorted, results are unpredictable, but it still tries." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n" + ] + } + ], + "source": [ + "a = [33, 24, 41, 41, 45, 50, 53, 59, 66, 62, 70]\n", + "i = bisect.bisect_left(a, 30)\n", + "print(i)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### insort_left\n", + "This inserts an item into the list in the correct position." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[24, 33, 41, 41, 44, 45, 50, 53, 59, 62, 66, 70]\n" + ] + } + ], + "source": [ + "d = [24, 33, 41, 41, 45, 50, 53, 59, 62, 66, 70]\n", + "bisect.insort_left(d, 44)\n", + "print(d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### bisect_right\n", + "Just like bisect_left, but for matches it returns the spot just to the right of matches." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "a = [24, 33, 41, 41, 45, 50, 53, 59, 62, 66, 70]\n", + "i = bisect.bisect_right(a, 41)\n", + "print(i)\n", + "\n", + "b = [1.3, 2.2, 3.4, 4.6, 5.5, 6.9, 7.2, 8.4]\n", + "j = bisect.bisect_right(b, 2.2)\n", + "print(j)\n", + "\n", + "c = ['A', 'big', 'dog', 'runs', 'slowly']\n", + "k = bisect.bisect_right(c, 'dog')\n", + "print(k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### insort_right\n", + "Just like insort_left, but for matches it inserts to the right of the match." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[24, 33, 41, 41, 45, 46, 50, 53, 59, 62, 66, 70]\n" + ] + } + ], + "source": [ + "d = [24, 33, 41, 41, 45, 50, 53, 59, 62, 66, 70]\n", + "bisect.insort_right(d, 46)\n", + "print(d)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A fast Find function for a Sorted List\n", + "Find leftmost value greater than x in sorted list a" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n" + ] + } + ], + "source": [ + "def find_next(a, x):\n", + " i = bisect.bisect_right(a, x)\n", + " if i < len(a):\n", + " return a[i]\n", + " return False\n", + "\n", + "print(find_next([10, 15, 20, 25, 30], 33))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A simple get_grade function\n", + "get_grade uses a list of cutoffs to split grades into 5 ranges, then uses the bisect index to return the corresponding grade. " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['F', 'A', 'C', 'C', 'B', 'A', 'A']\n" + ] + } + ], + "source": [ + "def get_grade(score, cutoffs=[60, 70, 80, 90], grades='FDCBA'):\n", + " i = bisect.bisect_right(cutoffs, score)\n", + " return grades[i]\n", + "\n", + "grades = [get_grade(score) for score in [52, 99, 77, 70, 89, 90, 100]]\n", + "print(grades)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Python Generators.ipynb b/Python Generators.ipynb new file mode 100644 index 00000000..1a68f384 --- /dev/null +++ b/Python Generators.ipynb @@ -0,0 +1,224 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Generators\n", + "[documentation](https://docs.python.org/3/howto/functional.html#generators) \n", + "[Another really good tutorial](https://realpython.com/introduction-to-python-generators/#using-generators)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*yield* keyword makes a function into a generator. Python keeps the call stack for the generator function open and saves the state. When you invoke the next() function it will return execution to the same point it left off in the generator function." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simple generator function \n", + "The while loop continues indefinitely. The function increments x then returns x with each iteration." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "def my_generator(x=1):\n", + " while True:\n", + " yield x\n", + " x += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the generator with a for loop\n", + "Here, gene is a my_generator function. \n", + "The for loop iterates through gene indefinitely. \n", + "Behind the scenes, the for loop is calling the generator's \\__next__ function. \n", + "Big advantages over Lists: \n", + "- Generator can provide an infinite seqence. \n", + "- Generator doesn't load values into memory. " + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 " + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mgene\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend\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[0;32m----> 7\u001b[0;31m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "import time\n", + "gene = my_generator()\n", + "print(type(gene))\n", + "\n", + "for i in gene:\n", + " print(i, end=' ')\n", + " time.sleep(0.5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the generator with explicit next( ) calls\n", + "*range* limits this for loop to 10 iterations. \n", + "Each iteration of the for loop it calls the generator using *next(gene)*." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2 3 4 5 6 7 8 9 10 11 " + ] + } + ], + "source": [ + "gene = my_generator()\n", + "print(gene.__next__())\n", + "for i in range(10):\n", + " print(next(gene), end=' ')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generators from Generator Expressions\n", + "Similar to List Comprehensions, but uses ( ) rather than [ ]. \n", + "Create with a single line of code. \n", + "Only use 120 bytes of memory." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "120\n", + "\n", + "0\n", + "3\n" + ] + } + ], + "source": [ + "gene = (x for x in range(999999))\n", + "\n", + "import sys\n", + "print(sys.getsizeof(gene))\n", + "print(type(gene))\n", + "\n", + "print(next(gene))\n", + "next(gene)\n", + "next(gene)\n", + "print(next(gene))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generator to Read File\n", + "Saves memory, and avoids memory overflow for very large files, because it only *loads one line into memory at a time*." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Rolling Stones\n", + "\n", + "Lady Gaga\n", + "Jackson Browne\n", + "Maroon 5\n", + "Arijit Singh\n", + "Elton John\n", + "John Mayer\n" + ] + } + ], + "source": [ + "def read_file(fn = 'bands.txt'):\n", + " for line in open(fn):\n", + " yield line\n", + " \n", + "band = read_file()\n", + "print(next(band))\n", + "for i in range(6):\n", + " print(next(band), end='')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Python List Iteration.ipynb b/Python List Iteration.ipynb new file mode 100644 index 00000000..7361caaf --- /dev/null +++ b/Python List Iteration.ipynb @@ -0,0 +1,197 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python List Iteration\n", + "A variety of ways to iterate Lists, including for loop, while loop, enumerate." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "The standard for loop works well if it is used inside the loop you only need the item and not its index." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a\n", + "b\n", + "c\n", + "d\n", + "e\n" + ] + } + ], + "source": [ + "letters = ['a', 'b', 'c', 'd', 'e']\n", + "\n", + "for letter in letters:\n", + " print(letter)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "If you need the index inside the loop you can use range(len(list)). \n", + "Then you can always get the list item if needed by using the index." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "letters 0 = a\n", + "letters 1 = b\n", + "letters 2 = c\n", + "letters 3 = d\n", + "letters 4 = e\n" + ] + } + ], + "source": [ + "for index in range(len(letters)):\n", + " print('letters', index, '=', letters[index])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "Best option if you need both index and item inside the loop is to use Python's **enumerate** function. \n", + "Enumerate works in both Python 2.x and 3.x" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "letters 0 = a\n", + "letters 1 = b\n", + "letters 2 = c\n", + "letters 3 = d\n", + "letters 4 = e\n" + ] + } + ], + "source": [ + "for index, item in enumerate(letters):\n", + " print('letters', index, '=', item)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Enumerate actually returns an iterable enumerate object, \n", + "which is a sequence of tuples of (index, item)." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 'a')\n", + "(1, 'b')\n", + "\n" + ] + } + ], + "source": [ + "enum_obj = enumerate(letters)\n", + "print(next(enum_obj))\n", + "print(next(enum_obj))\n", + "print(type(enum_obj))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "Probably the clumsiest way to iterate a list in Python -- the **while loop**. \n", + "Requires index initialization before list, and incrementation inside loop." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "letters 0 = a\n", + "letters 1 = b\n", + "letters 2 = c\n", + "letters 3 = d\n", + "letters 4 = e\n" + ] + } + ], + "source": [ + "index = 0\n", + "while index < len(letters): \n", + " print('letters', index, '=', letters[index]) \n", + " index += 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Python Random Numbers Module.ipynb b/Python Random Numbers Module.ipynb new file mode 100644 index 00000000..db837a8c --- /dev/null +++ b/Python Random Numbers Module.ipynb @@ -0,0 +1,450 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Random Numbers Module\n", + "[Official Documentation](https://docs.python.org/3/library/random.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import random" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### randint\n", + "Gives you a random integer between from and to values, inclusive." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 2 3 1 1 2 0 2 3 2 0 0 2 2 0 3 3 2 1 2 3 0 2 2 2 " + ] + } + ], + "source": [ + "for i in range (25):\n", + " print(random.randint(0, 3), end=' ')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### randrange\n", + "Works similar to the range function -- gives you a random number between from and to-1, with optional step. \n", + "From defaults to 0 if only 1 argument is given. \n", + "Step defaults to 1 if only 2 arguments are given." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "25\n", + "3 6 6 6 6 3 3 3 0 0 6 6 3 0 6 0 3 0 6 6 6 6 3 3 6 " + ] + } + ], + "source": [ + "print(random.randrange(100))\n", + "\n", + "for i in range (25):\n", + " print(random.randrange(0, 9, 3), end=' ')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### choice\n", + "Returns one randomly chosen item from a sequence (list, tuple or string). Works for lists/tuples of integers, floats, strings or other objects. " + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "9\n", + "Roby\n", + "Darby\n", + "Washington\n", + "Hampton\n" + ] + } + ], + "source": [ + "print(random.choice([3, 5, 7, 9, 11]))\n", + "\n", + "names = ['Roby', 'Matthews', 'Washington', 'Darby', 'Hampton']\n", + "for i in range(4):\n", + " print(random.choice(names))" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-\n", + "a c e b b a e d c c " + ] + } + ], + "source": [ + "print(random.choice('bunch-of-letters'))\n", + "\n", + "material = 'brocade'\n", + "for i in range(10):\n", + " print(random.choice(material), end=' ')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### choices\n", + "Just like choice, but returns a list of n random choices, with replacement, so each pick is from the full sequence." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[9, 5, 3, 6, 5, 6, 5, 3, 1, 5, 10, 1, 4, 4, 10]\n", + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n" + ] + } + ], + "source": [ + "numbers = [n+1 for n in range(10)]\n", + "my_picks = random.choices(numbers, k=15)\n", + "print(my_picks)\n", + "print(numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Darby', 'Hampton']\n" + ] + } + ], + "source": [ + "names = ['Roby', 'Matthews', 'Washington', 'Darby', 'Hampton']\n", + "print(random.choices(names, k=2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also add weights if you want some items to have a better chance of being picked. Here, 1 is 4x more likely than 4 to be picked." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 1, 3, 4, 1, 1, 1, 3, 2, 2, 2, 4, 2, 1, 1, 3, 2, 3, 1, 3]\n" + ] + } + ], + "source": [ + "numbers = [1,2,3,4]\n", + "my_picks = random.choices(numbers, weights=[4,3,2,1], k=20)\n", + "print(my_picks)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Use random.choices to generate random passwords \n", + "First we pick a list of 8 random numbers between a and z on the ascii table, then we convert the numbers to ascii letters, then join them into a string." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[100, 109, 104, 100, 103, 102, 118, 121]\n", + "dmhdgfvy\n" + ] + } + ], + "source": [ + "picks = random.choices(range(ord('a'),ord('z')), k=8)\n", + "print(picks)\n", + "picks = [chr(i) for i in picks]\n", + "print(''.join(picks))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here's a random password generator that uses all upper and lower case letters and numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Z81Hw3uk\n" + ] + } + ], + "source": [ + "import string\n", + "all_chars = string.ascii_lowercase + string.ascii_uppercase + string.digits\n", + "pw = ''.join(random.choices(all_chars, k=8))\n", + "print(pw)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### sample\n", + "Just like choices, but without replacement. \n", + "Useful for picking lottery winners or bingo numbers. \n", + "Returned list is in the order they were picked." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['green', 'pink']\n" + ] + } + ], + "source": [ + "colors = ['red', 'blue', 'green', 'aqua', 'pink', 'black']\n", + "picks = random.sample(colors, k=2)\n", + "print(picks)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using the range function as an argument will not give you any duplicate picks." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[18, 38, 20, 50, 1]\n" + ] + } + ], + "source": [ + "picks = random.sample(range(1,51), k=5)\n", + "print(picks)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### shuffle\n", + "Shuffle any sequence into random order. \n", + "This is an in-place shuffle, and it doesn't return anything." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4, 5, 6, 7, 8]\n", + "None\n", + "[2, 6, 8, 1, 4, 7, 5, 3]\n" + ] + } + ], + "source": [ + "numbers = [1, 2, 3, 4, 5, 6, 7, 8]\n", + "print(numbers)\n", + "print(random.shuffle(numbers))\n", + "\n", + "random.shuffle(numbers)\n", + "print(numbers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### random.random()\n", + "Random floating point values between 0.0 and 1.0." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.8424897774160051\n", + "0.9016594664191279\n", + "0.5162849368345925\n", + "0.021852081927422384\n", + "0.5740618908246983\n", + "0.6539291129848911\n" + ] + } + ], + "source": [ + "print(random.random())\n", + "\n", + "for i in range(5):\n", + " print(random.random())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### uniform (from, to)\n", + "Random float between a range of values" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.5032833557221568\n", + "10.31258224982709\n", + "9.431820659293221\n", + "10.4390639618008\n", + "9.6906814789157\n", + "10.559354593909362\n" + ] + } + ], + "source": [ + "print(random.uniform(2.1, 4.3))\n", + "\n", + "for i in range(5):\n", + " print(random.uniform(9.4, 10.7))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Python Set Comprehensions.ipynb b/Python Set Comprehensions.ipynb new file mode 100644 index 00000000..475521cb --- /dev/null +++ b/Python Set Comprehensions.ipynb @@ -0,0 +1,331 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Set Comprehensions\n", + "Note that Python sets are not ordered, and duplicates are automatically removed. \n", + "Otherwise, comprehensions work just like with lists. \n", + "General syntax is: new_set = {expression for item in iterable if condition}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simple Comprehension using Range" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n" + ] + } + ], + "source": [ + "ints = {i for i in range(10)}\n", + "print(ints)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Comprehension using Range with a Condition filter\n", + "Only take even values from range" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0, 2, 4, 6, 8}\n" + ] + } + ], + "source": [ + "evens = {i for i in range(10) if i%2 == 0}\n", + "print(evens)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Apply math function to values in range\n", + "Here, square each value" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}\n" + ] + } + ], + "source": [ + "squares = {i*i for i in range(10)}\n", + "print(squares)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that Python eliminates duplicates from sets" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0, 1, 4, 9, 16, 25}\n" + ] + } + ], + "source": [ + "sqrs = {i*i for i in range(-5, 5)}\n", + "print(sqrs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Set Comprehension on a List" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{4, 9, 169, 49, 121, 25}\n" + ] + } + ], + "source": [ + "primes = [2, 2, 2, 3, 3, 5, 5, 5, 7, 11, 11, 13, 13, 13, 13]\n", + "primes_squared = {p*p for p in primes}\n", + "print(primes_squared)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### More Complex Expressions: quadratic transformation\n", + "Any expression is allowed. More complex expressions can be put in parentheses. \n", + "Here, quadratic equation: \n", + "2x^2 + 5x + 10" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{43, 143, 307, 85, 28, 413}\n" + ] + } + ], + "source": [ + "transformed = {(2*x*x + 5*x + 10) for x in primes}\n", + "print(transformed)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Flatten List and eliminate duplicates\n", + "Syntax: {leaf for branch in tree for leaf in branch}" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{1, 2, 3, 98, 76}\n" + ] + } + ], + "source": [ + "nums = [[1,3],[2,3],[3,98],[76,1]]\n", + "flat_set = {a for b in nums for a in b}\n", + "print(flat_set)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Eliminate Dups from a List\n", + "We can easily eliminate differences in capitalization, while removing duplicates." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Albert', 'Ella', 'George', 'Salil'}\n" + ] + } + ], + "source": [ + "names = ['salil', 'ALBERT', 'Ella', 'george', 'Salil', 'George', 'ELLA', 'Albert']\n", + "names_set = {n.capitalize() for n in names}\n", + "print(names_set)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And it's easy to convert this back to a list." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Albert', 'Ella', 'George', 'Salil']\n" + ] + } + ], + "source": [ + "names_set = list({n.capitalize() for n in names})\n", + "print(names_set)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Car Make from list of Make & Model\n", + "We're getting the first word from each string." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Toyota', 'Tesla', 'Chevy'}\n" + ] + } + ], + "source": [ + "cars = ['Toyota Prius', 'Chevy Bolt', 'Tesla Model 3', 'Tesla Model Y']\n", + "makes = {(c.split()[0]) for c in cars}\n", + "print(makes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Initials from Names\n", + "Take first and last initials" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'CB', 'NF', 'HP'}\n" + ] + } + ], + "source": [ + "names = ['Clint Barton', 'Tony', 'Nick Fury', 'Hank Pym']\n", + "inits = {(n.split()[0][0] + n.split()[1][0]) for n in names if len(n.split())==2}\n", + "print(inits)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Queues implementaion.py b/Queues implementaion.py new file mode 100644 index 00000000..63170c8c --- /dev/null +++ b/Queues implementaion.py @@ -0,0 +1,64 @@ + +# implemented by Linked list +class Node(object): + def __init__(self, item = None): + self.item = item + self.next = None + self.previous = None + + +class Queue(object): + def __init__(self): + self.length = 0 + self.head = None + self.tail = None + + def enqueue(self, x): + newNode = Node(x) + if self.head == None: + self.head = self.tail = newNode + else: + self.tail.next = newNode + newNode.previous = self.tail + self.tail = newNode + self.length += 1 + + + def dequeue (self): + item = self.head.item + self.head = self.head.next + self.length -= 1 + if self.length == 0: + self.last = None + return item + + +################################################# + +# implemented by array +class Queue: + def __init__(self): + self.items = [] + + def is_empty(self): + return self.items == [] + + def enqueue(self, data): + self.items.append(data) + + def dequeue(self): + return self.items.pop(0) + + def display(self): + ar = [] + for i in self.items: + ar.append(i) + return ar +que = Queue() +que.enqueue('google') +que.enqueue('youtube') +que.enqueue('udemy') +que.enqueue('udacity') +que.dequeue() +que.dequeue() +print(que.display()) diff --git a/README.md b/README.md index 6f0d92be..939de1ed 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,19 @@ -# Python +#This is a open source project. +# Python 3 These files are mainly intended to accompany my series of YouTube tutorial videos here, https://www.youtube.com/user/joejamesusa and are mainly intended for educational purposes. -You are invited to subscribe to my video channel, and to download and use any code in +You are invited to subscribe to my video channel-Joe James, and to download and use any code in this Python repository, according to the MIT License. Feel free to post any comments on my YouTube channel. +I am very happy to see you there on my you tube channel. excited!!!!!!!!! +## Subscribe to my channel for more tutorial videos. +This source code is easy to understand and reliable for self study and you will learn them easily, try to practice more coding by making algorithms yourself and you can become a better Python programmer, and remember "Try to learn something about everything and everything about something". + +Thank you for reviewing my repositories and keep practicing. Joe James. -Fremont, California. -Copyright (C) 2015-2019, Joe James +Fremont, CA. +Copyright (C) 2015-2021, Joe James + +## Happy coding guys!😀 diff --git a/Sorting Algorithms/Heapsort.py b/Sorting Algorithms/Heapsort.py new file mode 100644 index 00000000..9a2e2c14 --- /dev/null +++ b/Sorting Algorithms/Heapsort.py @@ -0,0 +1,33 @@ +# heapify +def heapify(arr, n, i): + largest = i # largest value + l = 2 * i + 1 # left + r = 2 * i + 2 # right + # if left child exists + if l < n and arr[i] < arr[l]: + largest = l + # if right child exits + if r < n and arr[largest] < arr[r]: + largest = r + # root + if largest != i: + arr[i],arr[largest] = arr[largest],arr[i] # swap + # root. + heapify(arr, n, largest) +# sort +def heapSort(arr): + n = len(arr) + # maxheap + for i in range(n, -1, -1): + heapify(arr, n, i) + # element extraction + for i in range(n-1, 0, -1): + arr[i], arr[0] = arr[0], arr[i] # swap + heapify(arr, i, 0) +# main +arr = [2,5,3,8,6,5,4,7] +heapSort(arr) +n = len(arr) +print ("Sorted array is") +for i in range(n): + print (arr[i],end=" ") diff --git a/Sorting Algorithms/Python QuickSort.ipynb b/Sorting Algorithms/Python QuickSort.ipynb new file mode 100644 index 00000000..5f925c81 --- /dev/null +++ b/Sorting Algorithms/Python QuickSort.ipynb @@ -0,0 +1,140 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python QuickSort Algorithm" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 9, 1, 2, 4, 8, 6, 3, 7]\n", + "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n" + ] + } + ], + "source": [ + "#---------------------------------------\n", + "# Quick Sort\n", + "#---------------------------------------\n", + "def quick_sort(A):\n", + " quick_sort2(A, 0, len(A)-1)\n", + " \n", + "def quick_sort2(A, low, hi):\n", + " if hi-low < 1 and low < hi:\n", + " quick_selection(A, low, hi)\n", + " elif low < hi:\n", + " p = partition(A, low, hi)\n", + " quick_sort2(A, low, p - 1)\n", + " quick_sort2(A, p + 1, hi)\n", + " \n", + "def get_pivot(A, low, hi):\n", + " mid = (hi + low) // 2\n", + " s = sorted([A[low], A[mid], A[hi]])\n", + " if s[1] == A[low]:\n", + " return low\n", + " elif s[1] == A[mid]:\n", + " return mid\n", + " return hi\n", + " \n", + "def partition(A, low, hi):\n", + " pivotIndex = get_pivot(A, low, hi)\n", + " pivotValue = A[pivotIndex]\n", + " A[pivotIndex], A[low] = A[low], A[pivotIndex]\n", + " border = low\n", + "\n", + " for i in range(low, hi+1):\n", + " if A[i] < pivotValue:\n", + " border += 1\n", + " A[i], A[border] = A[border], A[i]\n", + " A[low], A[border] = A[border], A[low]\n", + "\n", + " return (border)\n", + " \n", + "def quick_selection(x, first, last):\n", + " for i in range (first, last):\n", + " minIndex = i\n", + " for j in range (i+1, last+1):\n", + " if x[j] < x[minIndex]:\n", + " minIndex = j\n", + " if minIndex != i:\n", + " x[i], x[minIndex] = x[minIndex], x[i]\n", + " \n", + "A = [5,9,1,2,4,8,6,3,7]\n", + "print(A)\n", + "quick_sort(A)\n", + "print(A)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Nice simple version written by Mr. UncleChu in comments\n", + "Slick code, but does not sort in place, so uses a lot more memory. Do not use for large lists or you'll get stackoverflow." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 9, 1, 2, 4, 8, 6, 3, 7]\n", + "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n" + ] + } + ], + "source": [ + "def quick_sort_chu(a_list):\n", + " if len(a_list) < 2: return a_list\n", + " lesser = quick_sort([x for x in a_list[1:] if x <= a_list[0]])\n", + " bigger = quick_sort([x for x in a_list[1:] if x > a_list[0]])\n", + " return sum([lesser, [a_list[0]], bigger], [])\n", + "A = [5,9,1,2,4,8,6,3,7]\n", + "print(A)\n", + "B = quick_sort_chu(A)\n", + "print(B)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Sorting Algorithms/Radix_Sort.ipynb b/Sorting Algorithms/Radix_Sort.ipynb new file mode 100644 index 00000000..0b701528 --- /dev/null +++ b/Sorting Algorithms/Radix_Sort.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Radix Sort\n", + "(c) 2020, Joe James" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# get number of digits in largest item\n", + "def __get_num_digits(A):\n", + " m = 0\n", + " for item in A:\n", + " m = max(m, item)\n", + " return len(str(m))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# flatten into a 1D List\n", + "from functools import reduce\n", + "def __flatten(A):\n", + " return reduce(lambda x, y: x + y, A)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Changed from YouTube video:\n", + "It's much cleaner to put the _get_num_digits call inside the radix function rather than in main as shown in the video. That way you only need to pass a List to the radix function. Thanks to Brother Lui for this suggestion." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def radix(A):\n", + " num_digits = __get_num_digits(A)\n", + " for digit in range(0, num_digits):\n", + " B = [[] for i in range(10)]\n", + " for item in A:\n", + " # num is the bucket number that the item will be put into\n", + " num = item // 10 ** (digit) % 10\n", + " B[num].append(item)\n", + " A = __flatten(B)\n", + " return A" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 45, 53, 55, 213, 288, 289]\n", + "[0, 1, 2, 3, 4, 5] [999994, 999995, 999996, 999997, 999998, 999999]\n" + ] + } + ], + "source": [ + "def main():\n", + " A = [55, 45, 3, 289, 213, 1, 288, 53, 2]\n", + " A = radix(A)\n", + " print(A)\n", + " \n", + " B = [i for i in range(1000000)]\n", + " from random import shuffle\n", + " shuffle(B)\n", + " B = radix(B)\n", + " print(B[:6], B[-6:])\n", + "\n", + "main()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Stacks, Queues & Heaps.ipynb b/Stacks, Queues & Heaps.ipynb new file mode 100644 index 00000000..a54ede21 --- /dev/null +++ b/Stacks, Queues & Heaps.ipynb @@ -0,0 +1,346 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Stacks, Queues & Heaps\n", + "© Joe James, 2019.\n", + "\n", + "### Stack using Python List\n", + "Stack is a LIFO data structure -- last-in, first-out. \n", + "Use append() to push an item onto the stack. \n", + "Use pop() to remove an item." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[4, 7, 12, 19]\n" + ] + } + ], + "source": [ + "my_stack = list()\n", + "my_stack.append(4)\n", + "my_stack.append(7)\n", + "my_stack.append(12)\n", + "my_stack.append(19)\n", + "print(my_stack)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "19\n", + "12\n", + "[4, 7]\n" + ] + } + ], + "source": [ + "print(my_stack.pop())\n", + "print(my_stack.pop())\n", + "print(my_stack)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Stack using List with a Wrapper Class\n", + "We create a Stack class and a full set of Stack methods. \n", + "But the underlying data structure is really a Python List. \n", + "For pop and peek methods we first check whether the stack is empty, to avoid exceptions." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "class Stack():\n", + " def __init__(self):\n", + " self.stack = list()\n", + " def push(self, item):\n", + " self.stack.append(item)\n", + " def pop(self):\n", + " if len(self.stack) > 0:\n", + " return self.stack.pop()\n", + " else:\n", + " return None\n", + " def peek(self):\n", + " if len(self.stack) > 0:\n", + " return self.stack[len(self.stack)-1]\n", + " else:\n", + " return None\n", + " def __str__(self):\n", + " return str(self.stack)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Test Code for Stack Wrapper Class" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 3]\n", + "3\n", + "1\n", + "1\n", + "None\n" + ] + } + ], + "source": [ + "my_stack = Stack()\n", + "my_stack.push(1)\n", + "my_stack.push(3)\n", + "print(my_stack)\n", + "print(my_stack.pop())\n", + "print(my_stack.peek())\n", + "print(my_stack.pop())\n", + "print(my_stack.pop())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "### Queue using Python Deque\n", + "Queue is a FIFO data structure -- first-in, first-out. \n", + "Deque is a double-ended queue, but we can use it for our queue. \n", + "We use append() to enqueue an item, and popleft() to dequeue an item. \n", + "See [Python docs](https://docs.python.org/3/library/collections.html#collections.deque) for deque." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "deque([5, 10])\n", + "5\n" + ] + } + ], + "source": [ + "from collections import deque\n", + "my_queue = deque()\n", + "my_queue.append(5)\n", + "my_queue.append(10)\n", + "print(my_queue)\n", + "print(my_queue.popleft())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Fun exercise:\n", + "Write a wrapper class for the Queue class, similar to what we did for Stack, but using Python deque. \n", + "Try adding enqueue, dequeue, and get_size methods." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Python Single-ended Queue Wrapper Class using Deque\n", + "We rename the append method to enqueue, and popleft to dequeue. \n", + "We also add peek and get_size operations." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from collections import deque\n", + "class Queue():\n", + " def __init__(self):\n", + " self.queue = deque()\n", + " self.size = 0\n", + " def enqueue(self, item):\n", + " self.queue.append(item)\n", + " self.size += 1\n", + " def dequeue(self, item):\n", + " if self.size > 0:\n", + " self.size -= 1\n", + " return self.queue.popleft()\n", + " else: \n", + " return None\n", + " def peek(self):\n", + " if self.size > 0:\n", + " ret_val = self.queue.popleft()\n", + " queue.appendleft(ret_val)\n", + " return ret_val\n", + " else:\n", + " return None\n", + " def get_size(self):\n", + " return self.size" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Python MaxHeap\n", + "A MaxHeap always bubbles the highest value to the top, so it can be removed instantly. \n", + "Public functions: push, peek, pop \n", + "Private functions: __swap, __floatUp, __bubbleDown, __str__." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "class MaxHeap:\n", + " def __init__(self, items=[]):\n", + " super().__init__()\n", + " self.heap = [0]\n", + " for item in items:\n", + " self.heap.append(item)\n", + " self.__floatUp(len(self.heap) - 1)\n", + "\n", + " def push(self, data):\n", + " self.heap.append(data)\n", + " self.__floatUp(len(self.heap) - 1)\n", + "\n", + " def peek(self):\n", + " if self.heap[1]:\n", + " return self.heap[1]\n", + " else:\n", + " return False\n", + " \n", + " def pop(self):\n", + " if len(self.heap) > 2:\n", + " self.__swap(1, len(self.heap) - 1)\n", + " max = self.heap.pop()\n", + " self.__bubbleDown(1)\n", + " elif len(self.heap) == 2:\n", + " max = self.heap.pop()\n", + " else: \n", + " max = False\n", + " return max\n", + "\n", + " def __swap(self, i, j):\n", + " self.heap[i], self.heap[j] = self.heap[j], self.heap[i]\n", + "\n", + " def __floatUp(self, index):\n", + " parent = index//2\n", + " if index <= 1:\n", + " return\n", + " elif self.heap[index] > self.heap[parent]:\n", + " self.__swap(index, parent)\n", + " self.__floatUp(parent)\n", + "\n", + " def __bubbleDown(self, index):\n", + " left = index * 2\n", + " right = index * 2 + 1\n", + " largest = index\n", + " if len(self.heap) > left and self.heap[largest] < self.heap[left]:\n", + " largest = left\n", + " if len(self.heap) > right and self.heap[largest] < self.heap[right]:\n", + " largest = right\n", + " if largest != index:\n", + " self.__swap(index, largest)\n", + " self.__bubbleDown(largest)\n", + " \n", + " def __str__(self):\n", + " return str(self.heap)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### MaxHeap Test Code" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 95, 10, 21, 3]\n", + "95\n", + "21\n" + ] + } + ], + "source": [ + "m = MaxHeap([95, 3, 21])\n", + "m.push(10)\n", + "print(m)\n", + "print(m.pop())\n", + "print(m.peek())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/String Formatting.ipynb b/String Formatting.ipynb new file mode 100644 index 00000000..82546e12 --- /dev/null +++ b/String Formatting.ipynb @@ -0,0 +1,444 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python String format()\n", + "[Official docs](https://docs.python.org/3/library/string.html#format-string-syntax) \n", + "[more documentation](https://pyformat.info)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Replace with String - positional" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "My name is Alex.\n", + "My name is Alex Marshall.\n" + ] + } + ], + "source": [ + "first_name = 'Alex'\n", + "last_name = 'Marshall'\n", + "print('My name is {}.'.format(first_name))\n", + "print('My name is {} {}.'.format(first_name, last_name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Replace with String using Index\n", + "Using indexes can be useful when order varies." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "My name is Alex Marshall.\n", + "My name is Marshall, Alex. First name Alex\n" + ] + } + ], + "source": [ + "print('My name is {0} {1}.'.format(first_name, last_name))\n", + "print('My name is {1}, {0}. First name {0}'.format(first_name, last_name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Alignment: Align Left, Right, Middle\n", + "{:<} align Left (default is align left, so this is optional) \n", + "{:>n} align Right with n padding spaces \n", + "{:^n} align Middle with n padding spaces" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of cases: 5\n", + "Number of cases: 16\n", + "Number of cases: 294\n", + "Number of cases: 5\n", + "Number of cases: 16\n", + "Number of cases: 294\n" + ] + } + ], + "source": [ + "# align left - these both do the same thing\n", + "cases = [5, 16, 294]\n", + "for case in cases:\n", + " print('Number of cases: {}'.format(case))\n", + "for case in cases:\n", + " print('Number of cases: {:<}'.format(case))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of cases: 5\n", + "Number of cases: 16\n", + "Number of cases: 294\n" + ] + } + ], + "source": [ + "# align right with 5 total spaces\n", + "for case in cases:\n", + " print('Number of cases:{:>5}'.format(case))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of cases: 5 \n", + "Number of cases: 16 \n", + "Number of cases: 294 \n" + ] + } + ], + "source": [ + "# align center with 5 total spaces\n", + "for case in cases:\n", + " print('Number of cases:{:^5}'.format(case))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Integers & Floats\n", + "{:d} Integer variable \n", + "{:5d} Integer with padding of 5 \n", + "{:f} Floating point variable " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Length is 26.\n", + "Length is 26.\n", + "In dog years, I'm 8 .\n" + ] + } + ], + "source": [ + "length = 26\n", + "print('Length is {:d}.'.format(length))\n", + "\n", + "# align right, padding=6, integer\n", + "print('Length is {:>6d}.'.format(length))\n", + "\n", + "# named variable, align center, padding=4, integer\n", + "print(\"In dog years, I'm {age:^5d}.\".format(age=8))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Distance to moon is 238,900 miles.\n" + ] + } + ], + "source": [ + "# integer with commas\n", + "print('Distance to moon is {:,d} miles.'.format(238900))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Radius is 4.780000 inches.\n", + "Radius is 4.8 inches.\n", + "Radius is 0004.8 inches.\n", + "Radius is 4.78000 inches.\n" + ] + } + ], + "source": [ + "radius = 4.78\n", + "print('Radius is {:f} inches.'.format(radius))\n", + "\n", + "# round to 1 decimal place, float\n", + "print('Radius is {:.1f} inches.'.format(radius))\n", + "\n", + "# padding=6 (pads with leading 0's), round to 1 decimal\n", + "print('Radius is {:06.1f} inches.'.format(radius))\n", + "\n", + "# padding=5 decimal places\n", + "print('Radius is {:.5f} inches.'.format(radius))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A is +15. B is -9. C is 33.\n", + "A is +15. B is -9. B is -9.\n" + ] + } + ], + "source": [ + "# positive & negative signs\n", + "a, b, c = 15, -9, 33\n", + "print('A is {:+d}. B is {:+d}. C is {:-d}.'.format(a, b, c))\n", + "\n", + "# {+3d} shows pos or neg sign, padding=3. \n", + "# {: d} prints neg or a leading space if positive.\n", + "print('A is {:+3d}. B is {:+4d}. B is {: d}.'.format(a, b, b))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Named Placeholders\n", + "You can pass in named variables as keyword args, or as an unpacked dict. \n", + "And it's easy to pass in a list." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mekael is a Carpenter.\n" + ] + } + ], + "source": [ + "print(\"{name} is a {job}.\".format(name='Mekael', job='Carpenter'))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "ename": "KeyError", + "evalue": "'name'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mjob\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'Carpenter'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;31m# THIS DOES NOT WORK!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"{name} is a {job}.\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mjob\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m: 'name'" + ] + } + ], + "source": [ + "name = 'Mekael'\n", + "job = 'Carpenter'\n", + "# THIS DOES NOT WORK!\n", + "print(\"{name} is a {job}.\".format(name, job))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mekael is a Carpenter.\n" + ] + } + ], + "source": [ + "# This works great\n", + "print(\"{n} is a {j}.\".format(n=name, j=job))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mekael is a Carpenter.\n" + ] + } + ], + "source": [ + "# Or use a dictionary, and ** unpacks the dictionary.\n", + "jobs = {'name':'Mekael', 'job':'Carpenter'}\n", + "print(\"{name} is a {job}.\".format(**jobs))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Score 2 is 96\n" + ] + } + ], + "source": [ + "# passing in a list is clean and easy\n", + "scores = [78, 96, 83, 86]\n", + "print('Score 2 is {s[1]}'.format(s = scores))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Scientific Notation\n", + "Use {:e}, or upper case E." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "My big number is 8.745770e+02\n", + "A bigger number is 6.022141E+23\n" + ] + } + ], + "source": [ + "print('My big number is {:e}'.format(874.577))\n", + "print('A bigger number is {:E}'.format(602214090000000000000000))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Binary & Hexadecimal\n", + "{:b} converts decimal to binary\n", + "{:x} converts decimal to hex. Or use upper case X for capitals." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The binary equivalent of 79 is 1001111\n", + "The Hexadecimal equivalent of 183 is B7\n" + ] + } + ], + "source": [ + "print('The binary equivalent of 79 is {:b}'.format(79))\n", + "print('The Hexadecimal equivalent of 183 is {:X}'.format(183))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Strings/Using Python Strings.ipynb b/Strings/Using Python Strings.ipynb new file mode 100644 index 00000000..19643b9c --- /dev/null +++ b/Strings/Using Python Strings.ipynb @@ -0,0 +1,518 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using Strings in Python 3\n", + "[Python String docs](https://docs.python.org/3/library/string.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating Strings\n", + "Enclose a string in single or double quotes, or in triple single quotes. \n", + "And you can embed single quotes within double quotes, or double quotes within single quotes. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tony Stark is Ironman.\n", + "Her book is called \"The Magician\".\n", + "Captain Rogers kicks butt.\n" + ] + } + ], + "source": [ + "s = 'Tony Stark is'\n", + "t = \"Ironman.\"\n", + "print(s, t)\n", + "u = 'Her book is called \"The Magician\".'\n", + "print(u)\n", + "v = '''Captain Rogers kicks butt.'''\n", + "print(v)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Type, Len, Split, Join\n", + "Get the number of characters in a string using len. \n", + "To get the number of words you have to split the string into a list. Split uses a space as its default, or you can split on any substring you like. \n", + "To reverse a split, use join(str)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "13\n" + ] + } + ], + "source": [ + "print(type(s))\n", + "print(len(s))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Tony', 'Stark', 'is']\n", + "3\n", + "['Her book is c', 'lled \"The M', 'gici', 'n\".']\n", + "['you', 'are', 'so', 'pretty']\n", + "Just do it.\n" + ] + } + ], + "source": [ + "print(s.split())\n", + "print(len(s.split()))\n", + "print(u.split('a'))\n", + "print('you,are,so,pretty'.split(','))\n", + "print(' '.join(['Just', 'do', 'it.']))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check if a substring is contained in a string\n", + "Use *in* or *not in*. \n", + "Startswith and Endswith are also useful boolean checks." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n", + "False\n", + "True\n", + "True\n", + "True\n" + ] + } + ], + "source": [ + "print('dog' in s)\n", + "print('k' in t)\n", + "print('k' not in t)\n", + "print(s.startswith('Tony'))\n", + "print(s.endswith('is'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Replace all substrings\n", + "Second example iterates through a dictionary and replaces all instances of text numbers with numerals." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Captain America kicks butt.\n" + ] + } + ], + "source": [ + "v = v.replace('Rogers', 'America')\n", + "print(v)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Anton has 3 cars. Javier has 4.\n" + ] + } + ], + "source": [ + "z = 'Anton has three cars. Javier has four.'\n", + "numbers = {'one':'1', 'two':'2', 'three':'3', 'four':'4', 'five':'5'}\n", + "for k,v in numbers.items():\n", + " z = z.replace(k,v)\n", + "print(z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Change case" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tony stark is\n", + "IRONMAN.\n", + "Her Book Is Called \"The Magician\".\n", + "Hulk rules!\n" + ] + } + ], + "source": [ + "print(s.lower())\n", + "print(t.upper())\n", + "print(u.title())\n", + "print('hulk rules!'.capitalize())" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n", + "True\n", + "True\n" + ] + } + ], + "source": [ + "print('david'.islower())\n", + "print('hulk'.isupper())\n", + "print('Hulk'.istitle())\n", + "print('covid19'.isalnum())" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n", + "True\n", + "False\n" + ] + } + ], + "source": [ + "print('Thor'.isalpha())\n", + "print('3.14'.isnumeric())\n", + "print('314'.isdigit())\n", + "print('3.14'.isdecimal())" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0123456789\n", + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n", + "abcdefghijklmnopqrstuvwxyz\n", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" + ] + } + ], + "source": [ + "import string\n", + "print(string.digits)\n", + "print(string.punctuation)\n", + "print(string.ascii_lowercase)\n", + "print(string.ascii_uppercase)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Strip leading or trailing characters\n", + "This is often used to strip blank spaces or newlines, but can be used for much more." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Natasha is a spy.\n", + "Natasha is a spy \n", + "\n", + "\n", + " Natasha is a spy\n", + "Natasha is a spy. She has red hair.\n", + "She has red \n" + ] + } + ], + "source": [ + "w = '\\n Natasha is a spy \\n'\n", + "x = '\\nShe has red hair\\n'\n", + "\n", + "print(w.strip() + '.')\n", + "print(w.lstrip())\n", + "print(w.rstrip())\n", + "print(w.strip() + '. ' + x.strip() + '.')\n", + "print(x.strip().rstrip('arih'))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "What do you want\n" + ] + } + ], + "source": [ + "y = 'What do you want?!!&?'\n", + "print(y.rstrip(string.punctuation))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Find, and Count substrings\n", + "Search from the left with find, or from the right with rfind. \n", + "The return value is the start index of the first match of the substring." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "5\n", + "What do you want?!!&?\n" + ] + } + ], + "source": [ + "print(y.find('a'))\n", + "print(y.rfind('do'))\n", + "print(y)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Natasha is a spy\n", + "4\n" + ] + } + ], + "source": [ + "print(w.strip())\n", + "print(w.count('a'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Strings are immutable\n", + "Any change to a string results in a new string being written to a new block of memory. " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4565794160\n", + "4565793776\n" + ] + } + ], + "source": [ + "m = 'Black widow'\n", + "print(id(m))\n", + "m = m + 's'\n", + "print(id(m))" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tony Stark is Ironman.\n", + "Tony Stark is Ironman.\n" + ] + } + ], + "source": [ + "print(s, t)\n", + "z = s + ' ' + t\n", + "print(z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Slicing Substrings\n", + "string[from:to+1:step]\n", + "Only 1 parameter: it is used as an index. \n", + "From defaults to beginning. \n", + "To defaults to end. \n", + "Step defaults to 1." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "567\n" + ] + } + ], + "source": [ + "z = '0123456789'\n", + "print(z[1])\n", + "print(z[5:8])" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "012\n", + "789\n", + "89\n", + "24\n" + ] + } + ], + "source": [ + "print(z[:3])\n", + "print(z[7:])\n", + "print(z[-2:])\n", + "print(z[2:5:2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Strings/bands.txt b/Strings/bands.txt new file mode 100644 index 00000000..7148cf12 --- /dev/null +++ b/Strings/bands.txt @@ -0,0 +1,38 @@ +Rolling Stones +Lady Gaga +Jackson Browne +Maroon 5 +Arijit Singh +Elton John +John Mayer +CCR +Eagles +Pink +Aerosmith +Adele +Taylor Swift +Faye Wong +UB40 +ColdPlay +Boston +4 Non Blondes +The Cars +Cheap Trick +Def Leppard +Ed Sheeran +Dire Straits +Train +Tom Petty +One Direction +Jimmy Buffett +Mumford & Sons +Phil Collins +Rod Stewart +The Script +Elvis +U2 +Simon & Garfunkel +Michael Buble +Abba +The Jackson 5 +R.E.M. \ No newline at end of file diff --git a/Trees/bst.py b/Trees/bst.py index 9137b4b8..f45b2f4f 100644 --- a/Trees/bst.py +++ b/Trees/bst.py @@ -131,7 +131,6 @@ def remove(self, data): delNodeParent = delNode delNode = delNode.leftChild - self.root.value = delNode.value if delNode.rightChild: if delNodeParent.value > delNode.value: delNodeParent.leftChild = delNode.rightChild @@ -142,6 +141,7 @@ def remove(self, data): delNodeParent.leftChild = None else: delNodeParent.rightChild = None + self.root.value = delNode.value return True @@ -233,4 +233,4 @@ def main(): print(bst.remove(10)) bst.preorder() -main() \ No newline at end of file +main() diff --git a/Unpacking Variables.ipynb b/Unpacking Variables.ipynb new file mode 100644 index 00000000..3b1f8d31 --- /dev/null +++ b/Unpacking Variables.ipynb @@ -0,0 +1,360 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Packing & Unpacking Variables" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assign variables\n", + "In Python you can assign multiple variables at a time using commas." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "a, b, c = 1, 2, 3\n", + "print(a)\n", + "print(b)\n", + "print(c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Swap a pair of Variables in Python\n", + "x,y = y,x" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x=12, y=5\n" + ] + } + ], + "source": [ + "x = 5; y = 12\n", + "x, y = y, x\n", + "print('x=' + str(x) + ', y=' + str(y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Swap a trio of Variables in Python\n", + "Yes, this trick works for 3 variables too." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "88 99 77\n" + ] + } + ], + "source": [ + "x, y, z = 77, 88, 99\n", + "z, x, y = x, y, z\n", + "print(x, y, z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split String into multiple variables\n", + "But be careful because the number of variables must match the number of substrings from the split." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "5\n", + "6\n" + ] + } + ], + "source": [ + "a, b, c = '4 5 6'.split()\n", + "print(a)\n", + "print(b)\n", + "print(c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Splitting a List into variables is magically easy" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "8\n", + "9\n", + "10\n" + ] + } + ], + "source": [ + "my_list = [8, 9, 10]\n", + "a, b, c = my_list\n", + "print(a)\n", + "print(b)\n", + "print(c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split Tuple into variables" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "25 26 27\n" + ] + } + ], + "source": [ + "tup = (25,26,27)\n", + "x, y, z = tup\n", + "print(x, y, z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### This gives you a Tuple, not a List" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(8, 9, 10)\n", + "\n" + ] + } + ], + "source": [ + "var = a, b, c\n", + "print(var)\n", + "print(type(var))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### *args for Functions\n", + "Used for passing a non-keyworded, variable-length argument list to a function. \n", + "Received as a Tuple." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('Forest', 'Hill', 'High')\n", + "\n" + ] + } + ], + "source": [ + "def pack_it(*args):\n", + " print(args)\n", + " print(type(args))\n", + " \n", + "x = 'Forest'; y = 'Hill'; z = 'High'\n", + "pack_it(x, y, z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This unpacks the List before sending it, so it can be received by the function as separate variables." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cullen\n", + "McDonough\n" + ] + } + ], + "source": [ + "def unpack_it(x, y):\n", + " print(x)\n", + " print(y)\n", + " \n", + "args = ['Cullen', 'McDonough']\n", + "unpack_it(*args)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### **kwargs for Functions\n", + "Used for passing keyworded, variable-length argument dictionary to functions. \n", + "This works, but it's kinda annoying because some normal Python dictionaries fail. \n", + "func (1:'Edsel', 2:'Betamax') does not work." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'a': 'Edsel', 'b': 'Betamax', 'c': 'mGaetz'}\n", + "Edsel\n", + "\n" + ] + } + ], + "source": [ + "def func(**losers):\n", + " print(losers)\n", + " print(losers['a'])\n", + " print(type(losers))\n", + " \n", + "func(a='Edsel', b='Betamax', c='mGaetz')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This works, but it's kinda annoying because you have to use strings for the keys, so some normal Python dictionaries will give you an error. {1:'Edsel', 2:'Betamax'} fails." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Edsel\n" + ] + } + ], + "source": [ + "def func(a, b, c):\n", + " print(a)\n", + "\n", + "losers = {'a':'Edsel', 'b':'Betamax', 'c':'mGaetz'}\n", + "func(**losers)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Web Data Mining/Python Requests.ipynb b/Web Data Mining/Python Requests.ipynb index 6b9274ec..66f27fed 100644 --- a/Web Data Mining/Python Requests.ipynb +++ b/Web Data Mining/Python Requests.ipynb @@ -19,7 +19,8 @@ "metadata": {}, "outputs": [], "source": [ - "import requests" + "import requests\n", + "import json" ] }, { diff --git a/addition of two number b/addition of two number new file mode 100644 index 00000000..d31335e3 --- /dev/null +++ b/addition of two number @@ -0,0 +1,9 @@ +# Store input numbers +num1 = input('Enter first number: ') +num2 = input('Enter second number: ') + +# Add two numbers +sum = float(num1) + float(num2) + +# Display the sum +print('The sum of {0} and {1} is {2}'.format(num1, num2, sum)) diff --git a/deep_copy.ipynb b/deep_copy.ipynb new file mode 100644 index 00000000..a11d7052 --- /dev/null +++ b/deep_copy.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python: how to Copy and Deep Copy Python Lists \n", + "(c) Joe James 2023" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assignment is not a Copy\n", + "listA = listB does not create a copy. Changes to one list will be reflected in the other.\n", + "listA and listB both reference the exact same list." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 44, 6, [1, 3]]\n", + "140554034568968\n", + "140554034568968\n" + ] + } + ], + "source": [ + "listA = [2, 4, 6, [1, 3]]\n", + "listB = listA\n", + "listB[1] = 44\n", + "print(listA)\n", + "print(id(listA))\n", + "print(id(listB))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Shallow copy using the list() constructor\n", + "Shallow copy only works for 1D lists of native data types. \n", + "Sublists, dicts, and other objects will retain the same referece to those objects." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6, [55, 3]]\n" + ] + } + ], + "source": [ + "listA = [2, 4, 6, [1, 3]]\n", + "listB = list(listA)\n", + "listB[1] = 44\n", + "listB[3][0] = 55\n", + "print(listA)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Other ways to make a Shallow copy\n", + "List comprehensions, list.copy(), or copy.copy() can also be used to make *shallow* copies" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6, [55, 3]]\n" + ] + } + ], + "source": [ + "listA = [2, 4, 6, [1, 3]]\n", + "listB = [x for x in listA]\n", + "listB[1] = 44\n", + "listB[3][0] = 55\n", + "print(listA)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6, [55, 3]]\n" + ] + } + ], + "source": [ + "listA = [2, 4, 6, [1, 3]]\n", + "listB = listA.copy()\n", + "listB[1] = 44\n", + "listB[3][0] = 55\n", + "print(listA)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6, [55, 3]]\n" + ] + } + ], + "source": [ + "import copy\n", + "listA = [2, 4, 6, [1, 3]]\n", + "listB = copy.copy(listA)\n", + "listB[1] = 44\n", + "listB[3][0] = 55\n", + "print(listA)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How to Deep Copy a Python List\n", + "use copy.deepcopy()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6, [1, 3]]\n" + ] + } + ], + "source": [ + "import copy\n", + "listA = [2, 4, 6, [1, 3]]\n", + "listB = copy.deepcopy(listA)\n", + "listB[1] = 44\n", + "listB[3][0] = 55\n", + "print(listA)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Deepcopy with Objects" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "140554035637216 140554035637104\n", + "140554035637216 140554035637216\n", + "140554035637216 140554035637048\n" + ] + } + ], + "source": [ + "class Pony():\n", + " def __init__(self, n):\n", + " self.name = n\n", + " \n", + "# copy.copy on an object gives you 2 unique objects (with same attributes)\n", + "pony1 = Pony('Pinto')\n", + "pony2 = copy.copy(pony1)\n", + "print(id(pony1), id(pony2))\n", + "\n", + "# copy.copy on a list of objects gives you 2 unique lists containing the exact same objects \n", + "# (ie. new list is a shallow copy)\n", + "m = [pony1, pony2]\n", + "n = copy.copy (m)\n", + "print(id(m[0]), id(n[0]))\n", + "\n", + "# use copy.deepcopy to deep copy a list of objects\n", + "n = copy.deepcopy (m)\n", + "print(id(m[0]), id(n[0]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/dict_comprehensions.py b/dict_comprehensions.py new file mode 100644 index 00000000..890c7221 --- /dev/null +++ b/dict_comprehensions.py @@ -0,0 +1,54 @@ +# Python Dictionary Comprehensions +# (c) Joe James 2023 + +# 1. math function to compute values using list +dict1 = {x: 2*x for x in [0, 2, 4, 6]} +print ('1. ', dict1) + +# 2. math function to compute values using range +dict2 = {x: x**2 for x in range(0, 7, 2)} +print ('2. ', dict2) + +# 3. from chars in a string +dict3 = {x: ord(x) for x in 'Kumar'} +print ('3. ', dict3) + +# 4. given lists of keys & values +x = ['Aditii', 'Brandon', 'Clumley', 'Magomed', 'Rishi'] +y = [1, 2, 3, 13, 18] +dict4 = {i: j for (i,j) in zip(x,y)} +print ('4. ', dict4) + +# 5. from chars in a string +x = "python" +dict5 = {i: 3*i.upper() for i in x} +print('5. ', dict5) + +# 6. list comprehension for the value +x = [2, 4, 6, 8] +y = [5, 10, 15, 20] +dict6 = {i: [i + 2*j for j in y] for i in x} +print('6. ', dict6) + +#7. using items +x = {'A':10, 'B':20, 'C':30} +dict7 = {i: j*2 for (i,j) in x.items()} +print('7. ', dict7) + +# 8. conditional comprehension +dict8 = {i: i**3 for i in range(10) if i%2 == 0} +print('8. ', dict8) + +# 9. if-else conditional comprehension +x = {'A':10, 'B':20, 'C':30} +dict9 = {i: (j if j < 15 else j+100) for (i,j) in x.items()} +print('9. ', dict9) + +# 10. transformation from an existing dict +x = {'A':10, 'B':20, 'C':30} +dict10 = {i: x[i]+1 for i in x} +print('10. ', dict10) + + + + diff --git a/exception-handling.py b/exception-handling.py index 8dd489f1..57ddf118 100644 --- a/exception-handling.py +++ b/exception-handling.py @@ -1,3 +1,20 @@ +# something more about try except +# basic syntax +''' +try: + code1 + +except: + some code that will execute if code 1 fails or raise some error + +else: + this code is executed only if try was succesful i.e no error in code1 + +finally: + + this code will execute in every situation if try fails or not +''' + filename = 'exception_data.txt' # Outer try block catches file name or file doesn't exist errors. try: @@ -28,4 +45,22 @@ def this_fails(): try: this_fails() except ZeroDivisionError as err: - print('Handling run-time error:', err) \ No newline at end of file + print('Handling run-time error:', err) + + +def divide_me(n): + x = 1/n + +i = int(input('enter a number ')) +try: + divide_me(i) + +except Exception as e: + print(e) # this will print the error msg but don't kill the execution of program + +else: + print('Your Code Run Successfully') # this will execute if divide_me(i) run sucessfully without an error + +finally: + print('thanks') # this will execute in every condition + diff --git a/factorial.py b/factorial.py index 2a70c3dc..8e4a65ea 100644 --- a/factorial.py +++ b/factorial.py @@ -14,6 +14,6 @@ def get_iterative_factorial(n): for i in range(1, n+1): fact *= i return fact - +print("input should be an integer") print(get_recursive_factorial(6)) -print(get_iterative_factorial(6)) \ No newline at end of file +print(get_iterative_factorial(6)) diff --git a/flatten_list.py b/flatten_list.py new file mode 100644 index 00000000..3f3c57df --- /dev/null +++ b/flatten_list.py @@ -0,0 +1,27 @@ +# Python Flatten Nested Lists +# (c) Joe James 2023 + +# list comprehension method +def flatten1 (myList): + return [i for j in myList for i in j] + +# recursive method +def flatten2 (myList): + flatList = [] + for item in myList: + if isinstance(item, list): + flatList.extend(flatten2(item)) + else: + flatList.append(item) + return flatList + +list1 = [[0], [1, 2], [3, [4, 5]], [6], [7]] +list2 = [0, [1, 2], [3, [4, 5]], [6], 7] + +print("flatten1(list1): ", flatten1(list1)) # works, but only flattens 1 layer of sublists +# print(flatten1(list2)) # error - can't work with list of ints and sublists of ints + +print("flatten2(list1): ", flatten2(list1)) +print("flatten2(list2): ", flatten2(list2)) + + diff --git a/graph_adjacency-list.py b/graph_adjacency-list.py index fec2f958..ebc3f47c 100644 --- a/graph_adjacency-list.py +++ b/graph_adjacency-list.py @@ -4,9 +4,9 @@ def __init__(self, n): self.name = n self.neighbors = list() - def add_neighbor(self, v): + def add_neighbor(self, v, weight): if v not in self.neighbors: - self.neighbors.append(v) + self.neighbors.append((v, weight)) self.neighbors.sort() class Graph: @@ -19,11 +19,11 @@ def add_vertex(self, vertex): else: return False - def add_edge(self, u, v): + def add_edge(self, u, v, weight=0): if u in self.vertices and v in self.vertices: # my YouTube video shows a silly for loop here, but this is a much faster way to do it - self.vertices[u].add_neighbor(v) - self.vertices[v].add_neighbor(u) + self.vertices[u].add_neighbor(v, weight) + self.vertices[v].add_neighbor(u, weight) return True else: return False diff --git a/graph_adjacency-matrix.py b/graph_adjacency-matrix.py index b6d05589..3f315001 100644 --- a/graph_adjacency-matrix.py +++ b/graph_adjacency-matrix.py @@ -1,4 +1,5 @@ # implementation of an undirected graph using Adjacency Matrix, with weighted or unweighted edges +# its definitely work class Vertex: def __init__(self, n): self.name = n @@ -46,4 +47,4 @@ def print_graph(self): for edge in edges: g.add_edge(edge[:1], edge[1:]) -g.print_graph() \ No newline at end of file +g.print_graph() diff --git a/lcm.py b/lcm.py index 8d584ab7..a308141e 100644 --- a/lcm.py +++ b/lcm.py @@ -1,4 +1,4 @@ -# computes Lowest Common Multiple LCM / Least Common Denominator LCD +# computes Lowest Common Multiple (LCM) / Least Common Denominator (LCD) # useful for adding and subtracting fractions # 2 numbers @@ -21,4 +21,4 @@ def lcm3(nums): print(str(lcm(7, 12))) nums = [3, 2, 16] -print(str(lcm3(nums))) \ No newline at end of file +print(str(lcm3(nums))) diff --git a/match statements.ipynb b/match statements.ipynb new file mode 100644 index 00000000..a8fc422d --- /dev/null +++ b/match statements.ipynb @@ -0,0 +1,327 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python 10 - Structural Pattern Matching\n", + "### match statements \n", + "Very similar to switch/case statements in C, Java, and Javascript. \n", + "Can be used in lieu of if/elif/else blocks. \n", + "[documentation](https://www.python.org/dev/peps/pep-0622/)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Can use integer for match variable..." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "large\n" + ] + } + ], + "source": [ + "var = 3\n", + "\n", + "match var:\n", + " case 1:\n", + " print('small')\n", + " case 2:\n", + " print('medium')\n", + " case 3:\n", + " print('large')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ...or floating point..." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "large\n" + ] + } + ], + "source": [ + "var = 1.5\n", + "\n", + "match var:\n", + " case 1.3:\n", + " print('small')\n", + " case 1.4:\n", + " print('medium')\n", + " case 1.5:\n", + " print('large')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ...or Tuple...\n", + "Note here we also use a variable to receive *any* value." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "on x-axis\n" + ] + } + ], + "source": [ + "var = (8,0)\n", + "\n", + "match var:\n", + " case (0,x):\n", + " print('on y-axis')\n", + " case (x,0):\n", + " print('on x-axis')\n", + " case (x,y):\n", + " print('not on axis')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ...or String" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "small\n" + ] + } + ], + "source": [ + "var = \"S\"\n", + "\n", + "match var:\n", + " case \"S\":\n", + " print('small')\n", + " case \"Med\":\n", + " print('medium')\n", + " case \"Lg\":\n", + " print('large')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### The Default case _ \n", + "The default case, using underscore, is optional. " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "large\n" + ] + } + ], + "source": [ + "var = 4\n", + "\n", + "match var:\n", + " case 1:\n", + " print('small')\n", + " case 2:\n", + " print('medium')\n", + " case _:\n", + " print('large')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Conditionals in case \n", + "*or* conditions (using bar) are supported in case statements." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "small\n" + ] + } + ], + "source": [ + "var = 2\n", + "\n", + "match var:\n", + " case 2 | 3:\n", + " print('small')\n", + " case 4 | 5 | 6:\n", + " print('medium')\n", + " case _:\n", + " print('large')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### No breaks needed\n", + "*if* statements are supported, but must follow syntax, case var if (inequality expression). \n", + "\n", + "Note that you do not need break statements. The match block will automatically end execution after one case is executed." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A\n", + "F\n" + ] + } + ], + "source": [ + "def print_grade(score):\n", + " match score:\n", + " # case score > 90 this does not work!\n", + " case score if score >= 90:\n", + " print('A')\n", + " case score if score >= 80:\n", + " print('B')\n", + " case score if score >= 70:\n", + " print('C')\n", + " case score if score >= 60:\n", + " print('D')\n", + " case _:\n", + " print('F')\n", + " \n", + "print_grade(94)\n", + "print_grade(48)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Python Objects \n", + "Match statements can also use Python objects and instance variables. \n", + "In the final case here we could have used _ default case, but instead used x so that we could use the value of x in our print statement." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "medium\n", + "Size XL is not recognized.\n" + ] + } + ], + "source": [ + "class T_shirt:\n", + " def __init__(self, s):\n", + " self.size = s\n", + "\n", + " def order(self):\n", + " match self.size:\n", + " case 'S' | 'Sm':\n", + " print('small')\n", + " case 'M' | 'Med':\n", + " print('medium')\n", + " case 'L' | 'Lg':\n", + " print('large')\n", + " case x:\n", + " print(f'Size {x} is not recognized.')\n", + " \n", + "shirt1 = T_shirt('Med')\n", + "shirt1.order()\n", + "\n", + "shirt2 = T_shirt('XL')\n", + "shirt2.order()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/python oriented programming b/python oriented programming new file mode 100644 index 00000000..8e3a4499 --- /dev/null +++ b/python oriented programming @@ -0,0 +1,34 @@ +class Mobile: + def make_call(self): + print("i am making a call") + def play_game(self): + print("i am playing games") + +m1=Mobile() + +m1.make_call() + +m1.play_game() + +class Mobile: + def set_color(self,color): + self.color=color + def set_cost(self,cost): + self.cost=cost + def show_color(self): + print("black") + def show_price(self): + print("5000") + def make_call(self): + print("i am making a call") + def play_game(self): + print("i am playing games") + + + +m2=Mobile() + +m2.show_price() + +m2.show_color() + diff --git a/remove_from_list.py b/remove_from_list.py new file mode 100644 index 00000000..9619664f --- /dev/null +++ b/remove_from_list.py @@ -0,0 +1,48 @@ +# Python: del vs pop vs remove from a list +# (c) Joe James 2023 + +def get_dogs(): + return ['Fido', 'Rover', 'Spot', 'Duke', 'Chip', 'Spot'] + +dogs = get_dogs() +print(dogs) + +# Use pop() to remove last item or an item by index and get the returned value. +print('1. pop last item from list:') +myDog = dogs.pop() +print(myDog, dogs) + +dogs = get_dogs() +print('2. pop item with index 1:') +myDog = dogs.pop(1) +print(myDog, dogs) + +# Use remove() to delete an item by value. (raises ValueError if value not found) +dogs = get_dogs() +print('3. remove first Spot from list:') +dogs.remove('Spot') +print(dogs) + +# Use del to remove an item or range of items by index. Or delete entire list. +dogs = get_dogs() +print('4. del item with index 3:') +del(dogs[3]) +print(dogs) + +dogs = get_dogs() +print('5. del items [1:3] from list:') +del(dogs[1:3]) +print(dogs) + +dogs = get_dogs() +print('6. del entire list:') +del(dogs) +print(dogs) + + + + + + + +