From 69824292d3ec71e8edb97eb95b38e4c95046dbde Mon Sep 17 00:00:00 2001 From: Joe James Date: Sun, 3 Feb 2019 19:46:28 -0800 Subject: [PATCH 01/75] uploaded date time Jupyter notebook --- Date Time Timestamp/Date_Time.ipynb | 424 ++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 Date Time Timestamp/Date_Time.ipynb diff --git a/Date Time Timestamp/Date_Time.ipynb b/Date Time Timestamp/Date_Time.ipynb new file mode 100644 index 00000000..795b0b61 --- /dev/null +++ b/Date Time Timestamp/Date_Time.ipynb @@ -0,0 +1,424 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using Times, Dates & Timestamps in Python" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Summary of Time and Date classes:\n", + "**datetime** # superclass for most of the date and time libraries \n", + "    **date** # general purpose date library \n", + "    **time** # general purpose time library \n", + "    **datetime** # for date and time in one object \n", + "    **timedelta** # for a duration or elapsed time \n", + "**time** # for Unix timestamp and process_time \n", + "**calendar** # for calendars \n", + "**dateutil** # extended datetime functionality, esp string parsing and delta calculation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Today's Date\n", + "- Use datetime.date.today()\n", + "- datetime.date class has the following integer attributes, date(year, month, day)\n", + "- get day of the week using date.weekday() # Monday is 0" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2019-02-03\n", + "2 3 2019\n", + "6\n" + ] + } + ], + "source": [ + "from datetime import date\n", + "d1 = date.today()\n", + "print(d1)\n", + "print(d1.month, d1.day, d1.year)\n", + "print(d1.weekday())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ISO format is a string format, yyyy-mm-dd\n", + "- date_object.isoformat() does the same thing as str(date_object)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2011-11-23\n", + "2011-11-23\n", + "2011-11-23\n" + ] + }, + { + "data": { + "text/plain": [ + "datetime.date(2011, 11, 23)" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d1 = date.fromisoformat('2011-11-23')\n", + "print(d1)\n", + "print(str(d1))\n", + "print(d1.isoformat())\n", + "d1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Comparison, addition and sutraction of dates\n", + "- Comparison gives boolean result. Later date is greater than earlier date.\n", + "- Date addition & subtraction give result as a datetime.timedelta object (explained more below).\n", + "- The same comparison and add/subtract operations can be used with time objects." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "1359 days, 0:00:00\n" + ] + } + ], + "source": [ + "d1 = date.today()\n", + "d2 = date(2015, 5, 14)\n", + "print(d1 > d2)\n", + "print(d1 - d2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Time\n", + "- time objects have the following attributes, time(hour, minute, second, microsecond, tzinfo)\n", + "- use datetime.time to compare time objects: t1 < t2 if t1 occurs before t2\n", + " - attributes are all optional, so you can just work with hours and minutes if you want\n", + "- daylight savings is handled by the time.dst() function (if tzinfo is set)" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "14:25:36.018625\n", + "02:19:00\n", + "False\n" + ] + } + ], + "source": [ + "from datetime import time\n", + "t1 = time(14, 25, 36, 18625)\n", + "print(t1)\n", + "\n", + "t2 = time(2, 19)\n", + "print(t2)\n", + "print(t1 < t2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### datetime.datetime combines date and time attributes into a datetime object\n", + "- datetime.datetime(year, month, day, hour, minute, second, microsecond, tzinfo)\n", + "- datetime.datetime objects can be used as dictionary keys\n", + "- includes functions: date(), time()" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1941-12-07 07:53:00\n", + "1941-12-07\n", + "07:53:00\n" + ] + } + ], + "source": [ + "from datetime import datetime\n", + "dt1 = datetime(1941, 12, 7, 7, 53)\n", + "print(dt1)\n", + "print(dt1.date())\n", + "print(dt1.time())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Use datetime.datetime.now() to get the current date and time" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10:02:21.354040\n", + "2019-02-03\n", + "10 2\n", + "2-3-2019\n" + ] + } + ], + "source": [ + "from datetime import datetime\n", + "t3 = datetime.now()\n", + "\n", + "print(t3.time())\n", + "print(t3.date())\n", + "print(t3.hour, t3.minute)\n", + "print(str(t3.month) + '-' + str(t3.day) + '-' + str(t3.year))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Use datetime.strftime() to get names of months and weekdays." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sunday\n", + "Sun, Sunday, Feb, February, 02/03/19\n" + ] + } + ], + "source": [ + "from datetime import datetime\n", + "t3 = datetime.now()\n", + "print(t3.strftime('%A'))\n", + "print(t3.strftime('%a, %A, %b, %B, %x'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A timedelta is used for a duration, or the time difference between two dates or times\n", + "- datetime.timedelta(days, seconds, microseconds)\n", + "- A timedelta can also be multiplied or divided by an integer or float" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "461 days, 0:00:00 \n", + "39830400.0\n", + "1383 days, 0:00:00\n" + ] + } + ], + "source": [ + "from datetime import timedelta, date, time\n", + "d1 = date(2011, 6, 15)\n", + "d2 = date(2012, 9, 18)\n", + "td = d2 - d1\n", + "print(td, type(td))\n", + "print(td.total_seconds())\n", + "print(td * 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1008 days to event.\n", + "1008 days, 0:00:00 days to event.\n" + ] + } + ], + "source": [ + "from datetime import datetime\n", + "today = datetime.today().date()\n", + "my_event = date(2021, 11, 6)\n", + "days_to_event = abs(my_event - today)\n", + "print(days_to_event.days, 'days to event.')\n", + "print(days_to_event, 'days to event.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a UNIX timestamp (time since the epoch)\n", + "- A timestamp is the time since Jan 1, 1970 in seconds\n", + "- Use time.time() to get timestamp\n", + "- Use datetime.fromtimestamp(ts) and datetime.timestamp(datetime_obj) to convert between timestamp and datetime\n", + "- Use time.process_time() to get runtime of an operation on your computer" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1549156155.9644115\n", + "Sat Feb 2 17:09:15 2019\n" + ] + } + ], + "source": [ + "import time\n", + "ts = time.time()\n", + "print(ts)\n", + "print(time.ctime(ts))" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2019-02-02 17:09:15.964411\n", + "1549156155.964411\n" + ] + } + ], + "source": [ + "from datetime import datetime\n", + "now = datetime.fromtimestamp(ts)\n", + "print(now)\n", + "print(datetime.timestamp(now))" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "operation executed in 0.0\n" + ] + } + ], + "source": [ + "start_time = time.process_time()\n", + "# do some stuff\n", + "end_time = time.process_time()\n", + "print('operation executed in ', end_time - start_time)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "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 +} From 5e60679ce8100a5ce558506b1d882e9fb364a1bd Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 4 Feb 2019 10:32:02 -0800 Subject: [PATCH 02/75] Uploaded python/text file for date and time --- Date Time Timestamp/Date_Time_Timestamp.py | 133 +++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 Date Time Timestamp/Date_Time_Timestamp.py diff --git a/Date Time Timestamp/Date_Time_Timestamp.py b/Date Time Timestamp/Date_Time_Timestamp.py new file mode 100644 index 00000000..7897332c --- /dev/null +++ b/Date Time Timestamp/Date_Time_Timestamp.py @@ -0,0 +1,133 @@ +"""############################################################################## +Using Times, Dates & Timestamps in Python + +Summary of Time and Date classes: +datetime # superclass for most of the date and time libraries + date # general purpose date library + time # general purpose time library + datetime # for date and time in one object + timedelta # for a duration or elapsed time +time # for Unix timestamp and process_time +calendar # for calendars +dateutil # extended datetime functionality, esp string parsing and delta calculation +##############################################################################""" + +# Today's Date +# --------------------------- +# Use datetime.date.today() +# datetime.date class has the following integer attributes, date(year, month, day) +# 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()) + +# 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 + +# Comparison, addition and sutraction of dates +# --------------------------- +# Comparison gives boolean result. Later date is greater than earlier date. +# Date addition & subtraction give result as a datetime.timedelta object (explained more below). +# The same comparison and add/subtract operations can be used with time objects. + +from datetime import date +d1 = date.today() +d2 = date(2015, 5, 14) +print(d1 > d2) +print(d1 - d2) + +# Time +# --------------------------- +# time objects have the following attributes, time(hour, minute, second, microsecond, tzinfo) +# use datetime.time to compare time objects: t1 < t2 if t1 occurs before t2 +# attributes are all optional, so you can just work with hours and minutes if you want +# daylight savings is handled by the time.dst() function (if tzinfo is set) + +from datetime import time +t1 = time(14, 25, 36, 18625) +print(t1) + +t2 = time(2, 19) +print(t2) +print(t1 < t2) + +# datetime.datetime combines date and time attributes into a datetime object +# --------------------------- +# datetime.datetime(year, month, day, hour, minute, second, microsecond, tzinfo) +# datetime.datetime objects can be used as dictionary keys +# includes functions: date(), time() + +from datetime import datetime +dt1 = datetime(1941, 12, 7, 7, 53) +print(dt1) +print(dt1.date()) +print(dt1.time()) + +# Use datetime.datetime.now() to get the current date and time + +t3 = datetime.now() + +print(t3.time()) +print(t3.date()) +print(t3.hour, t3.minute) +print(str(t3.month) + '-' + str(t3.day) + '-' + str(t3.year)) + +# Use datetime.strftime() to get names of months and weekdays. + +t3 = datetime.now() +print(t3.strftime('%A')) +print(t3.strftime('%a, %A, %b, %B, %x')) + +# A timedelta is used for a duration, or the time difference between two dates or times +# --------------------------- +# datetime.timedelta(days, seconds, microseconds) +# A timedelta can also be multiplied or divided by an integer or float + +from datetime import timedelta, date, time +d1 = date(2011, 6, 15) +d2 = date(2012, 9, 18) +td = d2 - d1 +print(td, type(td)) +print(td.total_seconds()) +print(td * 3) + +from datetime import datetime +today = datetime.today().date() +my_event = date(2021, 11, 6) +days_to_event = abs(my_event - today) +print(days_to_event.days, 'days to event.') +print(days_to_event, 'days to event.') + +# Get a UNIX timestamp (time since the epoch) +# --------------------------- +# A timestamp is the time since Jan 1, 1970 in seconds +# Use time.time() to get timestamp +# Use datetime.fromtimestamp(ts) and datetime.timestamp(datetime_obj) to convert between timestamp and datetime +# Use time.process_time() to get runtime of an operation on your computer + +import time +ts = time.time() +print(ts) +print(time.ctime(ts)) + + +from datetime import datetime +now = datetime.fromtimestamp(ts) +print(now) +print(datetime.timestamp(now)) + +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 From 88de190aa42410f0e1733b3d83ad51587c8243f8 Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 6 Feb 2019 19:05:03 -0800 Subject: [PATCH 03/75] Uploaded Graduate Admissions notebook and data --- Pandas/Admission_Predict_Ver1.1.csv | 501 ++++++++++++++ ...tlib Tackle Graduate Admissions Data.ipynb | 620 ++++++++++++++++++ 2 files changed, 1121 insertions(+) create mode 100644 Pandas/Admission_Predict_Ver1.1.csv create mode 100644 Pandas/Pandas and Matplotlib Tackle Graduate Admissions Data.ipynb diff --git a/Pandas/Admission_Predict_Ver1.1.csv b/Pandas/Admission_Predict_Ver1.1.csv new file mode 100644 index 00000000..ff4d3f2a --- /dev/null +++ b/Pandas/Admission_Predict_Ver1.1.csv @@ -0,0 +1,501 @@ +Serial No.,GRE Score,TOEFL Score,University Rating,SOP,LOR,CGPA,Research,Chance of Admit +1,337,118,4,4.5,4.5,9.65,1,0.92 +2,324,107,4,4,4.5,8.87,1,0.76 +3,316,104,3,3,3.5,8,1,0.72 +4,322,110,3,3.5,2.5,8.67,1,0.8 +5,314,103,2,2,3,8.21,0,0.65 +6,330,115,5,4.5,3,9.34,1,0.9 +7,321,109,3,3,4,8.2,1,0.75 +8,308,101,2,3,4,7.9,0,0.68 +9,302,102,1,2,1.5,8,0,0.5 +10,323,108,3,3.5,3,8.6,0,0.45 +11,325,106,3,3.5,4,8.4,1,0.52 +12,327,111,4,4,4.5,9,1,0.84 +13,328,112,4,4,4.5,9.1,1,0.78 +14,307,109,3,4,3,8,1,0.62 +15,311,104,3,3.5,2,8.2,1,0.61 +16,314,105,3,3.5,2.5,8.3,0,0.54 +17,317,107,3,4,3,8.7,0,0.66 +18,319,106,3,4,3,8,1,0.65 +19,318,110,3,4,3,8.8,0,0.63 +20,303,102,3,3.5,3,8.5,0,0.62 +21,312,107,3,3,2,7.9,1,0.64 +22,325,114,4,3,2,8.4,0,0.7 +23,328,116,5,5,5,9.5,1,0.94 +24,334,119,5,5,4.5,9.7,1,0.95 +25,336,119,5,4,3.5,9.8,1,0.97 +26,340,120,5,4.5,4.5,9.6,1,0.94 +27,322,109,5,4.5,3.5,8.8,0,0.76 +28,298,98,2,1.5,2.5,7.5,1,0.44 +29,295,93,1,2,2,7.2,0,0.46 +30,310,99,2,1.5,2,7.3,0,0.54 +31,300,97,2,3,3,8.1,1,0.65 +32,327,103,3,4,4,8.3,1,0.74 +33,338,118,4,3,4.5,9.4,1,0.91 +34,340,114,5,4,4,9.6,1,0.9 +35,331,112,5,4,5,9.8,1,0.94 +36,320,110,5,5,5,9.2,1,0.88 +37,299,106,2,4,4,8.4,0,0.64 +38,300,105,1,1,2,7.8,0,0.58 +39,304,105,1,3,1.5,7.5,0,0.52 +40,307,108,2,4,3.5,7.7,0,0.48 +41,308,110,3,3.5,3,8,1,0.46 +42,316,105,2,2.5,2.5,8.2,1,0.49 +43,313,107,2,2.5,2,8.5,1,0.53 +44,332,117,4,4.5,4,9.1,0,0.87 +45,326,113,5,4.5,4,9.4,1,0.91 +46,322,110,5,5,4,9.1,1,0.88 +47,329,114,5,4,5,9.3,1,0.86 +48,339,119,5,4.5,4,9.7,0,0.89 +49,321,110,3,3.5,5,8.85,1,0.82 +50,327,111,4,3,4,8.4,1,0.78 +51,313,98,3,2.5,4.5,8.3,1,0.76 +52,312,100,2,1.5,3.5,7.9,1,0.56 +53,334,116,4,4,3,8,1,0.78 +54,324,112,4,4,2.5,8.1,1,0.72 +55,322,110,3,3,3.5,8,0,0.7 +56,320,103,3,3,3,7.7,0,0.64 +57,316,102,3,2,3,7.4,0,0.64 +58,298,99,2,4,2,7.6,0,0.46 +59,300,99,1,3,2,6.8,1,0.36 +60,311,104,2,2,2,8.3,0,0.42 +61,309,100,2,3,3,8.1,0,0.48 +62,307,101,3,4,3,8.2,0,0.47 +63,304,105,2,3,3,8.2,1,0.54 +64,315,107,2,4,3,8.5,1,0.56 +65,325,111,3,3,3.5,8.7,0,0.52 +66,325,112,4,3.5,3.5,8.92,0,0.55 +67,327,114,3,3,3,9.02,0,0.61 +68,316,107,2,3.5,3.5,8.64,1,0.57 +69,318,109,3,3.5,4,9.22,1,0.68 +70,328,115,4,4.5,4,9.16,1,0.78 +71,332,118,5,5,5,9.64,1,0.94 +72,336,112,5,5,5,9.76,1,0.96 +73,321,111,5,5,5,9.45,1,0.93 +74,314,108,4,4.5,4,9.04,1,0.84 +75,314,106,3,3,5,8.9,0,0.74 +76,329,114,2,2,4,8.56,1,0.72 +77,327,112,3,3,3,8.72,1,0.74 +78,301,99,2,3,2,8.22,0,0.64 +79,296,95,2,3,2,7.54,1,0.44 +80,294,93,1,1.5,2,7.36,0,0.46 +81,312,105,3,2,3,8.02,1,0.5 +82,340,120,4,5,5,9.5,1,0.96 +83,320,110,5,5,4.5,9.22,1,0.92 +84,322,115,5,4,4.5,9.36,1,0.92 +85,340,115,5,4.5,4.5,9.45,1,0.94 +86,319,103,4,4.5,3.5,8.66,0,0.76 +87,315,106,3,4.5,3.5,8.42,0,0.72 +88,317,107,2,3.5,3,8.28,0,0.66 +89,314,108,3,4.5,3.5,8.14,0,0.64 +90,316,109,4,4.5,3.5,8.76,1,0.74 +91,318,106,2,4,4,7.92,1,0.64 +92,299,97,3,5,3.5,7.66,0,0.38 +93,298,98,2,4,3,8.03,0,0.34 +94,301,97,2,3,3,7.88,1,0.44 +95,303,99,3,2,2.5,7.66,0,0.36 +96,304,100,4,1.5,2.5,7.84,0,0.42 +97,306,100,2,3,3,8,0,0.48 +98,331,120,3,4,4,8.96,1,0.86 +99,332,119,4,5,4.5,9.24,1,0.9 +100,323,113,3,4,4,8.88,1,0.79 +101,322,107,3,3.5,3.5,8.46,1,0.71 +102,312,105,2,2.5,3,8.12,0,0.64 +103,314,106,2,4,3.5,8.25,0,0.62 +104,317,104,2,4.5,4,8.47,0,0.57 +105,326,112,3,3.5,3,9.05,1,0.74 +106,316,110,3,4,4.5,8.78,1,0.69 +107,329,111,4,4.5,4.5,9.18,1,0.87 +108,338,117,4,3.5,4.5,9.46,1,0.91 +109,331,116,5,5,5,9.38,1,0.93 +110,304,103,5,5,4,8.64,0,0.68 +111,305,108,5,3,3,8.48,0,0.61 +112,321,109,4,4,4,8.68,1,0.69 +113,301,107,3,3.5,3.5,8.34,1,0.62 +114,320,110,2,4,3.5,8.56,0,0.72 +115,311,105,3,3.5,3,8.45,1,0.59 +116,310,106,4,4.5,4.5,9.04,1,0.66 +117,299,102,3,4,3.5,8.62,0,0.56 +118,290,104,4,2,2.5,7.46,0,0.45 +119,296,99,2,3,3.5,7.28,0,0.47 +120,327,104,5,3,3.5,8.84,1,0.71 +121,335,117,5,5,5,9.56,1,0.94 +122,334,119,5,4.5,4.5,9.48,1,0.94 +123,310,106,4,1.5,2.5,8.36,0,0.57 +124,308,108,3,3.5,3.5,8.22,0,0.61 +125,301,106,4,2.5,3,8.47,0,0.57 +126,300,100,3,2,3,8.66,1,0.64 +127,323,113,3,4,3,9.32,1,0.85 +128,319,112,3,2.5,2,8.71,1,0.78 +129,326,112,3,3.5,3,9.1,1,0.84 +130,333,118,5,5,5,9.35,1,0.92 +131,339,114,5,4,4.5,9.76,1,0.96 +132,303,105,5,5,4.5,8.65,0,0.77 +133,309,105,5,3.5,3.5,8.56,0,0.71 +134,323,112,5,4,4.5,8.78,0,0.79 +135,333,113,5,4,4,9.28,1,0.89 +136,314,109,4,3.5,4,8.77,1,0.82 +137,312,103,3,5,4,8.45,0,0.76 +138,316,100,2,1.5,3,8.16,1,0.71 +139,326,116,2,4.5,3,9.08,1,0.8 +140,318,109,1,3.5,3.5,9.12,0,0.78 +141,329,110,2,4,3,9.15,1,0.84 +142,332,118,2,4.5,3.5,9.36,1,0.9 +143,331,115,5,4,3.5,9.44,1,0.92 +144,340,120,4,4.5,4,9.92,1,0.97 +145,325,112,2,3,3.5,8.96,1,0.8 +146,320,113,2,2,2.5,8.64,1,0.81 +147,315,105,3,2,2.5,8.48,0,0.75 +148,326,114,3,3,3,9.11,1,0.83 +149,339,116,4,4,3.5,9.8,1,0.96 +150,311,106,2,3.5,3,8.26,1,0.79 +151,334,114,4,4,4,9.43,1,0.93 +152,332,116,5,5,5,9.28,1,0.94 +153,321,112,5,5,5,9.06,1,0.86 +154,324,105,3,3,4,8.75,0,0.79 +155,326,108,3,3,3.5,8.89,0,0.8 +156,312,109,3,3,3,8.69,0,0.77 +157,315,105,3,2,2.5,8.34,0,0.7 +158,309,104,2,2,2.5,8.26,0,0.65 +159,306,106,2,2,2.5,8.14,0,0.61 +160,297,100,1,1.5,2,7.9,0,0.52 +161,315,103,1,1.5,2,7.86,0,0.57 +162,298,99,1,1.5,3,7.46,0,0.53 +163,318,109,3,3,3,8.5,0,0.67 +164,317,105,3,3.5,3,8.56,0,0.68 +165,329,111,4,4.5,4,9.01,1,0.81 +166,322,110,5,4.5,4,8.97,0,0.78 +167,302,102,3,3.5,5,8.33,0,0.65 +168,313,102,3,2,3,8.27,0,0.64 +169,293,97,2,2,4,7.8,1,0.64 +170,311,99,2,2.5,3,7.98,0,0.65 +171,312,101,2,2.5,3.5,8.04,1,0.68 +172,334,117,5,4,4.5,9.07,1,0.89 +173,322,110,4,4,5,9.13,1,0.86 +174,323,113,4,4,4.5,9.23,1,0.89 +175,321,111,4,4,4,8.97,1,0.87 +176,320,111,4,4.5,3.5,8.87,1,0.85 +177,329,119,4,4.5,4.5,9.16,1,0.9 +178,319,110,3,3.5,3.5,9.04,0,0.82 +179,309,108,3,2.5,3,8.12,0,0.72 +180,307,102,3,3,3,8.27,0,0.73 +181,300,104,3,3.5,3,8.16,0,0.71 +182,305,107,2,2.5,2.5,8.42,0,0.71 +183,299,100,2,3,3.5,7.88,0,0.68 +184,314,110,3,4,4,8.8,0,0.75 +185,316,106,2,2.5,4,8.32,0,0.72 +186,327,113,4,4.5,4.5,9.11,1,0.89 +187,317,107,3,3.5,3,8.68,1,0.84 +188,335,118,5,4.5,3.5,9.44,1,0.93 +189,331,115,5,4.5,3.5,9.36,1,0.93 +190,324,112,5,5,5,9.08,1,0.88 +191,324,111,5,4.5,4,9.16,1,0.9 +192,323,110,5,4,5,8.98,1,0.87 +193,322,114,5,4.5,4,8.94,1,0.86 +194,336,118,5,4.5,5,9.53,1,0.94 +195,316,109,3,3.5,3,8.76,0,0.77 +196,307,107,2,3,3.5,8.52,1,0.78 +197,306,105,2,3,2.5,8.26,0,0.73 +198,310,106,2,3.5,2.5,8.33,0,0.73 +199,311,104,3,4.5,4.5,8.43,0,0.7 +200,313,107,3,4,4.5,8.69,0,0.72 +201,317,103,3,2.5,3,8.54,1,0.73 +202,315,110,2,3.5,3,8.46,1,0.72 +203,340,120,5,4.5,4.5,9.91,1,0.97 +204,334,120,5,4,5,9.87,1,0.97 +205,298,105,3,3.5,4,8.54,0,0.69 +206,295,99,2,2.5,3,7.65,0,0.57 +207,315,99,2,3.5,3,7.89,0,0.63 +208,310,102,3,3.5,4,8.02,1,0.66 +209,305,106,2,3,3,8.16,0,0.64 +210,301,104,3,3.5,4,8.12,1,0.68 +211,325,108,4,4.5,4,9.06,1,0.79 +212,328,110,4,5,4,9.14,1,0.82 +213,338,120,4,5,5,9.66,1,0.95 +214,333,119,5,5,4.5,9.78,1,0.96 +215,331,117,4,4.5,5,9.42,1,0.94 +216,330,116,5,5,4.5,9.36,1,0.93 +217,322,112,4,4.5,4.5,9.26,1,0.91 +218,321,109,4,4,4,9.13,1,0.85 +219,324,110,4,3,3.5,8.97,1,0.84 +220,312,104,3,3.5,3.5,8.42,0,0.74 +221,313,103,3,4,4,8.75,0,0.76 +222,316,110,3,3.5,4,8.56,0,0.75 +223,324,113,4,4.5,4,8.79,0,0.76 +224,308,109,2,3,4,8.45,0,0.71 +225,305,105,2,3,2,8.23,0,0.67 +226,296,99,2,2.5,2.5,8.03,0,0.61 +227,306,110,2,3.5,4,8.45,0,0.63 +228,312,110,2,3.5,3,8.53,0,0.64 +229,318,112,3,4,3.5,8.67,0,0.71 +230,324,111,4,3,3,9.01,1,0.82 +231,313,104,3,4,4.5,8.65,0,0.73 +232,319,106,3,3.5,2.5,8.33,1,0.74 +233,312,107,2,2.5,3.5,8.27,0,0.69 +234,304,100,2,2.5,3.5,8.07,0,0.64 +235,330,113,5,5,4,9.31,1,0.91 +236,326,111,5,4.5,4,9.23,1,0.88 +237,325,112,4,4,4.5,9.17,1,0.85 +238,329,114,5,4.5,5,9.19,1,0.86 +239,310,104,3,2,3.5,8.37,0,0.7 +240,299,100,1,1.5,2,7.89,0,0.59 +241,296,101,1,2.5,3,7.68,0,0.6 +242,317,103,2,2.5,2,8.15,0,0.65 +243,324,115,3,3.5,3,8.76,1,0.7 +244,325,114,3,3.5,3,9.04,1,0.76 +245,314,107,2,2.5,4,8.56,0,0.63 +246,328,110,4,4,2.5,9.02,1,0.81 +247,316,105,3,3,3.5,8.73,0,0.72 +248,311,104,2,2.5,3.5,8.48,0,0.71 +249,324,110,3,3.5,4,8.87,1,0.8 +250,321,111,3,3.5,4,8.83,1,0.77 +251,320,104,3,3,2.5,8.57,1,0.74 +252,316,99,2,2.5,3,9,0,0.7 +253,318,100,2,2.5,3.5,8.54,1,0.71 +254,335,115,4,4.5,4.5,9.68,1,0.93 +255,321,114,4,4,5,9.12,0,0.85 +256,307,110,4,4,4.5,8.37,0,0.79 +257,309,99,3,4,4,8.56,0,0.76 +258,324,100,3,4,5,8.64,1,0.78 +259,326,102,4,5,5,8.76,1,0.77 +260,331,119,4,5,4.5,9.34,1,0.9 +261,327,108,5,5,3.5,9.13,1,0.87 +262,312,104,3,3.5,4,8.09,0,0.71 +263,308,103,2,2.5,4,8.36,1,0.7 +264,324,111,3,2.5,1.5,8.79,1,0.7 +265,325,110,2,3,2.5,8.76,1,0.75 +266,313,102,3,2.5,2.5,8.68,0,0.71 +267,312,105,2,2,2.5,8.45,0,0.72 +268,314,107,3,3,3.5,8.17,1,0.73 +269,327,113,4,4.5,5,9.14,0,0.83 +270,308,108,4,4.5,5,8.34,0,0.77 +271,306,105,2,2.5,3,8.22,1,0.72 +272,299,96,2,1.5,2,7.86,0,0.54 +273,294,95,1,1.5,1.5,7.64,0,0.49 +274,312,99,1,1,1.5,8.01,1,0.52 +275,315,100,1,2,2.5,7.95,0,0.58 +276,322,110,3,3.5,3,8.96,1,0.78 +277,329,113,5,5,4.5,9.45,1,0.89 +278,320,101,2,2.5,3,8.62,0,0.7 +279,308,103,2,3,3.5,8.49,0,0.66 +280,304,102,2,3,4,8.73,0,0.67 +281,311,102,3,4.5,4,8.64,1,0.68 +282,317,110,3,4,4.5,9.11,1,0.8 +283,312,106,3,4,3.5,8.79,1,0.81 +284,321,111,3,2.5,3,8.9,1,0.8 +285,340,112,4,5,4.5,9.66,1,0.94 +286,331,116,5,4,4,9.26,1,0.93 +287,336,118,5,4.5,4,9.19,1,0.92 +288,324,114,5,5,4.5,9.08,1,0.89 +289,314,104,4,5,5,9.02,0,0.82 +290,313,109,3,4,3.5,9,0,0.79 +291,307,105,2,2.5,3,7.65,0,0.58 +292,300,102,2,1.5,2,7.87,0,0.56 +293,302,99,2,1,2,7.97,0,0.56 +294,312,98,1,3.5,3,8.18,1,0.64 +295,316,101,2,2.5,2,8.32,1,0.61 +296,317,100,2,3,2.5,8.57,0,0.68 +297,310,107,3,3.5,3.5,8.67,0,0.76 +298,320,120,3,4,4.5,9.11,0,0.86 +299,330,114,3,4.5,4.5,9.24,1,0.9 +300,305,112,3,3,3.5,8.65,0,0.71 +301,309,106,2,2.5,2.5,8,0,0.62 +302,319,108,2,2.5,3,8.76,0,0.66 +303,322,105,2,3,3,8.45,1,0.65 +304,323,107,3,3.5,3.5,8.55,1,0.73 +305,313,106,2,2.5,2,8.43,0,0.62 +306,321,109,3,3.5,3.5,8.8,1,0.74 +307,323,110,3,4,3.5,9.1,1,0.79 +308,325,112,4,4,4,9,1,0.8 +309,312,108,3,3.5,3,8.53,0,0.69 +310,308,110,4,3.5,3,8.6,0,0.7 +311,320,104,3,3,3.5,8.74,1,0.76 +312,328,108,4,4.5,4,9.18,1,0.84 +313,311,107,4,4.5,4.5,9,1,0.78 +314,301,100,3,3.5,3,8.04,0,0.67 +315,305,105,2,3,4,8.13,0,0.66 +316,308,104,2,2.5,3,8.07,0,0.65 +317,298,101,2,1.5,2,7.86,0,0.54 +318,300,99,1,1,2.5,8.01,0,0.58 +319,324,111,3,2.5,2,8.8,1,0.79 +320,327,113,4,3.5,3,8.69,1,0.8 +321,317,106,3,4,3.5,8.5,1,0.75 +322,323,104,3,4,4,8.44,1,0.73 +323,314,107,2,2.5,4,8.27,0,0.72 +324,305,102,2,2,2.5,8.18,0,0.62 +325,315,104,3,3,2.5,8.33,0,0.67 +326,326,116,3,3.5,4,9.14,1,0.81 +327,299,100,3,2,2,8.02,0,0.63 +328,295,101,2,2.5,2,7.86,0,0.69 +329,324,112,4,4,3.5,8.77,1,0.8 +330,297,96,2,2.5,1.5,7.89,0,0.43 +331,327,113,3,3.5,3,8.66,1,0.8 +332,311,105,2,3,2,8.12,1,0.73 +333,308,106,3,3.5,2.5,8.21,1,0.75 +334,319,108,3,3,3.5,8.54,1,0.71 +335,312,107,4,4.5,4,8.65,1,0.73 +336,325,111,4,4,4.5,9.11,1,0.83 +337,319,110,3,3,2.5,8.79,0,0.72 +338,332,118,5,5,5,9.47,1,0.94 +339,323,108,5,4,4,8.74,1,0.81 +340,324,107,5,3.5,4,8.66,1,0.81 +341,312,107,3,3,3,8.46,1,0.75 +342,326,110,3,3.5,3.5,8.76,1,0.79 +343,308,106,3,3,3,8.24,0,0.58 +344,305,103,2,2.5,3.5,8.13,0,0.59 +345,295,96,2,1.5,2,7.34,0,0.47 +346,316,98,1,1.5,2,7.43,0,0.49 +347,304,97,2,1.5,2,7.64,0,0.47 +348,299,94,1,1,1,7.34,0,0.42 +349,302,99,1,2,2,7.25,0,0.57 +350,313,101,3,2.5,3,8.04,0,0.62 +351,318,107,3,3,3.5,8.27,1,0.74 +352,325,110,4,3.5,4,8.67,1,0.73 +353,303,100,2,3,3.5,8.06,1,0.64 +354,300,102,3,3.5,2.5,8.17,0,0.63 +355,297,98,2,2.5,3,7.67,0,0.59 +356,317,106,2,2,3.5,8.12,0,0.73 +357,327,109,3,3.5,4,8.77,1,0.79 +358,301,104,2,3.5,3.5,7.89,1,0.68 +359,314,105,2,2.5,2,7.64,0,0.7 +360,321,107,2,2,1.5,8.44,0,0.81 +361,322,110,3,4,5,8.64,1,0.85 +362,334,116,4,4,3.5,9.54,1,0.93 +363,338,115,5,4.5,5,9.23,1,0.91 +364,306,103,2,2.5,3,8.36,0,0.69 +365,313,102,3,3.5,4,8.9,1,0.77 +366,330,114,4,4.5,3,9.17,1,0.86 +367,320,104,3,3.5,4.5,8.34,1,0.74 +368,311,98,1,1,2.5,7.46,0,0.57 +369,298,92,1,2,2,7.88,0,0.51 +370,301,98,1,2,3,8.03,1,0.67 +371,310,103,2,2.5,2.5,8.24,0,0.72 +372,324,110,3,3.5,3,9.22,1,0.89 +373,336,119,4,4.5,4,9.62,1,0.95 +374,321,109,3,3,3,8.54,1,0.79 +375,315,105,2,2,2.5,7.65,0,0.39 +376,304,101,2,2,2.5,7.66,0,0.38 +377,297,96,2,2.5,2,7.43,0,0.34 +378,290,100,1,1.5,2,7.56,0,0.47 +379,303,98,1,2,2.5,7.65,0,0.56 +380,311,99,1,2.5,3,8.43,1,0.71 +381,322,104,3,3.5,4,8.84,1,0.78 +382,319,105,3,3,3.5,8.67,1,0.73 +383,324,110,4,4.5,4,9.15,1,0.82 +384,300,100,3,3,3.5,8.26,0,0.62 +385,340,113,4,5,5,9.74,1,0.96 +386,335,117,5,5,5,9.82,1,0.96 +387,302,101,2,2.5,3.5,7.96,0,0.46 +388,307,105,2,2,3.5,8.1,0,0.53 +389,296,97,2,1.5,2,7.8,0,0.49 +390,320,108,3,3.5,4,8.44,1,0.76 +391,314,102,2,2,2.5,8.24,0,0.64 +392,318,106,3,2,3,8.65,0,0.71 +393,326,112,4,4,3.5,9.12,1,0.84 +394,317,104,2,3,3,8.76,0,0.77 +395,329,111,4,4.5,4,9.23,1,0.89 +396,324,110,3,3.5,3.5,9.04,1,0.82 +397,325,107,3,3,3.5,9.11,1,0.84 +398,330,116,4,5,4.5,9.45,1,0.91 +399,312,103,3,3.5,4,8.78,0,0.67 +400,333,117,4,5,4,9.66,1,0.95 +401,304,100,2,3.5,3,8.22,0,0.63 +402,315,105,2,3,3,8.34,0,0.66 +403,324,109,3,3.5,3,8.94,1,0.78 +404,330,116,4,4,3.5,9.23,1,0.91 +405,311,101,3,2,2.5,7.64,1,0.62 +406,302,99,3,2.5,3,7.45,0,0.52 +407,322,103,4,3,2.5,8.02,1,0.61 +408,298,100,3,2.5,4,7.95,1,0.58 +409,297,101,3,2,4,7.67,1,0.57 +410,300,98,1,2,2.5,8.02,0,0.61 +411,301,96,1,3,4,7.56,0,0.54 +412,313,94,2,2.5,1.5,8.13,0,0.56 +413,314,102,4,2.5,2,7.88,1,0.59 +414,317,101,3,3,2,7.94,1,0.49 +415,321,110,4,3.5,4,8.35,1,0.72 +416,327,106,4,4,4.5,8.75,1,0.76 +417,315,104,3,4,2.5,8.1,0,0.65 +418,316,103,3,3.5,2,7.68,0,0.52 +419,309,111,2,2.5,4,8.03,0,0.6 +420,308,102,2,2,3.5,7.98,1,0.58 +421,299,100,3,2,3,7.42,0,0.42 +422,321,112,3,3,4.5,8.95,1,0.77 +423,322,112,4,3.5,2.5,9.02,1,0.73 +424,334,119,5,4.5,5,9.54,1,0.94 +425,325,114,5,4,5,9.46,1,0.91 +426,323,111,5,4,5,9.86,1,0.92 +427,312,106,3,3,5,8.57,0,0.71 +428,310,101,3,3.5,5,8.65,1,0.71 +429,316,103,2,2,4.5,8.74,0,0.69 +430,340,115,5,5,4.5,9.06,1,0.95 +431,311,104,3,4,3.5,8.13,1,0.74 +432,320,112,2,3.5,3.5,8.78,1,0.73 +433,324,112,4,4.5,4,9.22,1,0.86 +434,316,111,4,4,5,8.54,0,0.71 +435,306,103,3,3.5,3,8.21,0,0.64 +436,309,105,2,2.5,4,7.68,0,0.55 +437,310,110,1,1.5,4,7.23,1,0.58 +438,317,106,1,1.5,3.5,7.65,1,0.61 +439,318,110,1,2.5,3.5,8.54,1,0.67 +440,312,105,2,1.5,3,8.46,0,0.66 +441,305,104,2,2.5,1.5,7.79,0,0.53 +442,332,112,1,1.5,3,8.66,1,0.79 +443,331,116,4,4.5,4.5,9.44,1,0.92 +444,321,114,5,4.5,4.5,9.16,1,0.87 +445,324,113,5,4,5,9.25,1,0.92 +446,328,116,5,4.5,5,9.08,1,0.91 +447,327,118,4,5,5,9.67,1,0.93 +448,320,108,3,3.5,5,8.97,1,0.84 +449,312,109,2,2.5,4,9.02,0,0.8 +450,315,101,3,3.5,4.5,9.13,0,0.79 +451,320,112,4,3,4.5,8.86,1,0.82 +452,324,113,4,4.5,4.5,9.25,1,0.89 +453,328,116,4,5,3.5,9.6,1,0.93 +454,319,103,3,2.5,4,8.76,1,0.73 +455,310,105,2,3,3.5,8.01,0,0.71 +456,305,102,2,1.5,2.5,7.64,0,0.59 +457,299,100,2,2,2,7.88,0,0.51 +458,295,99,1,2,1.5,7.57,0,0.37 +459,312,100,1,3,3,8.53,1,0.69 +460,329,113,4,4,3.5,9.36,1,0.89 +461,319,105,4,4,4.5,8.66,1,0.77 +462,301,102,3,2.5,2,8.13,1,0.68 +463,307,105,4,3,3,7.94,0,0.62 +464,304,107,3,3.5,3,7.86,0,0.57 +465,298,97,2,2,3,7.21,0,0.45 +466,305,96,4,3,4.5,8.26,0,0.54 +467,314,99,4,3.5,4.5,8.73,1,0.71 +468,318,101,5,3.5,5,8.78,1,0.78 +469,323,110,4,4,5,8.88,1,0.81 +470,326,114,4,4,3.5,9.16,1,0.86 +471,320,110,5,4,4,9.27,1,0.87 +472,311,103,3,2,4,8.09,0,0.64 +473,327,116,4,4,4.5,9.48,1,0.9 +474,316,102,2,4,3.5,8.15,0,0.67 +475,308,105,4,3,2.5,7.95,1,0.67 +476,300,101,3,3.5,2.5,7.88,0,0.59 +477,304,104,3,2.5,2,8.12,0,0.62 +478,309,105,4,3.5,2,8.18,0,0.65 +479,318,103,3,4,4.5,8.49,1,0.71 +480,325,110,4,4.5,4,8.96,1,0.79 +481,321,102,3,3.5,4,9.01,1,0.8 +482,323,107,4,3,2.5,8.48,1,0.78 +483,328,113,4,4,2.5,8.77,1,0.83 +484,304,103,5,5,3,7.92,0,0.71 +485,317,106,3,3.5,3,7.89,1,0.73 +486,311,101,2,2.5,3.5,8.34,1,0.7 +487,319,102,3,2.5,2.5,8.37,0,0.68 +488,327,115,4,3.5,4,9.14,0,0.79 +489,322,112,3,3,4,8.62,1,0.76 +490,302,110,3,4,4.5,8.5,0,0.65 +491,307,105,2,2.5,4.5,8.12,1,0.67 +492,297,99,4,3,3.5,7.81,0,0.54 +493,298,101,4,2.5,4.5,7.69,1,0.53 +494,300,95,2,3,1.5,8.22,1,0.62 +495,301,99,3,2.5,2,8.45,1,0.68 +496,332,108,5,4.5,4,9.02,1,0.87 +497,337,117,5,5,5,9.87,1,0.96 +498,330,120,5,4.5,5,9.56,1,0.93 +499,312,103,4,4,5,8.43,0,0.73 +500,327,113,4,4.5,4.5,9.04,0,0.84 \ No newline at end of file diff --git a/Pandas/Pandas and Matplotlib Tackle Graduate Admissions Data.ipynb b/Pandas/Pandas and Matplotlib Tackle Graduate Admissions Data.ipynb new file mode 100644 index 00000000..414ccaf5 --- /dev/null +++ b/Pandas/Pandas and Matplotlib Tackle Graduate Admissions Data.ipynb @@ -0,0 +1,620 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pandas and Matplotlib Tackle Graduate Admissions Data\n", + "Source: Kaggle, https://www.kaggle.com/mohansacharya/graduate-admissions/ \n", + " Mohan S Acharya, Asfia Armaan, Aneeta S Antony : A Comparison of Regression Models for Prediction of Graduate Admissions, IEEE International Conference on Computational Intelligence in Data Science 2019 \n", + " \n", + "### 1. Load in Data\n", + "Import numpy, pandas and matplotlib libraries, and load data into a Pandas dataframe. \n", + "Print data shape and summary info of data." + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(500, 9)\n", + "\n", + "RangeIndex: 500 entries, 0 to 499\n", + "Data columns (total 9 columns):\n", + "Serial No. 500 non-null int64\n", + "GRE Score 500 non-null int64\n", + "TOEFL Score 500 non-null int64\n", + "University Rating 500 non-null int64\n", + "SOP 500 non-null float64\n", + "LOR 500 non-null float64\n", + "CGPA 500 non-null float64\n", + "Research 500 non-null int64\n", + "Chance of Admit 500 non-null float64\n", + "dtypes: float64(4), int64(5)\n", + "memory usage: 35.2 KB\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "df = pd.read_csv('Admission_Predict_Ver1.1.csv')\n", + "print(df.shape)\n", + "df.info()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. Clean up Columns\n", + "Delete the first column (serial num) since Pandas already assigns an id to each row. \n", + "Rename the columns to simpler names. Print first 5 rows." + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "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", + "
gretoeflratingsoplorgparesearchchance
033711844.54.59.6510.92
132410744.04.58.8710.76
231610433.03.58.0010.72
332211033.52.58.6710.80
431410322.03.08.2100.65
\n", + "
" + ], + "text/plain": [ + " gre toefl rating sop lor gpa research chance\n", + "0 337 118 4 4.5 4.5 9.65 1 0.92\n", + "1 324 107 4 4.0 4.5 8.87 1 0.76\n", + "2 316 104 3 3.0 3.5 8.00 1 0.72\n", + "3 322 110 3 3.5 2.5 8.67 1 0.80\n", + "4 314 103 2 2.0 3.0 8.21 0 0.65" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = df.drop(['Serial No.'], axis=1)\n", + "new_names = {'GRE Score':'gre', 'TOEFL Score':'toefl', 'University Rating':'rating', 'SOP':'sop', 'LOR':'lor', 'CGPA':'gpa', 'Research':'research', 'Chance of Admit ':'chance'}\n", + "df.rename(columns=new_names, inplace=True)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. Scope out Data\n", + "Show boxplots to see high-level distribution of main columns. \n", + "Use pandas.describe() to see high-level distribution of data." + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "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", + "
gretoeflratingsoplorgparesearchchance
count500.000000500.000000500.000000500.000000500.00000500.000000500.000000500.00000
mean316.472000107.1920003.1140003.3740003.484008.5764400.5600000.72174
std11.2951486.0818681.1435120.9910040.925450.6048130.4968840.14114
min290.00000092.0000001.0000001.0000001.000006.8000000.0000000.34000
25%308.000000103.0000002.0000002.5000003.000008.1275000.0000000.63000
50%317.000000107.0000003.0000003.5000003.500008.5600001.0000000.72000
75%325.000000112.0000004.0000004.0000004.000009.0400001.0000000.82000
max340.000000120.0000005.0000005.0000005.000009.9200001.0000000.97000
\n", + "
" + ], + "text/plain": [ + " gre toefl rating sop lor gpa \\\n", + "count 500.000000 500.000000 500.000000 500.000000 500.00000 500.000000 \n", + "mean 316.472000 107.192000 3.114000 3.374000 3.48400 8.576440 \n", + "std 11.295148 6.081868 1.143512 0.991004 0.92545 0.604813 \n", + "min 290.000000 92.000000 1.000000 1.000000 1.00000 6.800000 \n", + "25% 308.000000 103.000000 2.000000 2.500000 3.00000 8.127500 \n", + "50% 317.000000 107.000000 3.000000 3.500000 3.50000 8.560000 \n", + "75% 325.000000 112.000000 4.000000 4.000000 4.00000 9.040000 \n", + "max 340.000000 120.000000 5.000000 5.000000 5.00000 9.920000 \n", + "\n", + " research chance \n", + "count 500.000000 500.00000 \n", + "mean 0.560000 0.72174 \n", + "std 0.496884 0.14114 \n", + "min 0.000000 0.34000 \n", + "25% 0.000000 0.63000 \n", + "50% 1.000000 0.72000 \n", + "75% 1.000000 0.82000 \n", + "max 1.000000 0.97000 " + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plt.figure(1, figsize=(14,4))\n", + "for i in range(1,6):\n", + " plt.subplot(1,5,i)\n", + " plt.boxplot(df[df.columns[i]])\n", + " plt.title(df.columns[i])\n", + "plt.show()\n", + "df.describe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4. Detailed Data Distribution\n", + "Plot histograms for main columns to show detailed distribution of data" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "df[['gre','toefl','rating','gpa','research','chance']].hist(figsize=(14, 9),bins=16,linewidth='1',edgecolor='k',grid=False)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5. Show Correlation with Chance of Acceptance\n", + "Calculate correlation between each data column and Chance of Acceptance. \n", + "Here we can see GPA, GRE score and TOEFL score are the most important features because they have the best correlation with acceptance. \n", + "Research appears to be the least important feature." + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "gre 0.810351\n", + "toefl 0.792228\n", + "rating 0.690132\n", + "sop 0.684137\n", + "lor 0.645365\n", + "gpa 0.882413\n", + "research 0.545871\n", + "chance 1.000000\n", + "Name: chance, dtype: float64\n" + ] + } + ], + "source": [ + "correlation = df.corr()['chance']\n", + "plt.bar(df.columns, correlation, color='gray')\n", + "plt.show()\n", + "print(correlation)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 6. Plot Relations between GRE & TOEFL, and GPA & GRE\n", + "We can see a strong correlation between TOEFL and GRE scores -- people scoring high on one probably scored high on the other. \n", + "And we see a strong correlation between GPA and GRE -- people with a high GPA probably scored high on the GRE." + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "df.plot(kind='scatter', x='gre', y='toefl', color='green')\n", + "plt.xlabel(\"GRE\")\n", + "plt.ylabel(\"TOEFL\")\n", + "plt.show()\n", + "\n", + "df.plot(kind='scatter', x='gpa', y='gre', color='red')\n", + "plt.xlabel(\"GPA\")\n", + "plt.ylabel(\"GRE\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 7. Plot relations between Chance and other Features" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYwAAAEKCAYAAAAB0GKPAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAAIABJREFUeJztvXt8VPW57/951ppLICDGgAiEawNqoEI1FShCFWnrBbGtSK31ZWtrOZ6j1VYrtvscReF3en6I2/ZY7LbUurttrRbBykV3vaGbiwpGmyChCqkgBBQhBiRAMpf1nD/WzGRdvjOzZjK3JM/7VQuzZq01z5qE7/N97sTMEARBEIR0aMUWQBAEQegeiMIQBEEQPCEKQxAEQfCEKAxBEATBE6IwBEEQBE+IwhAEQRA8IQpDEARB8IQoDEEQBMETojAEQRAET/iKLUCuGDhwII8aNarYYgiCIHQr3n777cPMPMjLuT1GYYwaNQp1dXXFFkMQBKFbQUQfej03by4pInqMiD4hou2WY6cR0UtEtCv2Z0WSa78bO2cXEX03XzIKgiAI3slnDOMPAC5xHPsZgFeYeSyAV2KvbRDRaQAWApgM4HwAC5MpFkEQBKFw5E1hMPMGAJ86Dl8J4D9if/8PAF9XXPo1AC8x86fM3ArgJbgVjyAIglBgCp0lNZiZPwKA2J+nK84ZBmCf5XVz7JggCIJQREoxrZYUx5RDO4hoPhHVEVHdoUOH8iyWIAhC76bQCuMgEQ0BgNifnyjOaQYw3PK6CsAB1c2YeTkz1zJz7aBBnrLCBEEQhCwptMJYAyCe9fRdAKsV57wA4KtEVBELdn81dkwQBEEA0NLWgYZ9R9DS1lHQz81bHQYRPQngQgADiagZZubT/w9gBRH9AMBeAFfHzq0FcBMz38jMnxLRYgBvxW61iJmdwXNBEIReyer6/ViwsgE6aYiygaVzJ2LOpMKEeamnzPSura1lKdwTBKEn09LWgcm/eBkRo/OYTwO2/MssVPYLZnVPInqbmWu9nFuKQW9BEAQhhtX91HjgM5uyAICIATQe+KwgsvSY1iCCIAilQktbB5pbT6Kqok/WO3/AdD/dtWob/JqGsGHghi+NSnJmYTxFojAEQRByiHORv/+qc7KKMbS0deCuVdvQHjbQDtOseGzzHuW5Qwf06YrInhGXlCAIQo6wLvLHOiJoDxtYsGpbVtlMza0n4dfsS7SuEQK6vVStzK/heCjaJbm9IgpDEAQhR6gWeb+mobn1pPL8VOmxVRV90B6xK4Jw1AApSpurKgpjYYhLShAEIUdUVfRB2LBHpcOGoVzQvbiuoga7Xn/jvGFYUbc/cWxebVWX4iSZIBaGIAhCjqjsF8T9V52DMr+G/kEfyvwa7r/qHNeC7sV11XjgKBz6AgYDf/37ftuxFXXNBSvgEwtDEAQhh8yZNAzTqgemzJKKu67iwWyg03XVeb6qrR7gIw3hlNflD1EYgiAIOaayXzDlAu7FdTV0QJny2ih7c3nlA3FJCYIgFBgvrqv3Pj6mvPba80emdXnlC7EwBEEQikA619WHLceV1w3qH8Tmu2bmpDAwU0RhCIIgJCFXFdvJcLqurJ83srJcec3IyvK0Lq98IQpDEARBQa4qtuOkUz7Oz7v78hroGtlSa3WNMPVzlVnL0FVEYQiCIDhQteVYsGobplUPzGpnn6wleVyJlAd01+ctfm4HFl05HovW7kjcZ+ncwsUrVIjCEARBcOAt7TU5VmsCAO5YUR/rMmtWbt++oh7H2iNY/NwO+DUNHVEDYUcb2nDEwIShA/D6z4oTr1AhCkMQBMFBJhXbTlQdZlUtye9d24hwlG1KyUqUgXAkWrR4hQpJqxUEQXDgtWLbiaqC+9FNH2Qtx56WE1lfmw/EwhAEQVCQLO01VfBa5coK6DqYDUQswWufRghH08+wmDT81Bw9TW4QhSEIgpAEpzsoXeaUypUVZcY3zx2GFXXNiWNfqxmMF3Z87HJVWdEIqCgP5O5hcoC4pARBEDzgpWGgypV19+U1WNNwwHavl9/7JKWyAIDygC9pW/RiIRaGIAiCB7xmTjldWarrdI3g14BwCqVRyB5RXhGFIQiC4IFMMqecrqyT4Yjt/Y6we0IeAQj4NAT0TndXqWRHxRGFIQiC4IG4u2mBI4bhZVFnEABrkJsQZXacAzz3owtwPBQtiZoLFUVRGER0G4AfwlSqv2PmXznevxDAagC7Y4eeYeZFBRVSEATBgZdZF04aDxx1T85jdYbUex8fw+yJQ23H8t3PKhMKrjCIaAJMZXE+gBCAvxHRc8y8y3HqRmaeXWj5BEEQUpF5IZ16EJKKw23ttte57mfVVYqRJXU2gDeZ+QQzRwD8F4BvFEEOQRCEjGlp60DDviOex6KOH3oKfI6VVk+iQyYMHWD7nHRZWYWmGApjO4AZRFRJRH0BXAZguOK8qUTUQET/SUTjVTciovlEVEdEdYcOHcqnzIIg9EKcymF1/X5MW7Ie1z26BdOWrMea+v2o292CB198H3W7W5T3qOwXxIPzJiGgE4I+DQGd8ONZ45Tn+n164u/x7Crb+7GsrGJRcJcUM/+DiJYAeAlAG4AGABHHae8AGMnMbUR0GYBnAYxV3Gs5gOUAUFtbm75sUhAEwSOqduOLn9th6yj747/UIx6eeGh9E6ZXV+KPN05B08FjqN93BJOGn4rqwf1j4W4G2Ax+Rwx1Pm040pk91ZV+VvmCOEnwpWACEP0CQDMz/ybFOXsA1DLz4WTn1NbWcl1dXR4kFASht9HS1oFpS9ajPWxt8UEI+DS0dbhTYq2YVdwHE6/n1VbhmXeabYV6zpypOPdecTa+N21M4vWa+v2urKxcxzCI6G1mrvVybrGypE5n5k+IaASAbwKY6nj/DAAHmZmJ6HyYrjO1vScIgpBjlEV6uoaQh/5PVmUBwNYSJE6yuwzsV2Z7nU1WVj4pVh3GKiKqBBAGcDMztxLRTQDAzI8AmAvgvxNRBMBJANdwsU0hQRB6Dcl6Qi28ogaL18VmWEQMhKJp+ntkyFln9HcdK6X25kVRGMw8XXHsEcvflwFYVlChBEEQYiQr0pszaRguGX9GYsc/+6EN+OizUOK6geU+HD7uDMmqCehks1jK/BqOh1K7u4qNVHoLgiAomDNpGGqGnGILXlvZfajNpiwA4PDxCK6cOASrGz5KHJtXW4WVbzfDWrtHAIjckYxS6x3lRBSGIAiCAlXRHAO48+kGEBEiSdxR5UEf/BoQD21PrDrVFcdgAPdY3Ful2jvKSdGzpHKFZEkJgpArVFlSQZ+GUMRIGrCOo5M5XjVOsoyoZd/+AqZ+rrLoAe1MsqRkHoYgCD2KTCuxVaiK5oiSZzfFufjsQXAmUiW75nBbOyr7BTFx+Kklb1nEEZeUIAg9hmS9lzJt4KfKkookSanVNbMCmwGMO70/XvmHt64TF1QP8nReKSEWhiAIPYJkvZeeePNDVzuPdMSzpII+DX0DOoI+DQu+dqby3KgBtEcMdEQMPLZ5j6tvlF8nzKutsh27fuoIVA/unxNrqJCIhSEIQo8g2WS7+9Y2IhTlxPEFq7ahZsgpaedOONt5nDGgDNdPHYHH39ibOMenwVbBHdA1zL+oGstebYKuEaIGY+lc08qZd14VNuw6jBljB6J2dGXJdaL1ggS9BUHoESjbefg0+DWy1TcEdQITIagnX6hV9yrza9h810y0Hg+hft8RjKrsi28/ugVhi6vKrxPe/PnFiXPi6biuvlSzzQwp1f0LHc+QoLcgCL2OuBupzK+hf9CHMr+GhVfUuIYVdUQZoYi7ZbjVPdTcehLsGHrEBrs6xTo33MyMv23/GLOXbcJ9a3dg9rJNeGLLhy5X2X1rd0Ane4/zYnei9YK4pAShxCilCWvdDVXvpf5BH+5c2QCdNISNKHRNs+3s/ZqGJ7bsxW9ea0pYALd/ZRw6om5F8/tNH2CNpSjPiWEA963bgVCks6PtfWt3wK85lINOCEdKqxOtF0RhCEIJ0R392qWGs/eSuexT7H/kGpcaihp4+NVd6Ih0xjnu/9t7ynunUhYAzKsdVgcBCDuK/KIGY+EV47H4ue5VuCcKQxBKBGuWjzVAO616YMkvJMUinTUW/047LLt5n2YW4cWD0rdcVI2HX2uCtWIiybgKTzg72nZEDPzLZWfhwZd2uvtSTTijW1mTojAEoURQttSO+bW7w2JSaLzUXKhiAkQEwzCgkw6AEfTbXVQA0JUetJrjep2AyaMrsfmumS7lUEqdaL0gCkMQSoRSnLCWKbmMv6S6VzJr7Fh7xObmuX3WOJcyiGc1hQ0zc+qBF3e6OscGNCBs2Ku0NQLmnjcMK+o66zjOHFyO9w8eT7x2Nh4EzDYh5QG92ykHFaIwBKFESNZSu7ssMl2psnaes7p+Pxas3OaqZYifd/RkyHUPZrhqLpa+oI5FuC50oOka/r8ra3DfmkYQEZgZD1w9EXV7PrWdN3lMJR6+9rxECu3xUBQv7DjoSpct9bblXhGFIQglRKlNWPNKqh3/onU7XAu/FdXs7HvXNtrqG+54usFmPXREospYQXnAPhVPU7QQdxKKMv7l0rPw4MuKGINl9kXr8RBufaredu3jb+zF9VNGYW7t8MT3oKI7WYmpEIUhCCVGd3RdqOoWjKiBhWsaETHsC7+1yhqAS9E4lQVgupHix9uTRBh0Ak6E7O85U2NV+HXC5DHqGIOV+n1HlNfX7zuSmJXR3a3EdIjCEAShy5QHdNfibK7d7oX/0oc2oMznQ9gwcPOF1a5Av08jl8IAgGiaxd+DblASjjLKA7rruNPyuf0r45TXTxp+qu11d7USvSAKQxCELnM8FDWL0WzuIMBQLOLhKBCOmmNMl726C2alQicGu2dKODOPcolPA57f/jEefnUXdNIQZQP3zDZrJKyWz4Mv7cS82irbMKTrp45ARXkADfuOdOvsJ6+IwhAEocuUB3SXVaBSFk6ICDdfaNZBWF04ABLV2VE2MPfc4Xhi6940d8uOiAH86qWdMbVgBqfvWb3dfV7UwHcmj8T86WMSQe7Gjz7DtCXrc1ZoWepV/qIwBKFAlOpikE0Wk5PjoSiCOtncUn7NVBqpXEXtYQOXTjgD104e4br/0AFlie6up/YNeFIYs846HS+/90ni9bzaYVj1zgFXdbcVPwFhx9sqmSMGEI5EUR1rKJjrQsvuUOUvCkMQCkCpLgZe5PJyTlVFH5Bm9yMRmbMiUhHUzU6y1YPtLpx7nn0Xj79pKoiH1jfh+qkjXK3FVSyZe46tU2xFeQDPvJNm/oWGuGGRlj0tJ1A7uhJAbgstu0uVf1G61RLRbUS0nYgaiejHiveJiB4ioiYi2kZE5xZDTqF3ka9hNskG+xRjaI71Gb3I5VV2VafYH80ch6BOThFskEaoquiDpoPHsLJuH5oOHkPTwWMJZREnnr768k9m4IG55+D315+nvF/r8RCqB/fH3NrhqB7cH82tJ9HHb98Xl/k1+DWgr19H0Ee494oJ8DvkdA5BimMNcOey0FI1ErYUu9cW3MIgogkAfgjgfAAhAH8joueYeZfltEsBjI39NxnAv8X+FIS8kE8LIB8tP7JxbzmfUZWh5JQrE9nnTBqGmiGn2Hb3D7/WlNIn9cWRFfi/L++0KYhpYyqV59bvO5JQBCvr9iU9J57iCiQbtWpA1zQz1s6E/mU+/OvVE3Gno1Cw7sNPbRZNfEpenFym0HaXKv9iuKTOBvAmM58AACL6LwDfAHC/5ZwrATzOZrP5N4noVCIawsypW0UKQhbk2x2Q68UgG+WmesZlr9ob7qnkykR2lVzzzqtyWQtWNja1YGNTi+3Y5g9alOdW9PUn/u5MZU123Lmoh6JRGAxbM8IFq7Zh810z8frP7HUYcyYNw/VTRtkGITnJVQptd6nfKIbC2A7gfxNRJYCTAC4D4ByVNwyAdQvRHDsmCkPIOflu+pfLxSBb5aZ6xoCuYf6MMa4MJet9vMqukuvOlduQrso6E1pPhBN/rygPwFnDTbHjTqyWT5lfx09XNrgyuppbT2Li8FNdz1U9uL9SUVjJVQptd6jfKLjCYOZ/ENESAC8BaAPQACDiOE3l+HT95hHRfADzAWDEiBE5llToLRTCHZCrxSBb5ZbsGa+dPEKZoeRFdmdXWGcmUtRg5T/kbLFaD82tJ6E5azUIyu/Bavl0RCJwtnVqDxvKwr1iUOr1G0UJejPz75n5XGaeAeBTALscpzQDGG55XQXggOI+y5m5lplrBw0alD+BhR6NKmCbD3dAZb+gchebCdkqt1TP6EUu5zmr6/dj2pL1uO7RLZi2ZD1efe+ga9ceMRhhD8UYcyYOsb2OZ0Q5j1l3+uFI1BUaibJ53IozaJ+sB+CBo6UVXC5VipJWS0SnM/MnRDQCwDcBTHWcsgbALUT0FMxg91GJX/Q+Clm30B3cAUDX3Fu5ekaV++nh1/6pPNdZ/e0kqBN+cMEY3DpzrCtWkCp+sKflhPJ+1rRXQN3jSk0ubaGeS7HqMFbFYhhhADczcysR3QQAzPwIgOdhxjaaAJwAcEOR5BSKRDHqFkrdHRCnKwu/6hkzVcwqt5hP0xCOurfv5Io0ON6PpdVW9gu6lEKq+IHXoLeqx5UTnwaMH3pKynMEk6IoDGaerjj2iOXvDODmggollAzdpYipmORKuWWjmKsq+qDd4foJRw34NLMaOo5fJ/xoZjWWvdqUSFc9f1SFLStqXm0VKvsFM1Za1YP7uwr5nG4rwKxAL3NM1DNrLhh+TUeUDSydO1F+rzwild5CySGjSgtDJorZuqADADuGDjEzfLqGiCW+omuE08oDABhgArOB1z+wDyB6cus+nDn4FNuUPK/W5KIrP690W1llVcV2dI2w7pbpiRbr8jvlHVEYQsnRXYqYujteFbOq4K+P34djHZ3JjX0DPleK7t2za7B43Q50RBidvTfc7c6dU/LiSsva4iOZa8rptlJZTKqYT7pUWUGNKAyh5OguRUylRqZuHS+KWV3w525JHk/RvXTCGbZxpU6FpEJz5Mf6NQ13P/sunt9+MHHs+qkjsOjKz6e8TzKLafNdM9MORxK8IQpDKEm6S9ZSqZBNLMKLYlYX/OmYPnYgnt/+ceLYvNoqbGo6bB+1OrvGpZBUGI4splDUsCkLoLOXVCrLIJXF1NV0ZsFEFIZQspRq1lKptSnvSpKAs/+TMw5QHtBdi34oGsUrlhbiAPCXt/bhL281oyPSKcPidTtw9+U1WLSuETppiBhRRJlsBX5+nbBwzngsXtcZw/jmF4bhz1vdvaKcfaKciCsz/4jCEIQMKJU25c4qa9XOuvHAZxjQx59SsamehwHbsS+OtGc2XXz26di4s8XWj0knzVXK4Nc0tBwPASDzf6ThO+dX4S9vNdua/M2ZNAyTR52WUFoAlAojWSptHHFl5h9yZjt0V2pra7muztmSShByR0tbB6YtWW9L0Szza9h818y8dp11nuNc5OPBZatcPg3QNQ0B3a7YnNlOzucJ+jQAHAtUq9EJ8OmaTWEEfQSAHMfc9yrza/jT98/HnpYTCYtGpbRUnWIXXfn5nAx7EuwQ0dvMXOvlXLEwBMEjXU33TbfwexledPflNa5Z03HXTzw11dqRNb6AL1i1DcfaIwn3UJQN3HLRWNfz6BoBTEg1USjKwPxpo/Doxg/MKUnMWDp3Iur2fGrrTDvrrNPxwo6Pbdd2hA1c+/utCOpuZWd1p919eQ0COoGIwMyoHXmaZ+uuVF2ZPQGxMATBI12xMFIt/Mnupfq8+CJq3cmX+TX8Zf7UhHvq6MkQbn7i77a01/KAjvawvf+STuZ67yy2MwxOOVYVAMYP6Y/Gj44lXk8eXYGG5qMOWTWE0ozcC/g0+DVz6l5C1qCOcMRAyCKEyoLpqnUnmGRiYRSl+aAgdEeybVKomlp339pG+DS70985YU3VB4mZbYsm4O62OnSAO/gbStKsz5nEZBhsprmmwaosAGDL7lZojiAGeWjP5NcJ7WG7NdMeisKv25cmnTTT+rFeW4IT6Xo64pIShAzIJt1X6crS7e0qAKA9ErVl9Kj6IIUNIKABIculQZ3w/PaP8RtL0ZwzUP3lMwfh5X8ccsmm64BhWa91jeDT1X2h0uG0JgwP3otI1ICmEaKW59Q0slWMA0CUjZirrBPJgCo8YmEIeSdfs7KLRaZtypVjQg1WttewEu+DZCXo09xbdwIefrXJZsE4p9ht3HVYMbea4NjcIxRl11wLr8w663Tb6y+PHag8z68R+gZ0BH0abrloLMp89lkUZT7dPG6x5JbOnYilc/Pfgl5IjVgYQl4plTTUYlLZL4h5tVW2rJ9ZZ52ODbsO2+IMffw+WwBdtXsmAu6ZPd7We+nmC6uxfMMHLleV/TrCrRfZGwHeclE1lq3fZbNigjrhlouqEy0+2sMRhBW3HV5Rhn2t7YnX1YP64rVddgtmY9Nh6I4hRxR7BrNDCOO08kBGg52c1p1kRBUWURhC3uhNXWdTLVwtbR1YUddsO/byewehaq9hVRIqRTOvtgrfmTISl0w4w5Ye+9B65wwyO+1hA5dOOANTx5yGDbsOY8bYgRg9qB8efq3JtqKTRq7F+sdP/d1msUwZXYH65qO2++9tbYffEWMI6DpuuWgMfr1+JwgaDDYAIoSijFDM5bX4uR24e3YNFq3tzN6yWg7O79KaASWbkcIjCkPIG4XqOlvsXWa6hStZe41k87SbDh5D/b4jGFXZ16VoVtQ147aLx9kWzpa2jrRupKBO+NeXduI/Y+08HlrfhOunjkhZ6Bb/c/TAcpvCqCwPuocSMbsGJYUNA6eVB0CxgDVH3cOUIlEDLW1mcZ8Z8/A2yCjVZgSAWB15QhSGkDcK0aqh2LtML1ZUJvO073n2XVstg88RZVQp3MYDR5Eu7MDghLKIE+/PlKoxX9PBYzZ5AOA5x30AM/YxZ+IQrGnoHIw5Z+IQLH5uR0pXWcQAHnplFyKWB7jj6Ya0VmiyzcgTW/bagv9ideQWCXoLeSMfs7KtAXRVuuqCVdsKGlyPL1xWnOmeXudpqxZn51obV7jW7+H9j+0prnE0IPF5X605Q3nOC40fpwzi1+874uFbMHEqpGf/fsCVOqwi4tB24Sij8cDRJGebqJRwKBp1Bf8L/fvQ0xELo4dTbHdNLrvOquYyFHvQklcrysv3kGxx9umEPj49sWPe1HQYC1Y2JHz+X/pcpfK6ayePwNW1w1FV0QdPbd2Lde+6LYN0pOvfZJNTs7uc/LpmK77LjNSKRtU3ShX8l8FbuUUURg+m2O6aOLlo1aCey9AE10CeAufmZ9LwLt33kGxxfurGyfD79MRzTf7FyzHLwwwcv/b+YeV1X580FBNj9/za+DOw9MWdrnO+Nl5tecSpKA8ksqri6LE0J2fVuNMtFmXGwitqbJ1onfUh82qr8Mw7zTZLyuuMbacSBmAG8S1IrUZuEYXRQ+lpGUrqwLGWNHCcT5xWW66sqGRzqmtHd1oQG3YecrmpGMCEIf2x3VJ9Pb26Eqf2DWBl3b5Ek79kM7BVVmj82NGTIfT1647pembAftmruxJWztK5EwHApTjnTBqGS8afYbt/PKgfl+uC6oG402IxZTJj26mEpVttfhGF0UPpaXOxMwkc55NkVlvOGt6l9eCoTxg8oMymMD451o5Zv9yQeB3v9jrnnKGJtNra0ZVp25uHolGXgmqPRD3XSQDuRd05VjWXbksZvJVfRGH0UHraMJl0rp9CLAz5SOW07u5bj4dcQe/H39iLc4efig8On8CMsQMxfugA+HV7rMCnAa+8Zy+ae//gcdd9hp3aFw++tBO6Rvjthg9wzxXuTrF3rtyGeEvyZKNV4xXpKiWpOuYljpbLDrPSrTZ/SLfaHsya+v1KF0F3pphB/IZ9R3Ddo1ts7pn+QR9+OGNMVqmczt19sklzVqZXV+Lq2uG4c+W2RGxh7rlVeGLr3pTXAXDFInwaIejTbJ1i+wZ0gIETzp4hFvoHffjTjZMT8REr2bRwF4pLyc/DIKKfALgRpn39LoAbmLnd8v73ACwFsD92aBkzP1poObs7pWyeFzt7yytWOdWpnAYefnWXbUe+YNU21Aw5BcdD0aTPp7JWVr2z33Wek41NLbjt4rF4/WedtRMbd37iSWE4i/siBoMcDQPNc1JvIpNZql5md3TnOJpQBIVBRMMA3AqghplPEtEKANcA+IPj1L8w8y2Flq+nUYrmeba7zkLvVlWflzyVs9PqYINx2a83JYYEqabdqdpyEwGXfX4wnn/3YEq5Nuw6jNrRlYmf6weHT6R9lovPHoRXFN1qb7xgNP799T32aXeOQUjTqyvx1oetKQPJKgV439pGBHzqGpVS+50UvFGsGIYPQB8iCgPoC+BAkeQQCky22Vuprms9HrJl3XRFNmuKpurzNt8101YZDbhTOc1mfoyQY9qdtWHg7V8Z525vHjZw+6wzcfusM1G/7wh8GvDjFdtccs5wdIGdMXYgHlrf5DrvV/POQcQw03UrygOWdFwTnwbcOH0Mbpw+xvY8C1bZP/OtD1ux7pYLUlpMyVq4O+swunMcTShCpTcz7wfwAIC9AD4CcJSZX1ScehURbSOilUQ0XHUvIppPRHVEVHfokHv3JJQeXiqjM7nufz27HbN+uQE/XbkNs365Afesfld5fboW66vr92PakvW47tEtmLZkPf68Za8nOZ1V3AGdXC3JdY1w39pGWwXyAy/uRMDRbjyom5PnKsoDGDu4P6aPOx3Tq+1FedOrK21ptgAwelA/V5kbAaiq6GuT88F5kxD0Efr6dQR9hAfnTXJVmyf7ORw4mvrnU1XRByfDEduxjkgUC6+okZbkPYhiuKQqAFwJYDSAIwCeJqLrmPlPltPWAniSmTuI6CYA/wFgpvNezLwcwHLADHrnXXihy2SbvaW6riMSSdofyWpppHNlZVIUuH3/UXxr+Ruue8VjReUBHZc+tNEuZ9iA5owLKJJNSCPl/W+7eKwtFdZJ44GjrqgDA5j72zcTr+NptTVDTklpjZmjXN2Wzw/+8Bb8up6ok1C5Aqmzb3ni9SXjz3DVYajoLjGt3k4xeknNArCbmQ8xcxh9hKycAAAgAElEQVTAMwC+ZD2BmVuYOb4V/B2A8woso5Ansu0vpbru6vNGKM+1ttjw0m9KZb0EdHO4j3VHbg3iOu8V36VXlAeUg5FCjgzVUJTx06+eaXueZPcfPagfbv/qmTZlYbWY9nsYU/r4G3vx2//6Jy7/9Ubcs7oRl/96I9bU73fd68DRduX1YcPMnOqIMG5fUe+y1JpbTyoHIcXjFakGTjmtu7hcQunhycIgorEA/g+AGgBl8ePMPCaLz9wLYAoR9QVwEsDFAGz5sEQ0hJnjbS/nAPhHFp8jlCjZZm85r2s9HlJmB1lbbHgpYExm9ZxWHgBApn+HCZ8eD6W9V3PrSfTx+2ypt0GfjojBthGmZX4Nk8dU2uIhXostnRbT5ROGePr+lvztvVj7DjNl9vYV9a7Yyg3TRqW9T8QAGg98hhnjBiWOZWs59rSOBD0drxbGvwP4NwARABcBeBzAH7P5QGbeAmAlgHdgptRqAJYT0SIimhM77VYiaiSiBpgZVd/L5rOE0kAVP8h0zKnquni7CyvxdhdxvCxkKuslvtvviBg4EYqiI2Jg2atNicE/znvFn7E8oLs+L8qGa6pqXDbr83iRVWUxrWnwtiN39nqKGMC9a7bb7vXYpt2uUa5q7DeLf4dBn5YYv+rFcsw2piUUB68xjD7M/AoRETN/COBeItoIYGE2H8rMCxXX3mN5/+cAfp7NvYXSIt+psIuu/DyunzIqqV/ea3NAp/WSSe+qTU2Hbc84r7YKK+qabecA7j5Lqirp+686x1aU5zxPtZAy7LEDFcnO0GPydD5jvE+UOco1EjUQZXsNh18njB86QCFH7P/Z/mmp4hM9rSNBT8erwmgnIg3ALiK6BWZB3elprhF6OYVyN8SziirKA8r3vbrAnDUrXnpXAcC0Jettz7iirlmZhupFBtWia11wVUFp5zwJFQEfwWA42o8TWBHYdz7j5qbDNiW2dG7yOoyOCCPu8lKlEzs3DJl0+xWKj1eF8WOY9RK3AlgMM2Ppu/kSSugZFKIBolcLJtMCxnS7/fifDfuOKJ/xeCiqbJ2RCtWie8fTDdDI3PmHDQM3fGmU8tpZZw3Cy5Z+UtOrK7F1z6eubrLOhd881pBynnYyhessRHR+DzoR7lu3A6FI6g1DKXckEOx4UhjM/BYAxKyMW5lZPeJLECzk292QbwsmmYvFSrJnLA/oaNh3JG1PpXSLbtwiiFeSP7ppt1KOr39hGH526dkJ11zjR59h657WRMAeMBdmZ1rt6vr98DJP26lwXW1AZte4v4eogYBPQ8hSnpFsw1CKHQkEN16zpGphBr77x14fBfB9Zn47j7IJ3Zx8uxtybcGoKr2dLhanMlI947zzqjB72aa0PZWc7pq7L3cvuk6STTw91h5JtA3vtFQ675Xs8+5d22hzU3mZp61S1IvX7Ug8p/O5rUh8onvj1SX1GID/wcwbAYCILoCpQM7Jl2CCne5a2OTV3ZDN8+XSgunK+Fdn4d7sZZvS9lSKV3+Hop1NCxc/twN3z+6cUBeKGogahq2dRzSJPrEqB2VgnOH6vHvXboezKW18nvaMcfYQZTpLyK9pmDBsgC1NuLJfEP3LfBKf6EF4VRjH4soCAJh5ExGJW6pAdPcW0encDdk+X64smFyMf40/ozKmoeqpFOXY8c4V269pmDDUvuhubjpse77bvzIOv3j+PdfnX1Dd2V9KFRjviBgoD9jl8JGGsHLmhd2MUXWhTaaonT9riU/0LLwqjK1E9FsAT8L8V/QtAK8R0bkAwMzv5Em+Xk9PL2zq6vPlYkFKlUJrHUOaShnFd+DqOgzG1ycNxYq65sSxr08aijUN9p6bqkVXFXdobj2hHLUa53goiqBOsSaI8echOHQIoklm4QwdkKjNVbufHJaQWA69B68KY1Lsz3itRHwL8iWYCsTV50nIDT1t1KqT5taTYEdaKBuc0fN1NWCartI7XUDYuQP/4sgKbGxqSbw/Z6JbOaxpOOBp0VVZX+lqT6oq+riUgcGM2hGn4s3drYljNUNOwbv7j8Jq/OgE20ClpO6noW73k5fvprtZx4IdrwpjHUzFEP9XwwA+A1DHzPX5EEww6emFTeUB3bYTBsz24OUBPckV6ck0HqJybXkNCKt24FZlAQDP1h+A3xGtji+66265IOnCn8r6cs7FduJsBAiQTVkAQH3zUdd1UYbtu0/1+5dOUfd067g34lVhnAegFsAamErjcgBvAZhPRCuZ+f48ydfr6emFTcdDUZT5NZvPvcxvHxuaCdnuaJ2unwNHT9qUBdAZEB4/dIAtAOy0kJz4dUI44l50t+8/mrKoLVvrsrn1pKvnT7JRzM754M7vviu/fz3dOu6NeFUYlQDOZeY2ACCihTD7QX0ZwNsARGHkkXwHDr3uyPORqZXMUsrGgurKjnZ1/X4ssBS1fT9JE743/tmC+X98uzMIPWucy0JyEjUYC68Yr0w5TSVrttalympLJqLmskTMz206eCyhPLP9/evp1nFvxKvCGAEgZHkdBjAyNmJVPZFGyCn5KmzyuiPPly+6sl8Q82qrbEHcebVVOQtee9nRtrR14KdPN9h22r/b+IHy3N9v2m1LTX3gxffTyjWvtgrfmTISl0w4I21qqlXWbHf3yYYdzTp7EF62jGm9fuoI1I48zXX///vyTtuI1vgsjWwaRfZk67g34lVh/BnAm0S0Ovb6CgBPElE5gB3JLxNKGa878nz6olvaOmzZQ4DZi+m2i8dlfO9sd7SNB4663E8RAwlrI45PI/g0eyqsaofu5M9b9iaeJ12vKqes2e3u1QH666eOxk0zPucaxuRsGX/rU/awpGoolVckrbZn4am9OTMvBvBDmBPyjgK4iZkXMfNxZv5OPgUU8ofX1tL5bEGdy3tnO5wp2QIbNZxKhN3tzZNV0tmuM+dHqGS1DmhKJqvXVvBNB49hZd0+9PVrcNQJwqcB+z49gese24p/37wH1z22NTGoyHp/6/ApK8mOeyHbVvZC6eF5RGusDYi0AulBeN2R59MXnet7Z7OjHT/0FPg02CqqdTItCmctg1OJJIklK3CfaB4hW7+nbLnn2XdtbiRn88F7rhiPxetSx0wA+/ApK8mOC72LYoxoFUoErzvy7HfuuZMhjmoYk+qezh1tqusq+wVx7fn2QUxXnTcMpGjc1MeR7lvmMf136IA+Nhms/Z7iA5ri417jlkLTQW/NFJoOHrMpC8BM7f3Ntedi0ZXj8dyPpmPC0AFJLTmrXF6GUgm9F88WhtAz8dK6urJfMOe+aOv9vd4728B7uuta2jqw4m17HGVNw0eYM9FRnf2FYa4CvIgHl1RQJzy//WP8xjJ46eYLq5UFi3c/+y6e334wcSwecE5FMnfRf/vT2wj4dEQNxj2za9BmGRsLAG0dEWzffxTfWv5GRoWBQu+FkuVndzdqa2u5rq4u/YlCWvJdnZvN/VvaOhKDiuKU+TVsvmtm2gyodNc17DuC6x7dYpvDbbb4YIQi9uucHVmv+eJw/OH1D1PKTgACPs3WIDCgA15LTV7+yYyUi3bTwWOY9csNKe+hkzq1NuiQy8t3KvQsiOhtZq71cq64pAQbqpnRcVdJMe+fbXDcy3XKOErUQEBXVGfHOrL+6cbJ2HzXTMw8K/3gSQYUQWgdAd0hV5JZ2ukCztWD++OC6sqU5ySrw3B+oszTFlIhCkOwkc+MqK7cP9vguJfrVHGUhVeMd40+tbbEiMdIhg7wFpx3F9IZIMdqrTkPxEgXcG5p60Ddh60pz0mGU49IYZ2QClEYgo18V+dme/9sA+9er5szaZjNcvjOlJGxtFcNfQM6gj71dcmK5JzcfOHnbDIsnTsRS+fa77907jlZBZxVStiJTzMLCJ33Xjo3P8kMQs9Egt4OuuugolyRSXVuNt9VV6p/sw28ew3s7z7Ulihqq+wXTDqi1XrdZycjqo+04dOAmWcNxhXnDHWNR2U2EI1q4Fiq63kjT8NTW/eCYB6rHXla2vurlLBfJxAYPk1PzPSeM2kY5k8f4wpmS2Gd4JWiBL2J6CcAboT5r/BdADcwc7vl/SCAx2E2PWwB8C1m3pPqnrkIeksr5k7SKYNMvivVvfKpmL3c2yn/iNP6YOfB44n3p4yuQH3zUVew3Bn0vmHaKPzba+o2Iqmuu/vyGixcs91d+6FTbCxs57VegtBr6vfjzpUNibqLpXMniiIQPJFJ0LvgFgYRDQNwK4CaWC+qFQCuAfAHy2k/ANDKzNVEdA2AJTCHNuWN3tKKORcLdSbfVTLFUszeWCr5rcoCAN7c3Yq+fntMQTVW9bFNu10dX3WNYou/hqjBibkX1s+716EsADMwHYDdmknWC8v5c8xlEWBX6O0Wek+nWC4pH4A+RBQG0BfAAcf7VwK4N/b3lQCWERFxHs2h3tCKOVeNBpMFqJ3fVaGVsNfPU/2sVZwI23/dToai6OPXbe1BAroem8zXlOg99a0vVuGprXsRjTIYBj5tC7k+T499t04inD6+oxqZuvi5Hbb02DueboBGpnyFspbFQu/5FDzozcz7ATwAYC+AjwAcZeYXHacNA7Avdn4EZv+q1HmDXaSnt2L2ms7q5TzVzOj2sOEaepSPjKtUFduppvdZUf2svWAwlJlT104egdd/NhNP/nAKnvvRBfjzlr0IRYGOqIFQFPjVyzsRchT4MdiVRuvXCfdeMSFlEFr187lvbSN8jqr0cJTREeG8pEaryHc6tlAaFFxhEFEFTAtiNIChAMqJ6DrnaYpLXdYFEc0nojoiqjt06JDiEu/ks/1FKeB1MfWyyMdnRlsJ6uQaepRrJby6fj+mLVmP6x7dgmlL1iea58XxOr1P9bM+c3C57Zxxg+yv41x17jDl70g81fbA0Xalq+n700a5sqT+9eqJCOiEoE9DQCf869UT8Z0pI23ZWs4duvLno2sIpZnJke/6inynYwulQTFcUrMA7GbmQwBARM/AnA3+J8s5zQCGA2gmIh+AAQA+dd6ImZcDWA6YQe+uCtaTWzF7XUxTLfJx/3R5QDf7LFnuRxq5FEEu5yF4cTcdD0VdFc3OGdVxVD/rut0tiSypU/sGlNXT3582Gnd89cwUvyPqX8Opn6vEjdPH2K5bXb8fRBRzZXWemyq+o/r5RJmx8IrO+eChqIGoYdgUV76t5Z5uoQsmxVAYewFMIaK+AE4CuBiAM71pDYDvAngDwFwA6/MZv7CSr2BssfE6CjXZIr+p6bDNPz2vtgor6prTKoJcKWEvMaZwJOqqaI6yeVyF82ddO7oyMSMCAC6orsQmy3zu6dWViVTUZEHooQP6uILgfp0wfugA2+dZmw/G8RLfSfbzmTNpGCaPOi2RMrvjo88KOrhIhiX1DgquMJh5CxGtBPAOgAiAvwNYTkSLANQx8xoAvwfwRyJqgmlZXFNoOXsamYxCdS7yABL9mOIL9oq6Zqy75QIcD0ULYo152cHuaTmhvHZPywmbIvCCqnr6rQ9b0dLWocwEs453/fb5w/GXt5oTr5fOdS+cqRRg/P1k36tKCasCzpvvmllQa7knW+iCSVGypJh5IYCFjsP3WN5vB3B1QYXqZmRa25DpDtC6G27Yd0S5uB0PRTHR0bbCOgs6XpyWi8wZL6NcU81ysLqbvCgPrws6ANd41ye37sN/3jo9pTJNpgC37z+Kqx/ZnCjce+DqScrvS2WtON11m++a6fr55Dvttada6IKJVHp3Q1SLMANpF+Zsd4Be/dPOIT7zaquwpuFATtJqvYxyjc9ysCqV66eOwL1rGxOupYfWN2F6dSX+eOOUrJ7Z2Q78hi+Nco13DUcZB46exIxxyRsTqhT43bNr8L/+uj0WBTE/+7an6tN+X15TwiXtVegqojC6Gard5J0rtwEw0yjTLczZ7AC9WCeqIT4r6prR16/OnHHK4LRMnKTK8mo9Hkpc65zlcORECHN/+6btuo1NLajb3ZLS0ki2oDsL8H6/aU+SO6QvnnMq8Df+2eIKmTOAFxs/Rs3QARlbK1aF3lsKU4X8IgqjmxB3JRw9qSoCo1h1b2dwN9dFh+msk2QtuJ31B14sE9XQoGRZXo9t+gCrGz5yXRtXOg+++L5Srg27Dqd1TTmfWbmT95kZTlbRfJo59tULVgV+uK1dec7dq7ejj9+X1CrwotB7Q2GqkH9EYXQDrK6EUDQKw5kJZDCc6Zz5SGlMZZ0kix8s+NpZePDlnRlZJo+/sRfXTxllszRUWV4BnWzKQnXtjLED8dD6JpdcM8YOTPO0Js5ndqW0GoxFV07AonWNtj5O2SzCF1QPAvAP1/GIgcRwp2RWQTqFLmmvQi4QhVHiqFwJPg2xYq/ORRhA3lMaUwVMk8UP5n/5c7jqvKqMLZP6fUdsCkO1sCWr1d7UdCgRcK4dXYnp1ZXY6EiPzTRrCkiT0jr6tC6PNFV9hz4NtnqKVFZBKoUuaa9CLpARrSWOanxo/6APD3/nXAzo4y9YB1ivAdN0sYg4cVnDkagrxgCox5Kuqd9vW/Bu/8o4/OL591zXBnQg6LO7cDLNkkqF83vOdTA5/h2OquyL6x7bmvFY2kxkF4SS7lYrZEYyV8L4oafkJKDthUwCptWD+6fdYTtdbBrB5mbTNUJFecB1ncrt0tx6wrYjJ5izskNRuwvHWZTXFbyktHYlmGz9DnNtFUjaq9AVRGGUOKXgSshlwFS1wDrp69c9u12sWVFlfh0/f+ZdmzWW78BuvoPJUgwnlBKiMLoBxV40chkw9dJaPNN7x3fkLW0dBQ/sFiKYLFaBUCrITO9uQrwbajEWjlx28lUtsPEgflfvXYyOwz29y7EgWJGgt+CZXAVMncHr+686J6cWVDECuxJMFrorEvQWuoxqAcyVa2TOpGGoGXKKK5sqVwutuHAEIT+IwhBc5DpNNNs01Hzv2nN1f+nRJPQWRGFkgdeFxmtNQimR6zTRZPOn090/k0XYy88jX7UT0qNJ6E2IwsgQrwuNqj/SbRePK0k/t3Ux7cqcBtV9nYvpfWsbEfClbkiYahF2yuCcRbF0rjseYp7TkGjdcc8V411NBBes2oaaIae4WpKnU0bF6tEkMROhGIjCyACvu8lk/ZGe2roPQZ9eUm4LlwUwu8ZTW28v8isXU8X8aWcaarJF+Ikte/Gb15ps1sq9axtt7cV/sqIBPg0I6HrinIVrtsfaa5jNGe95djvK/PbRtGwwLvv1JgT1zFrGF6NHk7jAhGIhabUZ4HXQffLOrYxjHRG0hw0sWLUNLW0deZPVC1YFGJdr8boduPvyGluaqNWNlIn8qeZPp0pDVV0Xihp4+NVdNhmcygIwmwF2RDq/53sTysIqAxByjG3tiDJCkc5737lyGxasbEj7zIVOq1X9zErhd0noHYiFkQFed5PJOrdaKVZraS/upwnDBtjGe2brdknVrO+S8WdkNB3w5gursXzDB+iIdFZx+zRyKQwneux6JzdOH4N/f30P/JqGjkgUmka2nk2ZtIwvZGGltCkXiokojAzw2qZD1XXU2S+pGK2lVQHoZAowXVtvr/InW0zTpb6q5oo//Jq9TbnBgE72WRROGAy/blcsfp1w4/QxuHH6GDS3nkR5QMfsZZts12XaMr5QqbzSplwoJlK4lwVe52lbs6R2fPSZcqddKFraOjBtyXpX59O7Z9dg0Vr7LAeVXKpiu1zK7yWIq5IBAO60BLS/9cXhWFHXrDjHHhh3yp7s3sX8mSUj3z8LoXeRSeGeKIwcUCp1BalI1ib9hzPG4OFXm1IupnHyJX9XU2idx7wq9GzuXSqUqlxC90MURgFJtnPvysyCrsiSbBFRyRn0EQBCR6R4spfS9ycIvZFMFIZkSXURr5lT+WZ1/X5MW7Ie1z26BdOWrMea+v2291XZPLdcNBYBvbiyl8r3JwhCegoe9CaiMwH8xXJoDIB7mPlXlnMuBLAawO7YoWeYeVHBhMyAUghCeq0P8RJIzofsqSyfUvj+BEHwRsEtDGZ+n5knMfMkAOcBOAHgr4pTN8bPK1VlAZRGe+tku3HVcWub9ELIno3lI+3BBaE0KXZa7cUA/snMHxZZji5R7AFH5QHdFgMAgPawgfKAnuSKTvIpe7aWjygLQShNiq0wrgHwZJL3phJRA4ADAH7KzI3OE4hoPoD5ADBixIi8CemFYrbUPh6KIqgTOiy1BkGdcDwU9ZRNky/ZM+lL1RUZJGNIEApD0RQGEQUAzAHwc8Xb7wAYycxtRHQZgGcBjHWexMzLASwHzCypPIpb0lRV9AFp9go20iir/k+5lutkOGI7djIcyalc0ldJEApHMbOkLgXwDjMfdL7BzJ8xc1vs788D8BPRwEII1dLWgYZ9R0quN08quVRxgGz7P2UrQzKIyPV60brGnMglfZUEobAU0yX1bSRxRxHRGQAOMjMT0fkwFVtLvgUq1d2qF7mccYBc9xzK5rtpbj2JMp+OcLTTyvDrWqzjRvoeTemQvkqCUFiKYmEQUV8AXwHwjOXYTUR0U+zlXADbYzGMhwBcw3muMCzV3WomclkzoHKZrprtd6PsVmswopwbuUopJbdULVNByCVFURjMfIKZK5n5qOXYI8z8SOzvy5h5PDNPZOYpzPx6vmUq1QKybOXKZbpqLmVYOvccLJ07MSdylUpKbrrUYUHoKRQ7S6pkKKXdqpWuyKVKV80moyjXMgDIWRptsVNyZUSr0JuQ1iAxSmW3mkyuoE9D34COoC8zuaxuqmQ74XTulK5+N1YZUh3LllzeK1NK1TIVhHwgFoaFYu9Wk8Hx/2eCc0aDV5LthI+1R7D4uR1pg9ml+t0Um1K1TAUhH4iF4aCYu1UV8YW+I8I4EY6iI8JZBeNVO2GdCPet8556W2rfTSlQqpapIOQDsTBKnFyljip3wlEDAZ+GkKW2rhRGx3a3xVasL6G3IBZGiZMrl4dqJ7zwivGIGN7HkOaLnpBlJNaX0BsQC6PE8TpH3AuqnfD7Bz+zzR6fV1tV0EVPsowEofsgCqMbkEuXh7XJX0tbB1bUNdveX1HXjNsuHlewxToXLrfu7M4ShO6EKIxuQj46ypZCa42uutxULUskniAI+UEURg+n1KfddcXlpnJn3b6iHrqmIaCXVj8wQegJiMLowXjZfecqPtIVsnW5qSykiAFEDAMdEYmHCEKuEYXRQ1Htvu94ugEaAQFdt+2+S8GFk43LTWUhOZHutYKQOySttoeiKtQLRxkdEXYV6XXXlFBnqnDQR/Dr9vkbUnUtCLlDLIweSm/ZfTstpM1Nh4vuYhOEnooojB6KMz4RihqIGgYiFh3SU3bfVndWqbjYBKEnIgqjB9Nbd9/5SEEWBEEURo9Hdt+CIOQKURi9DNl9C4KQLZIlJQiCIHhCFIYgCILgCVEYgiAIgidEYQiCIAieKLjCIKIziaje8t9nRPRjxzlERA8RURMRbSOicwstpyAIgmCn4FlSzPw+gEkAQEQ6gP0A/uo47VIAY2P/TQbwb7E/BUEQhCJRbJfUxQD+ycwfOo5fCeBxNnkTwKlENKTw4gmCIAhxiq0wrgHwpOL4MAD7LK+bY8cEQRCEIlE0hUFEAQBzADyteltxjBX3mE9EdURUd+jQoVyLKAiCIFgopoVxKYB3mPmg4r1mAMMtr6sAHHCexMzLmbmWmWsHDRqUJzEFQRAEoLgK49tQu6MAYA2A62PZUlMAHGXmjwonmiAIguCkKL2kiKgvgK8A+G+WYzcBADM/AuB5AJcBaAJwAsANRRBTEARBsFAUhcHMJwBUOo49Yvk7A7i50HIJgiAIySl2lpQgCILQTRCFIQiCIHhCFIYgCILgCVEYgiAIgidEYWRBS1sHGvYdQUtbR7FFEQRBKBgyojVDVtfvx12rtsGvaQgbBu6/6hzMmSRdSwRB6PmIhZEBLW0duGvVNrSHDRzriKA9bGDBqm1iaQiC0CsQhZEBza0n4dfsX5lf09DcerJIEgmCIBQOURgZUFXRB2HDsB0LGwaqKvoUSSJBEITCIQojAyr7BXH/VeegzK+hf9CHMr+G+686B5X9gsUWTRAEIe9I0DtD5kwahmnVA9HcehJVFX1EWQiC0GsQhZEFlf2CoigEQeh1iEtKEARB8IQoDEEQBMETojAEQRAET4jCEARBEDwhCkMQBEHwhCgMQRAEwRNkTkPt/hDRIQAfFluOLBkI4HCxhciS7iw70L3lF9mLR3eW3yn7SGYe5OXCHqMwujNEVMfMtcWWIxu6s+xA95ZfZC8e3Vn+rsguLilBEATBE6IwBEEQBE+IwigNlhdbgC7QnWUHurf8Invx6M7yZy27xDAEQRAET4iFIQiCIHhCFEYBIaJLiOh9Imoiop+lOG8uETERlUwWRjrZieh7RHSIiOpj/91YDDlVePneiWgeEe0gokYi+nOhZUyFh+/+l5bvfScRHSmGnCo8yD6CiF4lor8T0TYiuqwYcqrwIPtIInolJvdrRFRVDDlVENFjRPQJEW1P8j4R0UOxZ9tGROd6ujEzy38F+A+ADuCfAMYACABoAFCjOK8/gA0A3gRQW2y5vcoO4HsAlhVb1ixlHwvg7wAqYq9PL7bcmf7eWM7/EYDHii13Bt/9cgD/Pfb3GgB7ii13BrI/DeC7sb/PBPDHYsttkW0GgHMBbE/y/mUA/hMAAZgCYIuX+4qFUTjOB9DEzB8wcwjAUwCuVJy3GMD9ANoLKVwavMpeiniR/YcAHmbmVgBg5k8KLGMqMv3uvw3gyYJIlh4vsjOAU2J/HwDgQAHlS4UX2WsAvBL7+6uK94sGM28A8GmKU64E8DibvAngVCIaku6+ojAKxzAA+yyvm2PHEhDRFwAMZ+Z1hRTMA2llj3FVzLxdSUTDCyNaWrzIPg7AOCLaTERvEtElBZMuPV6/exDRSACjAawvgFxe8CL7vQCuI6JmAM/DtJBKAS+yNwC4Kvb3bwDoT0SVBZAtF3j+vbIiCtU+aEkAAAQ8SURBVKNwkOJYIkWNiDQAvwRwR8Ek8k5K2WOsBTCKmc8B8DKA/8i7VN7wIrsPplvqQpg79EeJ6NQ8y+UVL/LHuQbASmaO5lGeTPAi+7cB/IGZq2C6Sf4Y+7dQbLzI/lMAXyaivwP4MoD9ACL5FixHZPJ7laAUfjC9hWYA1l13Fezmd38AEwC8RkR7YPoV15RI4Dud7GDmFmbuiL38HYDzCiRbOtLKHjtnNTOHmXk3gPdhKpBSwIv8ca5B6bijAG+y/wDACgBg5jcAlMHsdVRsvPzOH2DmbzLzFwD8z9ixo4UTsUtk8nuVQBRG4XgLwFgiGk1EAZj/uNfE32Tmo8w8kJlHMfMomEHvOcxcVxxxbaSUHQAc/s85AP5RQPlSkVZ2AM8CuAgAiGggTBfVBwWVMjle5AcRnQmgAsAbBZYvFV5k3wvgYgAgorNhKoxDBZVSjZff+YEWa+jnAB4rsIxdYQ2A62PZUlMAHGXmj9Jd5Mu/XAIAMHOEiG4B8ALMDIzHmLmRiBYBqGNm1yJQKniU/VYimgPTJP8UZtZU0fEo+wsAvkpEOwBEAdzJzC3Fk7qTDH5vvg3gKY6lwJQCHmW/A8DviOgnMF0i3yuFZ/Ao+4UA/g8RMczMxpuLJrADInoSpnwDY/GhhQD8AMDMj8CMF10GoAnACQA3eLpvCfxsBEEQhG6AuKQEQRAET4jCEARBEDwhCkMQBEHwhCgMQRAEwROiMARBEARPiMIQhDQQ0RlE9BQR/TPW0fZ5IppPRKXWwkUQ8oooDEFIARERgL8CeI2ZP8fMNQD+BcDg4komCIVHFIYgpOYiAOFYsRMAgJnrAWwE0C/WaPE9InoiplxARPcQ0VtEtJ2IlluOv0ZES4hoa2xuxfTYcZ2IHiCid2PNG38UO34eEf0XEb1NRC946SYqCPlEFIYgpGYCgLeTvPcFAD+G2eZ6DIBpsePLmPmLzDwBQB8Asy3X+Jj5/Nh1C2PH5sPsMvuFWPPGJ4jID+DXAOYy83kw207879w9liBkjrQGEYTs2crMzQBARPUARgHYBOAiIloAoC+A0wA0wuzmCwDPxP58O3Y+AMwC8AgzRwCAmT8logkwldVLMQNFB5C2148g5BNRGIKQmkYAc5O812H5exSAj4jKAPwG5rTEfUR0L8yGes5rouj890dwt5YmAI3MPLULsgtCThGXlCCkZj2AIBH9MH6AiL4Ic/6BirhyOExE/ZBc2Vh5EcBNROSL3f80mC3WBxHR1NgxPxGNz/IZBCEniMIQhBTEOqd+A8BXYmm1jTCnxClnBzDzEZjzQN6F2Tb9LQ8f8yjMNt/biKgBwLWxsaBzASyJHasH8KUuPo4gdAnpVisIgiB4QiwMQRAEwROiMARBEARPiMIQBEEQPCEKQxAEQfCEKAxBEATBE6IwBEEQBE+IwhAEQRA8IQpDEARB8MT/AxWcggb9ysONAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "for i in range(1,7):\n", + " df.plot(kind='scatter', x='chance', y=df.columns[i]) \n", + " plt.xlabel(\"Chance\")\n", + " plt.ylabel(df.columns[i])\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 +} From c957de2edc1c0e91fee785e3bf8b3c246ba63090 Mon Sep 17 00:00:00 2001 From: Joe James Date: Sat, 9 Feb 2019 14:03:15 -0800 Subject: [PATCH 04/75] Intro to Python Data Structures initial upload --- .../Intro Python Data Structures.pptx | Bin 0 -> 188344 bytes .../Python Data Structures.ipynb | 1096 +++++++++++++++++ 2 files changed, 1096 insertions(+) create mode 100644 Intro to Python Data Structures/Intro Python Data Structures.pptx create mode 100644 Intro to Python Data Structures/Python Data Structures.ipynb diff --git a/Intro to Python Data Structures/Intro Python Data Structures.pptx b/Intro to Python Data Structures/Intro Python Data Structures.pptx new file mode 100644 index 0000000000000000000000000000000000000000..0619f3243cffb03446679efb8945b9595853cd42 GIT binary patch literal 188344 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�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

uUF*02#(o-Q(Hw@>pgN*m|u>J7Cw6K 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 E1GZZRG5`Po literal 0 HcmV?d00001 diff --git a/Intro to Python Data Structures/Python Data Structures.ipynb b/Intro to Python Data Structures/Python Data Structures.ipynb new file mode 100644 index 00000000..3b42851f --- /dev/null +++ b/Intro to Python Data Structures/Python Data Structures.ipynb @@ -0,0 +1,1096 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Intro to Python Data Structures\n", + "Lists, Tuples, Sets, Dicts \n", + "(c) 2019 Joe James \n", + "## Sequences: String, List, Tuple\n", + "****\n", + "**indexing** - access any item in the sequence using its index. \n", + "Indexing starts with 0 for the first element." + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "g\n", + "cow\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'frog'\n", + "print (x[3])\n", + "\n", + "# list\n", + "x = ['pig', 'cow', 'horse']\n", + "print (x[1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**slicing** - slice out substrings, sublists, subtuples using indexes. \n", + "[start : end+1 : step]" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "omp\n", + "opt\n", + "puter\n", + "compu\n", + "r\n", + "ter\n", + "comput\n" + ] + } + ], + "source": [ + "x = 'computer'\n", + "print(x[1:4])\n", + "print(x[1:6:2])\n", + "print(x[3:])\n", + "print(x[:5])\n", + "print(x[-1])\n", + "print(x[-3:])\n", + "print(x[:-2])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**adding / concatenating** - combine 2 sequences of the same type by using +" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "horseshoe\n", + "['pig', 'cow', 'horse']\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'horse' + 'shoe'\n", + "print(x)\n", + "\n", + "# list\n", + "y = ['pig', 'cow'] + ['horse']\n", + "print(y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**multiplying** - multiply a sequence using *" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bugbugbug\n", + "[8, 5, 8, 5, 8, 5]\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'bug' * 3\n", + "print(x)\n", + "\n", + "# list\n", + "y = [8, 5] * 3\n", + "print(y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**checking membership** - test whether an item is or is not in a sequence." + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'bug'\n", + "print('u' in x)\n", + "\n", + "# list\n", + "y = ['pig', 'cow', 'horse']\n", + "print('cow' not in y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**iterating** - iterating through the items in a sequence" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "7\n", + "8\n", + "3\n", + "0 7\n", + "1 8\n", + "2 3\n" + ] + } + ], + "source": [ + "# item\n", + "x = [7, 8, 3]\n", + "for item in x:\n", + " print(item)\n", + " \n", + "# index & item\n", + "y = [7, 8, 3]\n", + "for index, item in enumerate(y):\n", + " print(index, item)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**number of items** - count the number of items in a sequence" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "3\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'bug'\n", + "print(len(x))\n", + "\n", + "# list\n", + "y = ['pig', 'cow', 'horse']\n", + "print(len(y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**minimum** - find the minimum item in a sequence lexicographically. \n", + "Alpha or numeric types, but cannot mix types." + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "b\n", + "cow\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'bug'\n", + "print(min(x))\n", + "\n", + "# list\n", + "y = ['pig', 'cow', 'horse']\n", + "print(min(y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**maximum** - find the maximum item in a sequence lexicographically. \n", + "Alpha or numeric types, but cannot mix types." + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "u\n", + "pig\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'bug'\n", + "print(max(x))\n", + "\n", + "# list\n", + "y = ['pig', 'cow', 'horse']\n", + "print(max(y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**sum** - find the sum of items in a sequence. \n", + "Entire sequence must be numeric." + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "27\n", + "20\n" + ] + } + ], + "source": [ + "# string -> error\n", + "# x = [5, 7, 'bug']\n", + "# print(sum(x)) # generates an error\n", + "\n", + "# list\n", + "y = [2, 5, 8, 12]\n", + "print(sum(y))\n", + "print(sum(y[-2:]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**sorting** - returns a new list of items in sorted order. \n", + "Does not change the original list." + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['b', 'g', 'u']\n", + "['cow', 'horse', 'pig']\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'bug'\n", + "print(sorted(x))\n", + "\n", + "# list\n", + "y = ['pig', 'cow', 'horse']\n", + "print(sorted(y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**count(item)** - returns count of an item" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "2\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'hippo'\n", + "print(x.count('p'))\n", + "\n", + "# list\n", + "y = ['pig', 'cow', 'horse', 'cow']\n", + "print(y.count('cow'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**index(item)** - returns the index of the first occurence of an item." + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "1\n" + ] + } + ], + "source": [ + "# string\n", + "x = 'hippo'\n", + "print(x.index('p'))\n", + "\n", + "# list\n", + "y = ['pig', 'cow', 'horse', 'cow']\n", + "print(y.index('cow'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**unpacking** - unpack the n items of a sequence into n variables" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "pig cow horse\n" + ] + } + ], + "source": [ + "x = ['pig', 'cow', 'horse']\n", + "a, b, c = x\n", + "print(a, b, c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lists \n", + "****\n", + "- General purpose\n", + "- Most widely used data structure \n", + "- Grow and shrink size as needed\n", + "- Sequence type\n", + "- Sortable \n", + "\n", + "**constructors** - creating a new list" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 2, 3, 4, 5, 6, 7]\n", + "[25, 36, 49, 64, 81]\n" + ] + } + ], + "source": [ + "x = list()\n", + "y = ['a', 25, 'dog', 8.43]\n", + "tuple1 = (10, 20)\n", + "z = list(tuple1)\n", + "\n", + "# list comprehension\n", + "a = [m for m in range(8)]\n", + "print(a)\n", + "b = [i**2 for i in range(10) if i>4]\n", + "print(b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**delete** - delete a list or an item in a list" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 8, 6]\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6]\n", + "del(x[1])\n", + "print(x)\n", + "del(x) # list x no longer exists" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**append** - append an item to a list" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 3, 8, 6, 7]\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6]\n", + "x.append(7)\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**extend** - append a sequence to a list" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 3, 8, 6, 12, 13]\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6]\n", + "y = [12, 13]\n", + "x.extend(y)\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**insert** - insert an item at a given index" + ] + }, + { + "cell_type": "code", + "execution_count": 134, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 7, 3, 8, 6]\n", + "[5, ['a', 'm'], 7, 3, 8, 6]\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6]\n", + "x.insert(1, 7)\n", + "print(x)\n", + "x.insert(1, ['a', 'm'])\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**pop** - pops last item off list and returns item" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 3, 8]\n", + "8\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6]\n", + "x.pop() # pop off the 6\n", + "print(x)\n", + "print(x.pop())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**remove** - remove first instance of an item" + ] + }, + { + "cell_type": "code", + "execution_count": 136, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5, 8, 6, 3]\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6, 3]\n", + "x.remove(3)\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**reverse** - reverse the order of the list. It is an in-place sort, meaning it changes the original list." + ] + }, + { + "cell_type": "code", + "execution_count": 137, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[6, 8, 3, 5]\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6]\n", + "x.reverse()\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**sort** - sort the list in place. \n", + "Note: \n", + "sorted(x) returns a new sorted list without changing the original list x. \n", + "x.sort() puts the items of x in sorted order (sorts in place)." + ] + }, + { + "cell_type": "code", + "execution_count": 138, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[3, 5, 6, 8]\n" + ] + } + ], + "source": [ + "x = [5, 3, 8, 6]\n", + "x.sort()\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tuples\n", + "****\n", + "- Immutable (can’t add/change)\n", + "- Useful for fixed data\n", + "- Faster than Lists\n", + "- Sequence type \n", + " \n", + "**constructors** - creating new tuples." + ] + }, + { + "cell_type": "code", + "execution_count": 139, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2,) \n", + "(2, 4, 6) \n" + ] + } + ], + "source": [ + "x = ()\n", + "x = (1, 2, 3)\n", + "x = 1, 2, 3\n", + "x = 2, # the comma tells Python it's a tuple\n", + "print(x, type(x))\n", + "\n", + "list1 = [2, 4, 6]\n", + "x = tuple(list1)\n", + "print(x, type(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**tuples are immutable**, but member objects may be mutable." + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 2, 3)\n", + "([1], 3)\n" + ] + } + ], + "source": [ + "x = (1, 2, 3)\n", + "# del(x[1]) # fails\n", + "# x[1] = 8 # fails\n", + "print(x)\n", + "\n", + "y = ([1, 2], 3) # a tuple where the first item is a list\n", + "del(y[0][1]) # delete the 2\n", + "print(y) # the list within the tuple is mutable" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sets\n", + "****\n", + "- Store non-duplicate items \n", + "- Very fast access vs Lists \n", + "- Math Set ops (union, intersect) \n", + "- Sets are Unordered \n", + " \n", + "**constructors** - creating new sets" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{3, 5}\n", + "set()\n", + "{2, 3, 4}\n" + ] + } + ], + "source": [ + "x = {3, 5, 3, 5}\n", + "print(x)\n", + "\n", + "y = set()\n", + "print(y)\n", + "\n", + "list1 = [2, 3, 4]\n", + "z = set(list1)\n", + "print(z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**set operations**" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{8, 3, 5}\n", + "{8, 3, 5, 7}\n", + "{8, 5, 7}\n", + "3\n", + "True\n", + "8 {5, 7}\n", + "set()\n" + ] + } + ], + "source": [ + "x = {3, 8, 5}\n", + "print(x)\n", + "x.add(7)\n", + "print(x)\n", + "\n", + "x.remove(3)\n", + "print(x)\n", + "\n", + "# get length of set x\n", + "print(len(x))\n", + "\n", + "# check membership in x\n", + "print(5 in x)\n", + "\n", + "# pop random item from set x\n", + "print(x.pop(), x)\n", + "\n", + "# delete all items from set x\n", + "x.clear()\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematical set operations** \n", + "intersection (AND): set1 & set2 \n", + "union (OR): set1 | set1 \n", + "symmetric difference (XOR): set1 ^ set2\n", + "difference (in set1 but not set2): set1 - set2 \n", + "subset (set2 contains set1): set1 <= set2 \n", + "superset (set1 contains set2): set1 >= set2" + ] + }, + { + "cell_type": "code", + "execution_count": 143, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{3}\n", + "{1, 2, 3, 4, 5}\n", + "{1, 2, 4, 5}\n", + "{1, 2}\n", + "False\n", + "False\n" + ] + } + ], + "source": [ + "s1 = {1, 2, 3}\n", + "s2 = {3, 4, 5}\n", + "print(s1 & s2)\n", + "print(s1 | s2)\n", + "print(s1 ^ s2)\n", + "print(s1 - s2)\n", + "print(s1 <= s2)\n", + "print(s1 >= s2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dictionaries (dict)\n", + "****\n", + "- Key/Value pairs\n", + "- Associative array, like Java HashMap\n", + "- Dicts are Unordered" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'pork': 25.3, 'beef': 33.8, 'chicken': 22.7}\n", + "{'pork': 25.3, 'beef': 33.8, 'chicken': 22.7}\n", + "{'pork': 25.3, 'beef': 33.8, 'chicken': 22.7}\n" + ] + } + ], + "source": [ + "x = {'pork':25.3, 'beef':33.8, 'chicken':22.7}\n", + "print(x)\n", + "x = dict([('pork', 25.3),('beef', 33.8),('chicken', 22.7)])\n", + "print(x)\n", + "x = dict(pork=25.3, beef=33.8, chicken=22.7)\n", + "print(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**dict operations**" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'pork': 25.3, 'beef': 33.8, 'chicken': 22.7, 'shrimp': 38.2}\n", + "{'pork': 25.3, 'beef': 33.8, 'chicken': 22.7}\n", + "3\n", + "{}\n" + ] + } + ], + "source": [ + "x['shrimp'] = 38.2 # add or update\n", + "print(x)\n", + "\n", + "# delete an item\n", + "del(x['shrimp'])\n", + "print(x)\n", + "\n", + "# get length of dict x\n", + "print(len(x))\n", + "\n", + "# delete all items from dict x\n", + "x.clear()\n", + "print(x)\n", + "\n", + "# delete dict x\n", + "del(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**accessing keys and values in a dict**" + ] + }, + { + "cell_type": "code", + "execution_count": 146, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['pork', 'beef', 'chicken'])\n", + "dict_values([25.3, 33.8, 22.7])\n", + "dict_items([('pork', 25.3), ('beef', 33.8), ('chicken', 22.7)])\n", + "True\n", + "False\n" + ] + } + ], + "source": [ + "y = {'pork':25.3, 'beef':33.8, 'chicken':22.7}\n", + "print(y.keys())\n", + "print(y.values())\n", + "print(y.items()) # key-value pairs\n", + "\n", + "# check membership in y_keys (only looks in keys, not values)\n", + "print('beef' in y)\n", + "\n", + "# check membership in y_values\n", + "print('clams' in y.values())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**iterating a dict - note, items are in random order**" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "pork 25.3\n", + "beef 33.8\n", + "chicken 22.7\n", + "pork 25.3\n", + "beef 33.8\n", + "chicken 22.7\n" + ] + } + ], + "source": [ + "for key in y:\n", + " print(key, y[key])\n", + " \n", + "for k, v in y.items():\n", + " print(k, v)" + ] + }, + { + "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 +} From e93dd56cef50bf58ea8195ef92f5c88a851b4af8 Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 13 Feb 2019 14:21:41 -0800 Subject: [PATCH 05/75] Tensorflow Keras initial upload --- ...nsorFlow Tutorial with MNIST Dataset.ipynb | 337 ++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 Tensorflow_Keras/TensorFlow Tutorial with MNIST Dataset.ipynb diff --git a/Tensorflow_Keras/TensorFlow Tutorial with MNIST Dataset.ipynb b/Tensorflow_Keras/TensorFlow Tutorial with MNIST Dataset.ipynb new file mode 100644 index 00000000..49cb48ed --- /dev/null +++ b/Tensorflow_Keras/TensorFlow Tutorial with MNIST Dataset.ipynb @@ -0,0 +1,337 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# TensorFlow Tutorial with MNIST Dataset\n", + "**About the MNIST dataset**. \n", + "MNIST is the equivalent *Hello World* of image analysis.\n", + "It consists of hand written numbers, 0-9, in 28x28 pixel squares. \n", + "Each gray-scale pixel contains an integer 0-255 to indicate darkness, with 0 white and 255 black. \n", + "There are about 60,000 training records, and about 10,000 test records. \n", + "In other words, the images of numbers have already been transformed into arrays of ints to make them easier to use for ML projects. You can find more info on the dataset [here](http://yann.lecun.com/exdb/mnist/). You can also download it from [here](https://s3.amazonaws.com/img-datasets/mnist.pkl.gz).\n", + "## 1. Load Data into a Numpy Array \n", + "I downloaded the data file onto my desktop and loaded it locally. \n", + "You can also load it directly from the cloud as follows: \n", + "```mnist = tf.keras.datasets.mnist \n", + "(x_train, y_train), (x_test, y_test) = mnist.load_data() \n", + "``` \n", + "**After the load:** \n", + "x_train contains 60k arrays of 28x28. \n", + "The y_train vector contains the corresponding labels for these. \n", + "x_test contains 10k arrays of 28x28. \n", + "The y_test vector contains the corresponding labels for these." + ] + }, + { + "cell_type": "code", + "execution_count": 218, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 47040000 (60000, 28, 28)\n", + " 60000 (60000,)\n", + " 7840000 (10000, 28, 28)\n", + " 10000 (10000,)\n", + "8 2\n" + ] + } + ], + "source": [ + "import pickle\n", + "import numpy as np\n", + "\n", + "with open('/Users/joejames/desktop/mnist.pkl', 'rb') as f:\n", + " (x_train, y_train), (x_test, y_test) = pickle.load(f, encoding='latin1')\n", + " \n", + "print(type(x_train), x_train.size, x_train.shape)\n", + "print(type(y_train), y_train.size, y_train.shape)\n", + "print(type(x_test), x_test.size, x_test.shape)\n", + "print(type(y_test), y_test.size, y_test.shape)\n", + "print(y_train[55], y_test[583])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Use Matplotlib to visualize one record. \n", + "I set the colormap to Greys. There are a bunch of other colormap choices if you like bright visualizations. Try magma or any of the other colormap choice in the [docs](https://matplotlib.org/tutorials/colors/colormaps.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 217, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 217, + "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.cm as cm\n", + "import matplotlib.pyplot as plt\n", + "\n", + "plt.imshow(x_train[55].reshape(28, 28), cmap=cm.Greys)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Plot a bunch of records to see sample data \n", + "Basically, use the same Matplotlib commands above in a for loop to show 18 records from the train set in a subplot figure. We also make the figsize a bit bigger and remove the tick marks for readability." + ] + }, + { + "cell_type": "code", + "execution_count": 213, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 213, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgsAAAEdCAYAAACCOCTVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3Xu81VP+x/H3mS6SJLoQ4bhEJSSJqYxIaRQJFVNyp1zLNX4mUkY0aZLcScgkRoZhcilSIYoowkzkNrocl8g9zu8Pj8/a69veZ5199jn7/nr+0+exzt77rL5nn33W97PW+qyS8vJyAQAAVOR32e4AAADIbQwWAABAEIMFAAAQxGABAAAEMVgAAABBDBYAAEAQgwUAABDEYAEAAAQxWAAAAEEMFgAAQFDtqjy4SZMm5aWlpWnqSn5buXKlysrKSlJ5Ltc1bPHixWXl5eVNq/o8rmsY1zU9uK7pwXVNj2Sva5UGC6WlpVq0aFHqvSpgHTp0SPm5XNewkpKSD1N5Htc1jOuaHlzX9OC6pkey15VpCAAAEMRgAQAABDFYAAAAQQwWAABAEIMFAAAQxGABAAAEMVgAAABBVaqzgOLz8ccfS5ImTpzo2iZMmCBJGj58uGs7//zzJUnbb799BnsHAMgEMgsAACCIwQIAAAjKm2mIX3/9VZL0448/Bh83depUF3/77beSpLffftu1/e1vf5MkXX755a7tpptucvGmm24qSRo/frxrGzp0aKrdzkuffvqpi/fZZx9J0ldffeXaSkp+OwLDrqUUu+5r167NRBeLzvLly1186KGHunjJkiWSpKZNq1wyv+jccccdLh4yZIik2OeKJL377rsu3m233TLXMRQt+3v2888/u7b58+dLin4On3jiiZKk2rWz9yebzAIAAAjKemZh3bp1kqRffvnFtb3xxhuSpKefftq12Z3t7bffXuXv4Z84duGFF0qS7rrrLte2xRZbuPjAAw+UJB1yyCFV/j757MMPY2eJdO3a1cVffvmlpFg2QYpdr0022cS1rVmzRpL0/vvvu7Ydd9zRxbVq1arZDteg//znPy62/2/Hjh2z1Z2EFi5c6OJu3bplsSf5Z/bs2ZKkCy64wLX97nfx90n+exyoSX5m1s9az5kzR1L09zsRyzKMHDkyDb1LDpkFAAAQxGABAAAEZWUa4pNPPnFxu3btJMXSvzXJUo3+lIMtYDz11FNdW7NmzVzcoEEDSYW9YMxfTGPTDz179nRtVluhIvYzu+aaa1xbly5dJEktW7Z0bf6UkX+9c42lqSXpnXfekZQ70xDl5eWSolMl7733Xra6k5fsev3www9Z7knuWrlypSTpnnvucW2zZs1y8auvvhr3nGnTpkmK1lZ55plnJEknnXSSa/OngYuBv8jb6tP4dWq+//57F9vv90477eTaGjduLElavHixa7vtttskRRfbZ/pvFJkFAAAQxGABAAAEZWUawtIskrT11ltLSm0aokePHnGv+cgjj7g2W63vr+6HdPHFF7vYrzGRrLlz50qK1bGQpL59+0qKXv/XX3891S5m1I033uhi/z2VC9avXy9Juvbaa12bldaWCnu6rDr82ipXXXVV3Nfbt28vKbrjarPNNkt7v3LJggULXNy/f39J0urVq12bpcgl6eijj5YUnaIcNGhQ3Gvac/xU/OTJk2uox7nHn9oaM2aMJOmWW25xbbbbryJ77rmnpNhnqiRt2LBBUuxvoxT7ufivxzQEAADIKVnJLNgiQym2oObhhx92bb///e8lScccc0zcc20hnST985//dHHdunUlSatWrXJt/qISxO4K7r//ftfm3z0YyxJIsZ+BfxdhC5pat27t2i699FJJ0Z9jotfORX6Nj1xjlQZ9/nVH1H//+19J0uGHH+7avvjii7jHjR07VlK0xkoh8ytV2mLGXr16uTbLYB111FGuze6UpdjCZf935ZRTTpEkTZ8+Pe77derUqQZ6nfv87Iy9pyrTpk0bF7/wwguSpIYNG7q2zz//vIZ6V7PILAAAgCAGCwAAICjr5Z73228/SdJee+3l2mxK4ZJLLnFt119/vSRp9OjRcY/zbbPNNi72F4UVq2QPhRo4cKBr8w/csYVifttxxx0nSapfv75r23bbbSVFy+jed999Lh4xYoSk6J7sbPvf//4nKXqNck2iFHr37t2z0JP8cOedd0pKXCvEFulJ0sEHH5yxPuWC5557zsWHHXZY3NcHDBggSbr77rtdm1/O3dghR1Li6QerqeBPZRYyvy5FInYgmX98gF+fxp9+MH7p/VxCZgEAAARlPbNgEo1it9xyy7g2f5ubHfokcQjMxsrKyiRJ1113nWuz7an+lhyrHOZXBvMzNlat0f6tiu+++87F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rLy8vGlVn8d1DeO6pgfXNT24rumR7HWt0mChtLRUixYtSr1XBaxDhw4pP5frGlZSUvJhKs/juoZxXdOD65oeXNf0SPa6Mg0BAACCGCwAAIAgBgsAACCIwQIAAAhisAAAAIIYLAAAgCAGCwAAIKhKdRayafTo0ZKkkSNHuraOHTu6+Omnn5YkbbHFFpntGICC069fP0lSeXm5a3v44Yez1Z20WL16tYufeuopSdLYsWNd2yGHHOJi/7PWDBw4UJJUq1atdHUROYTMAgAACGKwAAAAgnJ6GuKrr75y8Y033ihJ+t3vYuObxYsXu/ijjz6SJO25554Z6l3+Kisrc/GGDRskSa+88opr69Onj4v9652Mk08+2cW33Xabi4stVfnLL79IklasWOHahg0b5uInn3wy431C2DXXXOPiJ554QpI0fPjwbHUnbf71r39Jkv70pz+5tm+++SbuccuXL3fx5MmT475uUxOtWrWq6S4iB5FZAAAAQTmdWahfv76LjzzySEnSPffck6Xe5KdVq1a5+N5775Uk3X777a7t119/lRTLzEjRbEJJSdUO0vR/PltuuaWLx4wZI0naZJNNqvR6+erHH3+UFL3ratGihYvXr18vSWrQoEFmO4aI8ePHu9jPLNStW1eS1KtXr4z3Kd26desmKfreS5RZqEznzp0lSXPnznVtbdu2rWbvkKvILAAAgCAGCwAAICinpyEsFShJO+20UxZ7kr9GjBjh4vvvvz+j33vChAkuHjJkiCRpl112yWgfcsknn3zi4nXr1kliGiLb5s+f7+KffvrJxUcccYQkqVOnThnvU7ptuummkqILkI8//nhJ0rfffuvadt55Zxe///77ca/zxRdfSJIef/xx18Y0RHrZ54YUfb/OmDFDUmy612f1MCTpr3/9a8rfm8wCAAAIYrAAAACCcnoa4ocffnDx66+/nsWe5C9Lp0qJpyG23XZbSdJFF13k2myHhJS4zsK8efMkSTNnzqyxfhYDv3QwUvOf//xHUrTs+9133+1iS7FXxt7DL774omtr06aNi/0ptELlfzbsvffekqLXo0mTJi5ONA1hbIoRNevtt9928fTp0yVF6118+eWXLg7tWps9e3aN9IfMAgAACMrpzMLPP//sYn+UlcjLL78sSdphhx1cG4dKSX379nWxLUjyWeagKgvtzjzzTElS69atXZtf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hg2ubcWKFRnvEwAgM8gsAACAIAYLAAAgiGkIBI0aNUqSdOutt7q2tWvXSpIGDx6clT4BADKLzAIAAAgiswBJ0rfffuvifv36ufipp56SJJWUxOpN7b///pKkyZMnZ6h3AIBsIrMAAACCGCwAAICgGp2G+OmnnyRJzz33nGvbdNNNJUkLFixwbevWrXPxpEmTJEl9+/Z1bS1atEjq+2233XYu7tOnjyRphx12qGq3i5rVT7joootc29NPPx33uClTprh4v/32kxT72eI35eXlLj7nnHMkSdOmTXNtH330kYsbNmyYuY4BCTz//PMunjkxxI5yAAAOVklEQVRzpiTp5Zdfdm2vv/563HP++Mc/uvjBBx+UJNWrVy9NPYSxv609e/Z0bX5tmzfeeEOS1KhRo7T1gcwCAAAIqtHMwsSJEyVJl156aZWf+8ADD1Trew8fPlxS9ECn008/XZJ0zDHHuLZ0jrzy0ddffy1Juv/++4OP809ta9WqVTq7lLf8ipZPPPGEpNj1laQXX3zRxf4dApBu3333nYst6zV16lTXttVWW0mKZg523313Fz/66KOSpMcff9y1derUSZL02muvpaHHxeGbb76J/OvbbLPNXLx48WJJ0WzQ3nvv7eJMZHnJLAAAgCAGCwAAIKhGpyH8RXAhzZo1c/GBBx6Y1HNat24tSVq+fLlrW7NmjYvnzZsnSXrllVdcm8X77ruva2vXrl1S36+Q+YdCWdrRX5znW7hwoaTo9A4Sq1OnjovtevmLGj/99NOM96nY2HTmDz/84NqWLl0qSbrxxhvjHr/PPvu4eNGiRWnuXfb06tXLxW+//bYkady4ca5t6NChkipOZ1vV1pYtW7q2N998U1K0uuuQIUNqqMf567PPPnOxvedWrlyZ8LE2vZDoIL7x48e72N7D/ue0/7P49ddfU+9wksgsAACAIAYLAAAgqEanIebPny8pmnpNVPegbt26Lm7QoEHK3+/HH3908R577CFJev/99+Me99BDD7mYaQjp73//u4st/TVo0CDXdtNNN7l48803z1zHCsjFF18sSXrkkUdc27Jly7LVnYLx3nvvSYql0qVYSXJJuvPOOyUlnlbzS5YbS6VLUvv27V1cKCv833rrLUnSCy+84NpsyuGCCy5I+nWaNm0qSRozZoxrO++88yRJN9xwg2tjGiJaU+j6668PPtZq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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "images = x_train[0:18]\n", + "fig, axes = plt.subplots(3, 6, figsize=[9,5])\n", + "\n", + "for i, ax in enumerate(axes.flat):\n", + " ax.imshow(x_train[i].reshape(28, 28), cmap=cm.Greys)\n", + " ax.set_xticks([])\n", + " ax.set_yticks([])\n", + "plt.show" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Show distribution of training data labels \n", + "The training data is about evenly distributed across all nine digits. " + ] + }, + { + "cell_type": "code", + "execution_count": 214, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5923 6742 5958 6131 5842 5421 5918 6265 5851 5949]\n" + ] + } + ], + "source": [ + "counts = np.bincount(y_train)\n", + "nums = np.arange(len(counts))\n", + "plt.bar(nums, counts)\n", + "plt.show()\n", + "print(counts)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Apply Keras/TensorFlow neural network \n", + "Use tensorflow to train the model with 60k training records, compile the model, and classify 10k test records with 98% accuracy. \n", + "**Create the model** \n", + "Build the keras model by stacking layers into the network. Our model here has four layers:\n", + "- Flatten reshapes the data into a 1-dimensional array\n", + "- [Dense](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense) tells the model to use output arrays of shape (*, 512) and sets rectified linear [activation function](https://keras.io/activations/). \n", + "- [Dropout](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dropout) applies dropout to the input to help avoid overfitting.\n", + "- The next Dense line condenses the ouput into probabilities for each of the 10 digits.\n", + "\n", + "**Compile the model** \n", + "- [Adam](https://keras.io/optimizers/) is an optimization algorithm that uses stochastic gradient descent to update network weights.\n", + "- Sparse categorical crossentropy is a [loss function](https://keras.io/losses/) that is required to compile the model. The loss function measures how accurate the model is during training. We want to minimize this function to steer the model in the right direction.\n", + "- A metric is a function that is used to judge the performance of your model. We're using accuracy of our predictions as compared to y_test as our metric. \n", + "Lastly, we fit our training data into the model, with several training repetitions (epochs), then evaluate our test data. \n", + "\n", + "Our final result is about 98% accuracy in classifying 10k digits in the test set. You can try tweaking this model with different settings to get a better score. An easy tweak is increasing the epochs, which improves accuracy at the expense of time. Follow the links to the Keras layer docs above and try different options for Dense output, activation functions, optimization algorithms and loss functions." + ] + }, + { + "cell_type": "code", + "execution_count": 215, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/4\n", + "60000/60000 [==============================] - 5s 89us/sample - loss: 0.2581 - acc: 0.9244\n", + "Epoch 2/4\n", + "60000/60000 [==============================] - 5s 83us/sample - loss: 0.1180 - acc: 0.9644\n", + "Epoch 3/4\n", + "60000/60000 [==============================] - 5s 81us/sample - loss: 0.0867 - acc: 0.9736\n", + "Epoch 4/4\n", + "60000/60000 [==============================] - 5s 82us/sample - loss: 0.0697 - acc: 0.9785\n", + "10000/10000 [==============================] - 1s 59us/sample - loss: 0.0662 - acc: 0.9791\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.0662360069771763, 0.9791]" + ] + }, + "execution_count": 215, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import tensorflow as tf\n", + "# Disable some deprecated error messages\n", + "tf.logging.set_verbosity(tf.logging.ERROR)\n", + "\n", + "# Normalize the data to a 0.0 to 1.0 scale for faster processing\n", + "x_train, x_test = x_train / 255.0, x_test / 255.0\n", + "\n", + "model = tf.keras.models.Sequential([\n", + " tf.keras.layers.Flatten(input_shape=(28, 28)),\n", + " tf.keras.layers.Dense(256, activation=tf.nn.relu),\n", + " tf.keras.layers.Dropout(0.25),\n", + " tf.keras.layers.Dense(10, activation=tf.nn.softmax)\n", + "])\n", + " \n", + "model.compile(optimizer='adam',\n", + " loss='sparse_categorical_crossentropy',\n", + " metrics=['accuracy'])\n", + "\n", + "model.fit(x_train, y_train, epochs=4)\n", + "model.evaluate(x_test, y_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. Generate predictions for test set \n", + "Our predictions are in the form of a list of 10 floats, with probabilities for each value. We can get the prediction by picking the index of the list item with the highest probability. And we can visualize that item to verify our prediction." + ] + }, + { + "cell_type": "code", + "execution_count": 216, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5.5930052e-09 1.6970777e-15 2.4897268e-10 2.3935108e-14 7.2053798e-09\n", + " 4.4642620e-10 1.0000000e+00 8.1785776e-12 2.4993282e-10 2.6947859e-13]\n", + "6\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 216, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "predictions = model.predict(x_test)\n", + "print(predictions[88])\n", + "print(np.argmax(predictions[88]))\n", + "plt.imshow(x_test[88].reshape(28, 28), cmap=cm.Greys)" + ] + } + ], + "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 +} From 574e76d113fa58d67ac9acac98f0d97a8ecbda0c Mon Sep 17 00:00:00 2001 From: Joe James Date: Sun, 24 Feb 2019 20:52:49 -0800 Subject: [PATCH 06/75] Initial upload - nltk notebook --- NLTK/NLTK.ipynb | 665 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 665 insertions(+) create mode 100644 NLTK/NLTK.ipynb diff --git a/NLTK/NLTK.ipynb b/NLTK/NLTK.ipynb new file mode 100644 index 00000000..7c65f6a8 --- /dev/null +++ b/NLTK/NLTK.ipynb @@ -0,0 +1,665 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python NLTK Natural Language Tool Kit\n", + "## Topics covered in this video\n", + "- Exploring the NLTK corpus \n", + "- Dictionary definitions \n", + "- Punctuation and stop words \n", + "- Stemming and lemmatization \n", + "- Sentence and word tokenizers \n", + "- Parts of speech tagging \n", + "- word2vec \n", + "- Clustering and classifying\n", + "\n", + "### NLTK Setup\n", + "First you need to install the nltk library with 'pip install nltk' or some equivalent shell command. \n", + "Then you need to download the nltk corpus by running \n", + "```python \n", + "import nltk \n", + "nltk.download()```\n", + "This will open the NLTK downloader dialog window where you should just click Download All. The corpus is a large and varied body of sample documents that you'll need for this video, including dictionaries and word lists like stop words. You can uninstall it later if you have a shortage of disk space with *pip uninstall nltk*.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "260819\n", + "19317\n", + "['[', 'Moby', 'Dick', 'by', 'Herman', 'Melville', '1851', ']', 'ETYMOLOGY', '.']\n", + "['[', 'Sense', 'and', 'Sensibility', 'by', 'Jane', 'Austen', '1811', ']', 'CHAPTER']\n" + ] + } + ], + "source": [ + "import nltk\n", + "from nltk.book import *\n", + "\n", + "print(type(text1))\n", + "print(len(text1))\n", + "print(len(set(text1)))\n", + "print(text1[:10])\n", + "print(text2[:10])" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['austen-emma.txt', 'austen-persuasion.txt', 'austen-sense.txt', 'bible-kjv.txt', 'blake-poems.txt', 'bryant-stories.txt', 'burgess-busterbrown.txt', 'carroll-alice.txt', 'chesterton-ball.txt', 'chesterton-brown.txt', 'chesterton-thursday.txt', 'edgeworth-parents.txt', 'melville-moby_dick.txt', 'milton-paradise.txt', 'shakespeare-caesar.txt', 'shakespeare-hamlet.txt', 'shakespeare-macbeth.txt', 'whitman-leaves.txt']\n", + "37360\n", + "3106\n", + "['What', 'say', 'you', '?']\n", + "950\n" + ] + } + ], + "source": [ + "from nltk.corpus import gutenberg\n", + "print(gutenberg.fileids())\n", + "hamlet = gutenberg.words('shakespeare-hamlet.txt')\n", + "print(len(hamlet))\n", + "hamlet_sentences = gutenberg.sents('shakespeare-hamlet.txt')\n", + "print(len(hamlet_sentences))\n", + "print(hamlet_sentences[1024])\n", + "print(len(gutenberg.paras('shakespeare-hamlet.txt')))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get the count of a word in a document, or the context of every occurence of a word in a document." + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "26\n", + "Displaying 7 of 7 matches:\n", + "r him ,\" said I , now flying into a passion again at this unaccountable farrago\n", + " employed in the celebration of the Passion of our Lord ; though in the Vision \n", + "ce all mortal interests to that one passion ; nevertheless it may have been tha\n", + "ing with the wildness of his ruling passion , yet were by no means incapable of\n", + "it , however promissory of life and passion in the end , it is above all things\n", + "o ' s lordly chest . So have I seen Passion and Vanity stamping the living magn\n", + " Guernseyman , flying into a sudden passion . \" Oh ! keep cool -- cool ? yes , \n", + "None\n", + "Displaying 5 of 5 matches:\n", + "one ,\" said Elinor , \" who has your passion for dead leaves .\" \" No ; my feelin\n", + "r daughters , without extending the passion to her ; and Elinor had the satisfa\n", + "r , if he was to be in the greatest passion !-- and Mr . Donavan thinks just th\n", + "edness I could have borne , but her passion -- her malice -- At all events it m\n", + "ling a sacrifice to an irresistible passion , as once she had fondly flattered \n", + "None\n" + ] + } + ], + "source": [ + "print(text1.count('horse'))\n", + "print(text1.concordance('passion'))\n", + "print(text2.concordance('passion'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**FreqDist and most_common** \n", + "We can use FreqDist to find the number of occurrences of each word in the text. \n", + "By getting len(vocab) we get the number of unique words in the text (including punctuation). \n", + "And we can get the most common words easily too." + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "19317\n", + "[(',', 18713), ('the', 13721), ('.', 6862), ('of', 6536), ('and', 6024), ('a', 4569), ('to', 4542), (';', 4072), ('in', 3916), ('that', 2982), (\"'\", 2684), ('-', 2552), ('his', 2459), ('it', 2209), ('I', 2124), ('s', 1739), ('is', 1695), ('he', 1661), ('with', 1659), ('was', 1632)]\n" + ] + } + ], + "source": [ + "vocab = nltk.FreqDist(text1)\n", + "print(len(vocab))\n", + "print(vocab.most_common(20))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we got the 80 most common words, filtered only the ones with at least 3 characters, then sorted them descending by number of occurences. \n", + "A better way is to first remove all the *stop words* (see below), then get the FreqDist." + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('that', 2982), ('with', 1659), ('this', 1280), ('from', 1052), ('whale', 906), ('have', 760), ('there', 715), ('were', 680), ('which', 640), ('like', 624), ('their', 612), ('they', 586), ('some', 578), ('then', 571), ('when', 553), ('upon', 538), ('into', 520), ('ship', 507), ('more', 501), ('Ahab', 501), ('them', 471), ('what', 442), ('would', 421), ('been', 415), ('other', 412), ('over', 403)]\n" + ] + } + ], + "source": [ + "mc = sorted([w for w in vocab.most_common(80) if len(w[0]) > 3], key=lambda x: x[1], reverse=True)\n", + "print(mc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### A dispersion plot shows you where in the document a word is used. You can pass in a list of words." + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "text1.dispersion_plot(['capture', 'whale', 'life', 'death', 'kill'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Dictionary definitions\n", + "Use wordnet synsets to get word definitions and examples of usage. \n", + "The [0] is required because synsets returns a list, with an entry for each POS." + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "unmitigated.a.01 - not diminished or moderated in intensity or severity; sometimes used as an intensifier\n", + "['unmitigated suffering', 'an unmitigated horror', 'an unmitigated lie']\n" + ] + } + ], + "source": [ + "from nltk.corpus import wordnet as wn\n", + "w = wn.synsets(\"unmitigated\")[0]\n", + "print(w.name(), '-', w.definition())\n", + "print(w.examples())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Punctuation and Stop Words\n", + "Text analysis is often faster and easier if you can remove useless words. \n", + "NLTK provides a list of these stop words so it's easy to filter them out of your text prior to processing. \n", + "Here, 15% of our text is punctuation, and 40% is stop words. So we shrink the text by more than half by stripping out punctuation and stop words." + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n", + "['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', \"you're\", \"you've\", \"you'll\", \"you'd\", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', \"she's\", 'her', 'hers', 'herself', 'it', \"it's\", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', \"that'll\", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', \"don't\", 'should', \"should've\", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', \"aren't\", 'couldn', \"couldn't\", 'didn', \"didn't\", 'doesn', \"doesn't\", 'hadn', \"hadn't\", 'hasn', \"hasn't\", 'haven', \"haven't\", 'isn', \"isn't\", 'ma', 'mightn', \"mightn't\", 'mustn', \"mustn't\", 'needn', \"needn't\", 'shan', \"shan't\", 'shouldn', \"shouldn't\", 'wasn', \"wasn't\", 'weren', \"weren't\", 'won', \"won't\", 'wouldn', \"wouldn't\"]\n", + "260819\n", + "221767\n", + "122226\n" + ] + } + ], + "source": [ + "from string import punctuation\n", + "print(punctuation)\n", + "without_punct = [w for w in text1 if w not in punctuation] # this is called a list comprehension\n", + "\n", + "from nltk.corpus import stopwords\n", + "sw = stopwords.words('english')\n", + "print(sw)\n", + "without_sw = [w for w in without_punct if w not in sw] \n", + "\n", + "print(len(text1))\n", + "print(len(without_punct))\n", + "print(len(without_sw))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Stemming and Lemmatization\n", + "These term normalization algorithms strip the word endings off to reduce the number of root words for easier matching. \n", + "This is useful for search term matching. [NLTK stemming docs](https://www.nltk.org/api/nltk.stem.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "is is\n", + "are are\n", + "bought bought\n", + "buys buy\n", + "giving give\n", + "jumps jump\n", + "jumped jump\n", + "birds bird\n", + "do do\n", + "does doe\n", + "did did\n", + "doing do\n" + ] + } + ], + "source": [ + "from nltk.stem.porter import PorterStemmer\n", + "st = PorterStemmer()\n", + "words = ['is', 'are', 'bought', 'buys', 'giving', 'jumps', 'jumped', 'birds', 'do', 'does', 'did', 'doing']\n", + "for word in words:\n", + " print(word, st.stem(word))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**WordNet Lemmatizer** \n", + "The difference is that the result of stemming may not be an actual word, but lemmatization returns the root word. NLTK supports both. \n", + "You can also try the Lancaster or Snowball stemmers. The Snowball stemmer supports numerous languages: Arabic, Danish, Dutch, English, Finnish, French, German, Hungarian, Italian, Norwegian, Portuguese, Romanian, Russian, Spanish and Swedish." + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "is is\n", + "are are\n", + "bought bought\n", + "buys buy\n", + "giving giving\n", + "jumps jump\n", + "jumped jumped\n", + "birds bird\n", + "do do\n", + "does doe\n", + "did did\n", + "doing doing\n" + ] + } + ], + "source": [ + "from nltk.stem import WordNetLemmatizer\n", + "wnl = WordNetLemmatizer()\n", + "words = ['is', 'are', 'bought', 'buys', 'giving', 'jumps', 'jumped', 'birds', 'do', 'does', 'did', 'doing']\n", + "for word in words:\n", + " print(word, wnl.lemmatize(word))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sentence and Word Tokenizers\n", + "Sentence tokenizer breaks text down into a list of sentences. It's pretty good at handling punctuation and decimal numbers. \n", + "[Word tokenizer](https://www.nltk.org/api/nltk.tokenize.html) breaks a string down into a list of words and punctuation. \n", + "It is also easy to get parts of speech using nltk.pos_tag. There are different tagsets, depending on how much detail you want. I like universal." + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Hello.', 'I am Joe!', 'I like Python.', '263.5 is a big number.']\n", + "['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog', '.']\n" + ] + } + ], + "source": [ + "from nltk.tokenize import sent_tokenize, word_tokenize\n", + "s = 'Hello. I am Joe! I like Python. 263.5 is a big number.' # 4 sentences\n", + "print(sent_tokenize(s))\n", + "\n", + "w = word_tokenize('The quick brown fox jumps over the lazy dog.')\n", + "print(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parts of Speech Tagging\n", + "To break a block of text down into its parts of speech use pos_tag. \n", + "The default tagset uses 2 or 3 letter tokens that are hard for me to understand. [StackOverflow](https://stackoverflow.com/questions/15388831/what-are-all-possible-pos-tags-of-nltk) has a great decoder for the default POS tags. \n", + "The Universal tagset gives a more familiar looking tag (noun, verb, adj). \n", + "NLTK includes several other tagsets you can try." + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog', '.']\n", + "[('The', 'DT'), ('quick', 'JJ'), ('brown', 'NN'), ('fox', 'NN'), ('jumps', 'VBZ'), ('over', 'IN'), ('the', 'DT'), ('lazy', 'JJ'), ('dog', 'NN'), ('.', '.')]\n", + "[('The', 'DET'), ('quick', 'ADJ'), ('brown', 'NOUN'), ('fox', 'NOUN'), ('jumps', 'VERB'), ('over', 'ADP'), ('the', 'DET'), ('lazy', 'ADJ'), ('dog', 'NOUN'), ('.', '.')]\n" + ] + } + ], + "source": [ + "w = word_tokenize('The quick brown fox jumps over the lazy dog.')\n", + "print(w)\n", + "print(nltk.pos_tag(w))\n", + "print(nltk.pos_tag(w, tagset='universal'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Word2Vec\n", + "[Word2Vec](https://radimrehurek.com/gensim/models/word2vec.html) uses neural networks to analyze words in a corpus by using the contexts of words. \n", + "It takes as its input a large corpus of text, and maps unique words to a vector space, such that \n", + "words that share common contexts in the corpus are located in close proximity to one another in the space. \n", + "Word2Vec does NOT look at word meanings, it only finds words that are used in combination with other words. So *frying* and *pan* may have a high similarity. \n", + "You can see here the context of one word (pain) for two different corpora. \n", + "This uses the popular gensim library, which is not part of NLTK." + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('person', 0.9992861747741699), ('favourable', 0.998925507068634), ('meaning', 0.9987690448760986), ('effect', 0.9987439513206482), ('comfortable', 0.998741626739502), ('delay', 0.9987210035324097)]\n", + "[('even', 0.9980006217956543), ('moment', 0.9979783296585083), ('hence', 0.9979231357574463), ('without', 0.9979217052459717), ('separate', 0.9979064464569092), ('Now', 0.9979038238525391)]\n" + ] + } + ], + "source": [ + "from gensim.models import Word2Vec\n", + "emma_vec = Word2Vec(gutenberg.sents('austen-emma.txt'))\n", + "leaves_vec = Word2Vec(gutenberg.sents('whitman-leaves.txt'))\n", + "print(emma_vec.wv.most_similar('pain', topn=6))\n", + "print(leaves_vec.wv.most_similar('pain', topn=6))" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "30103\n", + "[('mercy', 0.9284727573394775),\n", + " ('liveth', 0.9062315821647644),\n", + " ('truth', 0.8941866159439087),\n", + " ('grace', 0.8938426375389099),\n", + " ('glory', 0.8936725854873657),\n", + " ('salvation', 0.8859732747077942),\n", + " ('hosts', 0.8839103579521179),\n", + " ('confession', 0.8837960958480835)]\n", + "[('making', 0.9873884916305542),\n", + " ('abundant', 0.9802387952804565),\n", + " ('realm', 0.98007732629776),\n", + " ('powers', 0.9798883199691772),\n", + " ('twice', 0.9775580763816833)]\n" + ] + } + ], + "source": [ + "from gensim.models import Word2Vec\n", + "from nltk.corpus import stopwords\n", + "from string import punctuation\n", + "import pprint as pp\n", + "\n", + "bible_sents = gutenberg.sents('bible-kjv.txt')\n", + "sw = stopwords.words('english')\n", + "bible = [[w.lower() for w in s if w not in punctuation and w not in sw] for s in bible_sents]\n", + "print(len(bible))\n", + "\n", + "bible_vec = Word2Vec(bible)\n", + "pp.pprint(bible_vec.wv.most_similar('god', topn=8))\n", + "pp.pprint(bible_vec.wv.most_similar('creation', topn=5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### k-Means Clustering\n", + "[Clustering](http://www.nltk.org/api/nltk.cluster.html) groups similar items together. \n", + "The K-means clusterer starts with k arbitrarily chosen means (or centroids) then assigns each vector to the cluster with the closest mean. It then recalculates the means of each cluster as the centroid of its vector members. This process repeats until the cluster memberships stabilize. [NLTK docs on this example](https://www.nltk.org/_modules/nltk/cluster/kmeans.html) \n", + "This example clusters int vectors, which you can think of as points on a plane. But you could also use clustering to cluster similar documents by vocabulary/topic." + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "k-means trial 0\n", + "iteration\n", + "iteration\n", + "Clustered: [array([2, 1]), array([1, 3]), array([4, 7]), array([6, 7])]\n", + "As: [0, 0, 1, 1]\n", + "Means: [array([1.5, 2. ]), array([5., 7.])]\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from nltk.cluster import KMeansClusterer, euclidean_distance\n", + "\n", + "vectors = [np.array(f) for f in [[2, 1], [1, 3], [4, 7], [6, 7]]]\n", + "means = [[4, 3], [5, 5]]\n", + "\n", + "clusterer = KMeansClusterer(2, euclidean_distance, initial_means=means)\n", + "clusters = clusterer.cluster(vectors, True, trace=True)\n", + "\n", + "print('Clustered:', vectors)\n", + "print('As:', clusters)\n", + "print('Means:', clusterer.means())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**k-Means Clustering, Example-2** \n", + "In this example we cluster an array of 6 points into 2 clusters. \n", + "The initial centroids are randomly chosen by the clusterer, and it does 10 iterations to regroup the clusters and recalculate centroids. " + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Clustered: [array([3, 3]), array([1, 2]), array([4, 2]), array([4, 0]), array([2, 3]), array([3, 1])]\n", + "As: [0, 0, 1, 1, 0, 1]\n", + "Means: [array([2. , 2.66666667]), array([3.66666667, 1. ])]\n", + "classify([2 2]): 0\n" + ] + } + ], + "source": [ + "vectors = [np.array(f) for f in [[3, 3], [1, 2], [4, 2], [4, 0], [2, 3], [3, 1]]]\n", + "\n", + "# test k-means using 2 means, euclidean distance, and 10 trial clustering repetitions with random seeds\n", + "clusterer = KMeansClusterer(2, euclidean_distance, repeats=10)\n", + "clusters = clusterer.cluster(vectors, True)\n", + "centroids = clusterer.means()\n", + "print('Clustered:', vectors)\n", + "print('As:', clusters)\n", + "print('Means:', centroids)\n", + "\n", + "# classify a new vector\n", + "vector = np.array([2,2])\n", + "print('classify(%s):' % vector, end=' ')\n", + "print(clusterer.classify(vector))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Plot a Chart of the Clusters in Example-2** \n", + "Make a Scatter Plot of the two clusters using matplotlib.pyplot. \n", + "We plot all the points in cluster-0 blue, and all the points in cluster-1 red. Then we plot the two centroids in orange. \n", + "I used list comprehensions to create new lists for all the x0, y0, x1 and y1 values." + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [ + { + "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", + "\n", + "x0 = np.array([x[0] for idx, x in enumerate(vectors) if clusters[idx]==0])\n", + "y0 = np.array([x[1] for idx, x in enumerate(vectors) if clusters[idx]==0])\n", + "plt.scatter(x0,y0, color='blue')\n", + "x1 = np.array([x[0] for idx, x in enumerate(vectors) if clusters[idx]==1])\n", + "y1 = np.array([x[1] for idx, x in enumerate(vectors) if clusters[idx]==1])\n", + "plt.scatter(x1,y1, color='red')\n", + "\n", + "xc = np.array([x[0] for x in centroids])\n", + "yc = np.array([x[1] for x in centroids])\n", + "plt.scatter(xc,yc, color='orange')\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 +} From a17b63d45b660910faa9aef082be2de359608b73 Mon Sep 17 00:00:00 2001 From: Joe James Date: Tue, 26 Feb 2019 13:40:54 -0800 Subject: [PATCH 07/75] Initial upload - Requests notebook --- Web Data Mining/Python Requests.ipynb | 418 ++++++++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 Web Data Mining/Python Requests.ipynb diff --git a/Web Data Mining/Python Requests.ipynb b/Web Data Mining/Python Requests.ipynb new file mode 100644 index 00000000..6b9274ec --- /dev/null +++ b/Web Data Mining/Python Requests.ipynb @@ -0,0 +1,418 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Requests\n", + "(c) 2019, Joe James.\n", + "MIT License.\n", + "\n", + "Tutorial on using the [Requests](http://docs.python-requests.org/en/master/user/quickstart/) library to access HTTP requests, GET, POST, PUT, DELETE, HEAD, OPTIONS. \n", + "This notebook also covers how to use the Python [JSON](https://docs.python.org/3/library/json.html) library to parse values out of a GET response. \n", + "If you don't have the requests library installed you can run 'pip install requests' or some equivalent command for your system in the console window. " + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [], + "source": [ + "import requests" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [], + "source": [ + "r = requests.get('https://api.github.com/events')\n", + "r = requests.post('https://httpbin.org/post', data = {'name':'Joe'})\n", + "r = requests.put('https://httpbin.org/put', data = {'name':'Joe'})\n", + "r = requests.delete('https://httpbin.org/delete')\n", + "r = requests.head('https://httpbin.org/get')\n", + "r = requests.options('https://httpbin.org/get')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### GET Requests - Passing Parameters in URLs\n", + "A URL that returns an HTTP response in JSON format is called an API endpoint. \n", + "Here's an example, https://httpbin.org/get \n", + "\n", + "With GET requests we can add parameters onto the URL to retrieve specific data. \n", + "We define the params as a dictionary, and add params=payload to the Request. \n", + "The Requests library builds the whole URL for us." + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://httpbin.org/get?key1=value1&key2=value2\n" + ] + } + ], + "source": [ + "payload = {'key1': 'value1', 'key2': 'value2'}\n", + "r = requests.get('https://httpbin.org/get', params=payload)\n", + "print(r.url)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Passing a List as a parameter** \n", + "Still use key:value pairs, with the list as the value. \n", + "You can see here all the different attributes included in an HTTP Request response." + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "URL: https://httpbin.org/get?key1=value1&key2=value2&key2=value3\n", + "ENCODING: None\n", + "STATUS_CODE: 200\n", + "HEADERS: {'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Tue, 26 Feb 2019 18:13:35 GMT', 'Server': 'nginx', 'Content-Length': '229', 'Connection': 'keep-alive'}\n", + "TEXT: {\n", + " \"args\": {\n", + " \"key1\": \"value1\", \n", + " \"key2\": [\n", + " \"value2\", \n", + " \"value3\"\n", + " ]\n", + " }, \n", + " \"headers\": {\n", + " \"Accept\": \"*/*\", \n", + " \"Accept-Encoding\": \"gzip, deflate\", \n", + " \"Host\": \"httpbin.org\", \n", + " \"User-Agent\": \"python-requests/2.21.0\"\n", + " }, \n", + " \"origin\": \"99.99.39.153, 99.99.39.153\", \n", + " \"url\": \"https://httpbin.org/get?key1=value1&key2=value2&key2=value3\"\n", + "}\n", + "\n", + "CONTENT: b'{\\n \"args\": {\\n \"key1\": \"value1\", \\n \"key2\": [\\n \"value2\", \\n \"value3\"\\n ]\\n }, \\n \"headers\": {\\n \"Accept\": \"*/*\", \\n \"Accept-Encoding\": \"gzip, deflate\", \\n \"Host\": \"httpbin.org\", \\n \"User-Agent\": \"python-requests/2.21.0\"\\n }, \\n \"origin\": \"99.99.39.153, 99.99.39.153\", \\n \"url\": \"https://httpbin.org/get?key1=value1&key2=value2&key2=value3\"\\n}\\n'\n", + "JSON: >\n" + ] + } + ], + "source": [ + "payload = {'key1': 'value1', 'key2': ['value2', 'value3']}\n", + "r = requests.get('https://httpbin.org/get', params=payload)\n", + "print('URL: ', r.url)\n", + "print('ENCODING: ', r.encoding)\n", + "print('STATUS_CODE: ', r.status_code)\n", + "print('HEADERS: ', r.headers)\n", + "print('TEXT: ', r.text)\n", + "print('CONTENT: ', r.content)\n", + "print('JSON: ', r.json)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### POST Requests\n", + "We can add parameters to a POST request in Dictionary format, but we use data=payload. \n", + "POST requests are used to upload new records to the server. \n", + "POST would typically be used to get data from a web form and submit it to the server. " + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"args\": {}, \n", + " \"data\": \"\", \n", + " \"files\": {}, \n", + " \"form\": {\n", + " \"key1\": \"value1\", \n", + " \"key2\": \"value2\"\n", + " }, \n", + " \"headers\": {\n", + " \"Accept\": \"*/*\", \n", + " \"Accept-Encoding\": \"gzip, deflate\", \n", + " \"Content-Length\": \"23\", \n", + " \"Content-Type\": \"application/x-www-form-urlencoded\", \n", + " \"Host\": \"httpbin.org\", \n", + " \"User-Agent\": \"python-requests/2.21.0\"\n", + " }, \n", + " \"json\": null, \n", + " \"origin\": \"99.99.39.153, 99.99.39.153\", \n", + " \"url\": \"https://httpbin.org/post/"\n", + "}\n", + "\n" + ] + } + ], + "source": [ + "r = requests.post('https://httpbin.org/post', data = {'name':'Joe'})\n", + "\n", + "payload = {'key1': 'value1', 'key2': 'value2'}\n", + "r = requests.post(\"https://httpbin.org/post/", data=payload)\n", + "print(r.text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using Requests to GET Currency Exchange Data\n", + "Here's a handy endpoint where we can GET foreign currency exchange rates in JSON format, https://api.exchangeratesapi.io/latest" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"rates\":{\"MXN\":21.7145,\"AUD\":1.5897,\"HKD\":8.9178,\"RON\":4.7626,\"HRK\":7.4275,\"CHF\":1.1371,\"IDR\":15917.9,\"CAD\":1.5024,\"USD\":1.1361,\"ZAR\":15.752,\"JPY\":125.93,\"BRL\":4.2574,\"HUF\":317.06,\"CZK\":25.663,\"NOK\":9.7725,\"INR\":80.853,\"PLN\":4.3282,\"ISK\":136.1,\"PHP\":59.144,\"SEK\":10.5858,\"ILS\":4.1148,\"GBP\":0.86055,\"SGD\":1.5332,\"CNY\":7.6077,\"TRY\":6.0254,\"MYR\":4.6157,\"RUB\":74.6158,\"NZD\":1.652,\"KRW\":1270.0,\"THB\":35.583,\"BGN\":1.9558,\"DKK\":7.4616},\"base\":\"EUR\",\"date\":\"2019-02-26\"}\n" + ] + } + ], + "source": [ + "url = 'https://api.exchangeratesapi.io/latest'\n", + "r = requests.get(url)\n", + "print(r.text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**It looks like the default is base:EUR, but we want exchange rates for USD, so we can pass in a parameter for base. \n", + "We can also put in any date we want.**" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"rates\":{\"MXN\":18.8315549401,\"AUD\":1.2571475116,\"HKD\":7.823572534,\"RON\":3.7694876599,\"HRK\":6.0552252179,\"CHF\":0.9610654069,\"IDR\":13307.03754989,\"CAD\":1.2432190274,\"USD\":1.0,\"JPY\":110.621487334,\"BRL\":3.1959762157,\"PHP\":50.2997474953,\"CZK\":20.7957970188,\"NOK\":7.8771686894,\"INR\":63.5175531482,\"PLN\":3.3954549157,\"MYR\":3.9560153132,\"ZAR\":12.302191089,\"ILS\":3.399609025,\"GBP\":0.7252830496,\"SGD\":1.3214140262,\"HUF\":251.6086991936,\"EUR\":0.8145312373,\"CNY\":6.4380548994,\"TRY\":3.7828459721,\"SEK\":8.0096929217,\"RUB\":56.4333306182,\"NZD\":1.3706931661,\"KRW\":1063.5660177568,\"THB\":31.9247373137,\"BGN\":1.5930601939,\"DKK\":6.0679319052},\"base\":\"USD\",\"date\":\"2018-01-15\"}\n" + ] + } + ], + "source": [ + "url = 'https://api.exchangeratesapi.io/2018-01-15'\n", + "r = requests.get(url, params={'base':'USD'})\n", + "print(r.text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Decoding JSON data\n", + "Now we have the rates in JSON format. We need to convert that to usable data. \n", + "The JSON library basically has two functions: \n", + "- json.loads( ) converts a text string into Python dict/list objects. \n", + "- json.dumps( ) converts dict/list objects into a string. \n", + "\n", + "We need to decode the JSON data into a dictionary, then get the rate for GBP, convert it to a float, and do a conversion." + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'MXN': 18.8315549401, 'AUD': 1.2571475116, 'HKD': 7.823572534, 'RON': 3.7694876599, 'HRK': 6.0552252179, 'CHF': 0.9610654069, 'IDR': 13307.03754989, 'CAD': 1.2432190274, 'USD': 1.0, 'JPY': 110.621487334, 'BRL': 3.1959762157, 'PHP': 50.2997474953, 'CZK': 20.7957970188, 'NOK': 7.8771686894, 'INR': 63.5175531482, 'PLN': 3.3954549157, 'MYR': 3.9560153132, 'ZAR': 12.302191089, 'ILS': 3.399609025, 'GBP': 0.7252830496, 'SGD': 1.3214140262, 'HUF': 251.6086991936, 'EUR': 0.8145312373, 'CNY': 6.4380548994, 'TRY': 3.7828459721, 'SEK': 8.0096929217, 'RUB': 56.4333306182, 'NZD': 1.3706931661, 'KRW': 1063.5660177568, 'THB': 31.9247373137, 'BGN': 1.5930601939, 'DKK': 6.0679319052}\n", + "0.7252830496\n", + "200USD = 145.05660992 GBP\n" + ] + } + ], + "source": [ + "rates_json = json.loads(r.text)['rates']\n", + "print(rates_json)\n", + "print(rates_json['GBP'])\n", + "gbp = float(rates_json['GBP'])\n", + "print('200USD = ', str(gbp * 200), 'GBP')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using Requests to GET Song Data\n", + "Every API has documentation on how to use it. \n", + "You can find the docs for this Song Data API [here.](https://documenter.getpostman.com/view/3719697/RzfarXB4)" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{\"id\":12,\"name\":\"Beatles\",\"year_started\":1960,\"year_quit\":1970,\"text\":\"Beatles\"},{\"id\":14,\"name\":\"Dario G\",\"year_started\":1997,\"year_quit\":null,\"text\":\"Dario G\"},{\"id\":16,\"name\":\"Fleetwood Mac\",\"year_started\":1967,\"year_quit\":null,\"text\":\"Fleetwood Mac\"},{\"id\":17,\"name\":\"Blink 182\",\"year_started\":1992,\"year_quit\":null,\"text\":\"Blink 182\"},{\"id\":18,\"name\":\"Bloc Party\",\"year_started\":2002,\"year_quit\":null,\"text\":\"Bloc Party\"},{\"id\":19,\"name\":\"The Temper Trap\",\"year_started\":2005,\"year_quit\":null,\"text\":\"The Temper Trap\"},{\"id\":20,\"name\":\"MGMT\",\"year_started\":2002,\"year_quit\":null,\"text\":\"MGMT\"},{\"id\":21,\"name\":\"Coldplay\",\"year_started\":1996,\"year_quit\":null,\"text\":\"Coldplay\"},{\"id\":22,\"name\":\"\n" + ] + } + ], + "source": [ + "url = 'https://musicdemons.com/api/v1/artist'\n", + "r = requests.get(url)\n", + "print(r.text[:700])" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"id\":21,\"name\":\"Coldplay\",\"year_started\":1996,\"year_quit\":null,\"text\":\"Coldplay\"}\n" + ] + } + ], + "source": [ + "url = 'https://musicdemons.com/api/v1/artist/21'\n", + "r = requests.get(url)\n", + "print(r.text)" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"id\":21,\"name\":\"Coldplay\",\"year_started\":1996,\"year_quit\":null,\"text\":\"Coldplay\",\"songs\":[{\"id\":1,\"title\":\"Something Just Like This\",\"released\":\"02\\/22\\/2017\",\"text\":\"Something Just Like This\",\"youtube_id\":\"FM7MFYoylVs\",\"pivot\":{\"artist_id\":21,\"song_id\":1},\"subject\":{\"id\":226,\"subjectable_id\":1,\"subjectable_type\":\"App\\\\Entities\\\\MusicDemons\\\\Song\"}},{\"id\":11,\"title\":\"Hymn For The Weekend\",\"released\":\"01\\/25\\/2016\",\"text\":\"Hymn For The Weekend\",\"youtube_id\":\"YykjpeuMNEk\",\"pivot\":{\"artist_id\":21,\"song_id\":11},\"subject\":{\"id\":233,\"subjectable_id\":11,\"subjectable_type\":\"App\\\\Entities\\\\MusicDemons\\\\Song\"}},{\"id\":78,\"title\":\"Sky Full Of Stars\",\"released\":\"05\\/02\\/2014\",\"text\":\"Sky Full Of Stars\",\n" + ] + } + ], + "source": [ + "url = 'https://musicdemons.com/api/v1/artist/21'\n", + "headers = {'with': 'songs,members'}\n", + "r = requests.get(url, headers=headers)\n", + "print(r.text[:700])" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coldplay\n", + "Something Just Like This\n", + "Hymn For The Weekend\n", + "Sky Full Of Stars\n", + "Fix You\n", + "Brothers & Sisters\n", + "Shiver\n", + "The Scientist\n", + "Yellow\n", + "Trouble\n", + "Every Teardrop Is a Waterfall\n", + "Life in Technicolor ii\n", + "Adventure Of A Lifetime\n", + "Magic\n", + "The Hardest Part\n", + "Viva la Vida\n", + "1.36\n", + "42\n", + "A Head Full of Dreams\n", + "A Hopeful Transmission\n", + "A Message\n", + "A Rush of Blood to the Head\n", + "Princess of China\n" + ] + } + ], + "source": [ + "import json\n", + "text_json = json.loads(r.text)\n", + "print(text_json['name'])\n", + "for song in text_json['songs']:\n", + " print(song['title'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tips on breaking down JSON \n", + "To get data out of a JSON object, which is a combination of lists and dictionaries, \n", + "just remember for lists you need a numerical index, and for key-value pairs you need a text index. \n", + "So if the object looks like this, {\"cars\":[\"id\":1,\"model\":\"Camry\"... you can access the model of the first car with text['cars'][0]['model']" + ] + }, + { + "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 +} From b6cb971723d164512f0d8fb2b53bc60f94075ebc Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 4 Mar 2019 16:52:26 -0800 Subject: [PATCH 08/75] Initial upload_Numpy Jupyter Notebook and data.txt --- Numpy/Python Numpy Intro.ipynb | 558 +++++++++++++++++++++++++++++++++ Numpy/data.txt | 14 +- 2 files changed, 565 insertions(+), 7 deletions(-) create mode 100644 Numpy/Python Numpy Intro.ipynb diff --git a/Numpy/Python Numpy Intro.ipynb b/Numpy/Python Numpy Intro.ipynb new file mode 100644 index 00000000..637478b8 --- /dev/null +++ b/Numpy/Python Numpy Intro.ipynb @@ -0,0 +1,558 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Numpy Intro\n", + "An introduction to the [Python Numpy](http://www.numpy.org/) numerical python library. \n", + "The core data structure behind Numpy is the n-dimensional [Numpy Array](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html). It is 3x to 10x faster and more memory efficient than Python's lists because, similar to Java arrays, it uses contiguous blocks of memory, and all elements are the same data type so there is no type checking at runtime. The Numpy library also includes many built-in code-saving mathematical functions that can be performed on an entire array or any slice of an array with a single line of code (ie. no for loops). \n", + "Numpy n-dimensional arrays are also sometimes referred to as nd-arrays.\n", + "\n", + "**Install Numpy** using pip: pip install numpy\n", + "The convention for importing numpy is *import numpy as np*.\n", + "\n", + "import numpy as np\n", + "\n", + "### Creating a Numpy Array\n", + "There are MANY ways to instantiate a numpy array. I covered the most common ones below. [Docs here cover more constructors](https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.array-creation.html).\n", + "- Pass in a list to the array() constructor\n", + "- Use the arange function, similar to the range function but used for Numpy arrays. Uses arguments, (start, stop+1, step).\n", + "- Use linspace to create an array of n equally spaced values. Uses arguments (start, stop, number of items).\n", + "- Create an array empty, full of ones or zeros, or full of any fill value. Uses argument (shape) in the form of a tuple. \n", + "\n", + "You can pass in dtype as an optional argument for any of these. This is especially useful if you want to limit memory usage for a very large array of small integers because int8 and int16 use much less space than the default int32." + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 1 3 5 7 9 11]\n", + "[ 1 3 5 7 9 11]\n", + "[5. 5.25 5.5 5.75 6. 6.25 6.5 6.75 7. 7.25 7.5 7.75 8. ]\n", + "[[0. 0.]\n", + " [0. 0.]\n", + " [0. 0.]\n", + " [0. 0.]]\n", + "[[1 1 1]\n", + " [1 1 1]]\n", + "[88 88 88 88 88 88]\n", + "[25 30 35 40]\n", + "[[ 1 3 5]\n", + " [ 7 9 11]]\n", + "[[0 0 0]\n", + " [0 0 0]]\n" + ] + } + ], + "source": [ + "a = np.array([1,3,5,7,9,11])\n", + "print(a)\n", + "\n", + "a = np.arange(1, 12, 2) # (start, stop, step)\n", + "print(a)\n", + "\n", + "a = np.linspace(5, 8, 13) # (start, stop, number of items)\n", + "print(a)\n", + "\n", + "a = np.zeros((4, 2))\n", + "print(a)\n", + "\n", + "a = np.ones((2, 3), dtype=np.int16)\n", + "print(a)\n", + "\n", + "a = np.full((6,), 88)\n", + "print(a)\n", + "\n", + "a = np.fromstring('25 30 35 40', dtype=np.int, sep=' ')\n", + "print(a)\n", + "\n", + "a = np.array([[1,3,5],[7,9,11]])\n", + "print(a)\n", + "\n", + "b = np.zeros_like(a) # _like gives you a new array in the same shape as the argument.\n", + "print(b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Numpy Array Attributes\n", + "Get size (number of items), shape (dimensions), itemsize(bytes of memory for each item), and dtype (numpy data type). \n", + "See how many bytes of memory space the whole array uses from the product of size and itemsize. See [complete list of attributes and methods](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n", + "(2, 3)\n", + "2\n", + "4\n", + "int32\n", + "24\n" + ] + } + ], + "source": [ + "print(a.size)\n", + "print(a.shape)\n", + "print(a.ndim)\n", + "print(a.itemsize)\n", + "print(a.dtype)\n", + "print(a.nbytes) # same as a.size * a.itemsize" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Indexing and Slicing\n", + "Use square brackets to get any item of an array by index. Multi-dimensional arrays can use multiple square brackets.\n", + "\n", + "There are three arguments for slicing arrays, all are optional: [start:stop:step]. \n", + " If start is left blank it defaults to 0. If stop is left blank it defaults to the end of the array. Step defaults to 1." + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 1 3 5]\n", + " [ 7 9 11]]\n", + "[ 7 9 11]\n", + "5\n", + "[]\n", + "[[1 3 5]]\n", + "[[ 7 9 11]]\n", + "[[3]\n", + " [9]]\n" + ] + } + ], + "source": [ + "print(a)\n", + "print(a[1])\n", + "print(a[0][2])\n", + "print(b[2:4])\n", + "\n", + "print(a[:1])\n", + "print(a[1:3:2])\n", + "print(a[:, 1:2]) # all elements on dimension 0, only element 1 on dimension 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reshape, Swap Axes, Flatten\n", + "See full list of [array manipulation routines](https://docs.scipy.org/doc/numpy/reference/routines.array-manipulation.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[-9 -8 -7]\n", + " [-6 -5 -4]]\n", + "[[-9 -6]\n", + " [-8 -5]\n", + " [-7 -4]]\n", + "[-9 -6 -8 -5 -7 -4]\n" + ] + } + ], + "source": [ + "c = np.arange(-9, -3,).reshape(2,3)\n", + "print(c)\n", + "\n", + "c = c.swapaxes(0,1)\n", + "print(c)\n", + "\n", + "c = c.flatten()\n", + "print(c)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Use dtype to Save Space\n", + "Default data types (int32 and float64) are memory hogs. If you don't need the higher precision you can save a lot of memory space and improve speed of operations by using smaller data types. For large data sets this makes a big difference." + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "int32 \n", + "400\n", + "int8 \n", + "100\n" + ] + } + ], + "source": [ + "d = np.arange(0,100)\n", + "print(d.dtype, type(d[1]))\n", + "print(d.nbytes)\n", + "\n", + "d = np.arange(0,100, dtype='int8')\n", + "print(d.dtype, type(d[1]))\n", + "print(d.nbytes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### UpCasting, Rounding, Print Formatting\n", + "Data type of all Items is upcast to the most precise element. " + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "float64\n", + "[[1.57 2. 3. ]\n", + " [4. 5. 6. ]]\n", + "[[1.57 2. 3. ]\n", + " [4. 5. 6. ]]\n" + ] + } + ], + "source": [ + "e = np.array([(1.566666,2,3), (4,5,6)])\n", + "print(e.dtype)\n", + "\n", + "e = e.round(4)\n", + "print(e)\n", + "\n", + "np.set_printoptions(precision=2, suppress=True) # show 2 decimal places, suppress scientific notation\n", + "print(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Numpy Data Types Available\n", + "uint is unsigned int, for positive numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'complex': [, ],\n", + " 'float': [,\n", + " ,\n", + " ],\n", + " 'int': [,\n", + " ,\n", + " ,\n", + " ,\n", + " ],\n", + " 'others': [,\n", + " ,\n", + " ,\n", + " ,\n", + " ],\n", + " 'uint': [,\n", + " ,\n", + " ,\n", + " ,\n", + " ]}\n" + ] + } + ], + "source": [ + "import pprint as pp\n", + "pp.pprint(np.sctypes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reading and Writing to Files\n", + "Can use [loadtxt](https://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html#numpy.loadtxt), or [genfromtxt](https://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html#numpy.genfromtxt) to load data to load an entire file into an array at once. Genfromtxt is more fault tolerant. \n", + "Use [savetxt](https://docs.scipy.org/doc/numpy/reference/generated/numpy.savetxt.html#numpy.savetxt) to write an array to file." + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[9 3 8 7 6 1 0 4 2 5]\n", + " [1 7 4 9 2 6 8 3 5 0]\n", + " [4 8 3 9 5 7 2 6 0 1]\n", + " [1 7 4 2 5 9 6 8 0 3]\n", + " [0 7 5 2 8 6 3 4 1 9]\n", + " [5 9 1 4 7 0 3 6 8 2]]\n", + "int32\n" + ] + } + ], + "source": [ + "f = np.loadtxt('data.txt', skiprows=1, delimiter=',', dtype=np.int32)\n", + "print(f)\n", + "print(f.dtype)\n", + "\n", + "np.savetxt('data2.txt', f, delimiter=';', fmt='%d', header='a;b;c;d;e;f;g;h;i;j', comments='')" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[9 3 8 7 6 1 0 4 2 5]\n", + " [1 7 4 9 2 6 8 3 5 0]\n", + " [4 8 3 9 5 7 2 6 0 1]\n", + " [1 7 4 2 5 9 6 8 0 3]\n", + " [0 7 5 2 8 6 3 4 1 9]\n", + " [5 9 1 4 7 0 3 6 8 2]]\n" + ] + } + ], + "source": [ + "g = np.genfromtxt('data.txt', skip_header=1, delimiter=',', dtype=np.int32)\n", + "print(g)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Mathematical Functions\n", + "Numpy has an extensive list of [math and scientific functions](https://docs.scipy.org/doc/numpy/reference/routines.html). \n", + "The best part is that you don't have to iterate. You can apply an operation to the entire array or a slice of an array at once." + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ True False True True True False False False False True]\n", + " [False True False True False True True False True False]\n", + " [False True False True True True False True False False]\n", + " [False True False False True True True True False False]\n", + " [False True True False True True False False False True]\n", + " [ True True False False True False False True True False]]\n", + "[[80 8 63 48 35 0 -1 15 3 24]\n", + " [ 0 48 15 80 3 35 63 8 24 -1]\n", + " [15 63 8 80 24 48 3 35 -1 0]\n", + " [ 0 48 15 3 24 80 35 63 -1 8]\n", + " [-1 48 24 3 63 35 8 15 0 80]\n", + " [24 80 0 15 48 -1 8 35 63 3]]\n" + ] + } + ], + "source": [ + "print(g > 4)\n", + "print(g ** 2 - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "9\n", + "270\n", + "4.5\n", + "8.25\n", + "2.8722813232690143\n", + "[45 45 45 45 45 45]\n", + "[0 3 1 2 2 0 0 3 0 0]\n", + "6\n", + "0\n", + "[[6 5 8 1 7 9 4 3 2 0]\n", + " [9 0 4 7 2 8 5 1 6 3]\n", + " [8 9 6 2 0 4 7 5 1 3]\n", + " [8 0 3 9 2 4 6 1 7 5]\n", + " [0 8 3 6 7 2 5 1 4 9]\n", + " [5 2 9 6 3 0 7 4 8 1]]\n" + ] + } + ], + "source": [ + "print(g.min())\n", + "print(g.max())\n", + "print(g.sum())\n", + "print(g.mean())\n", + "print(g.var()) # variance\n", + "print(g.std()) # standard deviation\n", + "\n", + "print(g.sum(axis=1))\n", + "print(g.min(axis=0))\n", + "\n", + "print(g.argmin()) # index of min element\n", + "print(g.argmax()) # index of max element\n", + "print(g.argsort()) # returns array of indices that would put the array in sorted order" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Column Operations\n", + "Apply functions only to specific columns by slicing, or create a new array from the columns you want, then work on them. \n", + "But Beware that creating a new pointer to the same data can screw up your data if you're not careful." + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[8]\n", + " [4]\n", + " [3]\n", + " [4]\n", + " [5]\n", + " [1]]\n", + "8\n", + "298.607881119482\n", + "[[ 9 3 8 70000 6 1 0 4 2 5]\n", + " [ 1 7 4 90000 2 6 8 3 5 0]\n", + " [ 4 8 3 90000 5 7 2 6 0 1]\n", + " [ 1 7 4 20000 5 9 6 8 0 3]\n", + " [ 0 7 5 20000 8 6 3 4 1 9]\n", + " [ 5 9 1 40000 7 0 3 6 8 2]]\n" + ] + } + ], + "source": [ + "print(g[:, 2:3])\n", + "print(g[:, 2:3].max())\n", + "\n", + "col3 = g[:, 3:4] # not a copy, just a pointer to a slice of g\n", + "print(col3.std())\n", + "\n", + "col3 *= 100 # Beware: this is applied to g data\n", + "print(g)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Numpy Random Functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.set_printoptions(precision=5, suppress=True) # show 5 decimal places, suppress scientific notation\n", + "h = np.random.random(6)\n", + "print(h)\n", + "\n", + "h = np.random.randint(10, 99, 8) # (low, high inclusive, size)\n", + "print(h)\n", + "\n", + "np.random.shuffle(h) # in-place shuffle\n", + "print(h)\n", + "\n", + "print(np.random.choice(h))\n", + "\n", + "h.sort() # in-place sort\n", + "print(h)" + ] + }, + { + "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.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Numpy/data.txt b/Numpy/data.txt index 9156b512..d3e350d6 100644 --- a/Numpy/data.txt +++ b/Numpy/data.txt @@ -1,7 +1,7 @@ -a, b, c, d, e, f, g, h, i, j -9, 3, 8, 7, 6, 1, 0, 4, 2, 5 -1, 7, 4, 9, 2, 6, 8, 3, 5, 0 -4, 8, 3, 9, 5, 7, 2, 6, 0, 1 -1, 7, 4, 2, 5, 9, 6, 8, 0, 3 -0, 7, 5, 2, 8, 6, 3, 4, 1, 9 -5, 9, 1, 4, 7, 0, 3, 6, 8, 2 \ No newline at end of file +a,b,c,d,e,f,g,h,i,j +9,3,8,7,6,1,0,4,2,5 +1,7,4,9,2,6,8,3,5,0 +4,8,3,9,5,7,2,6,0,1 +1,7,4,2,5,9,6,8,0,3 +0,7,5,2,8,6,3,4,1,9 +5,9,1,4,7,0,3,6,8,2 From 16fc60d5f278a8daf6c81b610cd66df738b698bb Mon Sep 17 00:00:00 2001 From: Joe James Date: Sat, 9 Mar 2019 19:18:08 -0800 Subject: [PATCH 09/75] Python Lambda Functions Jupyter initial upload --- .../Python Lambda Functions.ipynb | 364 ++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 Numpy/Lambda Functions/Python Lambda Functions.ipynb diff --git a/Numpy/Lambda Functions/Python Lambda Functions.ipynb b/Numpy/Lambda Functions/Python Lambda Functions.ipynb new file mode 100644 index 00000000..61c11f0c --- /dev/null +++ b/Numpy/Lambda Functions/Python Lambda Functions.ipynb @@ -0,0 +1,364 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Lambda Functions\n", + "Anonymous, single-use, or throw-away functions. \n", + "**lambda arguments : expression** \n", + "Here are some single-argument lambdas:" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "12\n" + ] + } + ], + "source": [ + "add5 = lambda x: x + 5\n", + "print(add5(7))" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "64\n" + ] + } + ], + "source": [ + "square = lambda x: x * x\n", + "print(square(8))" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n" + ] + } + ], + "source": [ + "get_tens = lambda p: int(p/10)%10\n", + "print(get_tens(749))\n", + "print(get_tens(836.21))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lambdas as an argument in other functions** \n", + "One of the most popular uses for lambda functions is as an argument inside sort, or filter functions. \n", + "### Sorting a List of Tuples using Lambda" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('carrots', 1.1), ('peaches', 2.45), ('eggs', 5.25), ('honey', 9.7)]\n" + ] + } + ], + "source": [ + "list1 = [('eggs', 5.25), ('honey', 9.70), ('carrots', 1.10), ('peaches', 2.45)]\n", + "list1.sort(key = lambda x: x[1])\n", + "print(list1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sorting a List of Dictionaries using Lambda" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'make': 'Tesla', 'model': 'X', 'year': 1999},\n", + " {'make': 'Mercedes', 'model': 'C350E', 'year': 2008},\n", + " {'make': 'Ford', 'model': 'Focus', 'year': 2013}]\n" + ] + } + ], + "source": [ + "import pprint as pp\n", + "list1 = [{'make':'Ford', 'model':'Focus', 'year':2013}, {'make':'Tesla', 'model':'X', 'year':1999}, {'make':'Mercedes', 'model':'C350E', 'year':2008}]\n", + "list2 = sorted(list1, key = lambda x: x['year'])\n", + "pp.pprint(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Filtering a List of Integers using Lambda" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6]\n" + ] + } + ], + "source": [ + "list1 = [1, 2, 3, 4, 5, 6]\n", + "list2 = list(filter(lambda x: x%2 == 0, list1))\n", + "print(list2)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 3, 5]\n" + ] + } + ], + "source": [ + "odds = lambda x: x%2 == 1\n", + "list1 = [1, 2, 3, 4, 5, 6]\n", + "list2 = list(filter(odds, list1))\n", + "print(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lambda Function on a List using Map\n", + "Python's map function applies the lambda to every element in the list." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 4, 9, 16, 25, 36]\n" + ] + } + ], + "source": [ + "list1 = [1, 2, 3, 4, 5, 6]\n", + "list2 = list(map(lambda x: x ** 2, list1))\n", + "print(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lambda Conditionals\n", + "**lambda args: a if boolean_expression else b** " + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "starts_with_J = lambda x: True if x.startswith('J') else False\n", + "print(starts_with_J('Joey'))" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "and\n" + ] + } + ], + "source": [ + "wordb4 = lambda s, w: s.split()[s.split().index(w)-1] if w in s else None\n", + "sentence = 'Four score and seven years ago'\n", + "print(wordb4(sentence, 'seven'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lambdas on DataTime Objects\n", + "You sometimes want to get just the year, month, date or time for comparision. \n", + "This would typically be most useful as a parameter in sort or filter functions." + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2019-03-07 19:36:58.442863\n", + "2019\n" + ] + } + ], + "source": [ + "import datetime\n", + "\n", + "now = datetime.datetime.now()\n", + "print(now)\n", + "year = lambda x: x.year\n", + "print(year(now))" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4096\n", + "125\n" + ] + } + ], + "source": [ + "def do_something(f, val):\n", + " return f(val)\n", + "\n", + "func = lambda x: x**3\n", + "print(func(16))\n", + "print(do_something(func, 5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extreme Lambdas\n", + "This is probably a stretch -- you shouldn't be trying to do this much with Lambdas. \n", + "Some things are better done in a regular function. But this shows what's possible with Lambdas." + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "True\n", + "False\n", + "False\n", + "True\n", + "-1\n", + "-21.67 \n" + ] + } + ], + "source": [ + "isnum = lambda q: q.replace('.','',1).isdigit()\n", + "print(isnum('25983'))\n", + "print(isnum('3.1415'))\n", + "print(isnum('T57'))\n", + "print(isnum('-16'))\n", + "\n", + "is_num = lambda r: isnum(r[1:]) if r[0]=='-' else isnum(r)\n", + "print(is_num('-16.4'))\n", + "\n", + "tonum = lambda s: float(s) if is_num(s) else -1\n", + "print(tonum('30y'))\n", + "print(tonum('-21.67'), type(tonum('-21.67')))" + ] + } + ], + "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 +} From 7a191a168288e1230b9f40998112770e1fe11413 Mon Sep 17 00:00:00 2001 From: Joe James Date: Sat, 9 Mar 2019 19:20:09 -0800 Subject: [PATCH 10/75] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6b87efd..6f0d92be 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,4 @@ Feel free to post any comments on my YouTube channel. Joe James. Fremont, California. -Copyright (C) 2015-2018, Joe James +Copyright (C) 2015-2019, Joe James From e74d1d6fc5f3e1f2e0d752b1eb757d871706559b Mon Sep 17 00:00:00 2001 From: Joe James Date: Sat, 9 Mar 2019 19:22:44 -0800 Subject: [PATCH 11/75] Python Lambda Functions Jupyter nb initial upload --- .../Python Lambda Functions.ipynb | 364 ++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 Lambda Functions/Python Lambda Functions.ipynb diff --git a/Lambda Functions/Python Lambda Functions.ipynb b/Lambda Functions/Python Lambda Functions.ipynb new file mode 100644 index 00000000..61c11f0c --- /dev/null +++ b/Lambda Functions/Python Lambda Functions.ipynb @@ -0,0 +1,364 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Lambda Functions\n", + "Anonymous, single-use, or throw-away functions. \n", + "**lambda arguments : expression** \n", + "Here are some single-argument lambdas:" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "12\n" + ] + } + ], + "source": [ + "add5 = lambda x: x + 5\n", + "print(add5(7))" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "64\n" + ] + } + ], + "source": [ + "square = lambda x: x * x\n", + "print(square(8))" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n", + "3\n" + ] + } + ], + "source": [ + "get_tens = lambda p: int(p/10)%10\n", + "print(get_tens(749))\n", + "print(get_tens(836.21))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lambdas as an argument in other functions** \n", + "One of the most popular uses for lambda functions is as an argument inside sort, or filter functions. \n", + "### Sorting a List of Tuples using Lambda" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('carrots', 1.1), ('peaches', 2.45), ('eggs', 5.25), ('honey', 9.7)]\n" + ] + } + ], + "source": [ + "list1 = [('eggs', 5.25), ('honey', 9.70), ('carrots', 1.10), ('peaches', 2.45)]\n", + "list1.sort(key = lambda x: x[1])\n", + "print(list1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sorting a List of Dictionaries using Lambda" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'make': 'Tesla', 'model': 'X', 'year': 1999},\n", + " {'make': 'Mercedes', 'model': 'C350E', 'year': 2008},\n", + " {'make': 'Ford', 'model': 'Focus', 'year': 2013}]\n" + ] + } + ], + "source": [ + "import pprint as pp\n", + "list1 = [{'make':'Ford', 'model':'Focus', 'year':2013}, {'make':'Tesla', 'model':'X', 'year':1999}, {'make':'Mercedes', 'model':'C350E', 'year':2008}]\n", + "list2 = sorted(list1, key = lambda x: x['year'])\n", + "pp.pprint(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Filtering a List of Integers using Lambda" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 4, 6]\n" + ] + } + ], + "source": [ + "list1 = [1, 2, 3, 4, 5, 6]\n", + "list2 = list(filter(lambda x: x%2 == 0, list1))\n", + "print(list2)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 3, 5]\n" + ] + } + ], + "source": [ + "odds = lambda x: x%2 == 1\n", + "list1 = [1, 2, 3, 4, 5, 6]\n", + "list2 = list(filter(odds, list1))\n", + "print(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lambda Function on a List using Map\n", + "Python's map function applies the lambda to every element in the list." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 4, 9, 16, 25, 36]\n" + ] + } + ], + "source": [ + "list1 = [1, 2, 3, 4, 5, 6]\n", + "list2 = list(map(lambda x: x ** 2, list1))\n", + "print(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lambda Conditionals\n", + "**lambda args: a if boolean_expression else b** " + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "starts_with_J = lambda x: True if x.startswith('J') else False\n", + "print(starts_with_J('Joey'))" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "and\n" + ] + } + ], + "source": [ + "wordb4 = lambda s, w: s.split()[s.split().index(w)-1] if w in s else None\n", + "sentence = 'Four score and seven years ago'\n", + "print(wordb4(sentence, 'seven'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lambdas on DataTime Objects\n", + "You sometimes want to get just the year, month, date or time for comparision. \n", + "This would typically be most useful as a parameter in sort or filter functions." + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2019-03-07 19:36:58.442863\n", + "2019\n" + ] + } + ], + "source": [ + "import datetime\n", + "\n", + "now = datetime.datetime.now()\n", + "print(now)\n", + "year = lambda x: x.year\n", + "print(year(now))" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4096\n", + "125\n" + ] + } + ], + "source": [ + "def do_something(f, val):\n", + " return f(val)\n", + "\n", + "func = lambda x: x**3\n", + "print(func(16))\n", + "print(do_something(func, 5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extreme Lambdas\n", + "This is probably a stretch -- you shouldn't be trying to do this much with Lambdas. \n", + "Some things are better done in a regular function. But this shows what's possible with Lambdas." + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "True\n", + "False\n", + "False\n", + "True\n", + "-1\n", + "-21.67 \n" + ] + } + ], + "source": [ + "isnum = lambda q: q.replace('.','',1).isdigit()\n", + "print(isnum('25983'))\n", + "print(isnum('3.1415'))\n", + "print(isnum('T57'))\n", + "print(isnum('-16'))\n", + "\n", + "is_num = lambda r: isnum(r[1:]) if r[0]=='-' else isnum(r)\n", + "print(is_num('-16.4'))\n", + "\n", + "tonum = lambda s: float(s) if is_num(s) else -1\n", + "print(tonum('30y'))\n", + "print(tonum('-21.67'), type(tonum('-21.67')))" + ] + } + ], + "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 +} From 3785f2d0dde0af17e8b0f694fa22cb4b02cc20de Mon Sep 17 00:00:00 2001 From: Joe James Date: Sat, 9 Mar 2019 19:26:30 -0800 Subject: [PATCH 12/75] Delete Python Lambda Functions.ipynb --- .../Python Lambda Functions.ipynb | 364 ------------------ 1 file changed, 364 deletions(-) delete mode 100644 Numpy/Lambda Functions/Python Lambda Functions.ipynb diff --git a/Numpy/Lambda Functions/Python Lambda Functions.ipynb b/Numpy/Lambda Functions/Python Lambda Functions.ipynb deleted file mode 100644 index 61c11f0c..00000000 --- a/Numpy/Lambda Functions/Python Lambda Functions.ipynb +++ /dev/null @@ -1,364 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Python Lambda Functions\n", - "Anonymous, single-use, or throw-away functions. \n", - "**lambda arguments : expression** \n", - "Here are some single-argument lambdas:" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "12\n" - ] - } - ], - "source": [ - "add5 = lambda x: x + 5\n", - "print(add5(7))" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "64\n" - ] - } - ], - "source": [ - "square = lambda x: x * x\n", - "print(square(8))" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4\n", - "3\n" - ] - } - ], - "source": [ - "get_tens = lambda p: int(p/10)%10\n", - "print(get_tens(749))\n", - "print(get_tens(836.21))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Lambdas as an argument in other functions** \n", - "One of the most popular uses for lambda functions is as an argument inside sort, or filter functions. \n", - "### Sorting a List of Tuples using Lambda" - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[('carrots', 1.1), ('peaches', 2.45), ('eggs', 5.25), ('honey', 9.7)]\n" - ] - } - ], - "source": [ - "list1 = [('eggs', 5.25), ('honey', 9.70), ('carrots', 1.10), ('peaches', 2.45)]\n", - "list1.sort(key = lambda x: x[1])\n", - "print(list1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sorting a List of Dictionaries using Lambda" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[{'make': 'Tesla', 'model': 'X', 'year': 1999},\n", - " {'make': 'Mercedes', 'model': 'C350E', 'year': 2008},\n", - " {'make': 'Ford', 'model': 'Focus', 'year': 2013}]\n" - ] - } - ], - "source": [ - "import pprint as pp\n", - "list1 = [{'make':'Ford', 'model':'Focus', 'year':2013}, {'make':'Tesla', 'model':'X', 'year':1999}, {'make':'Mercedes', 'model':'C350E', 'year':2008}]\n", - "list2 = sorted(list1, key = lambda x: x['year'])\n", - "pp.pprint(list2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Filtering a List of Integers using Lambda" - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2, 4, 6]\n" - ] - } - ], - "source": [ - "list1 = [1, 2, 3, 4, 5, 6]\n", - "list2 = list(filter(lambda x: x%2 == 0, list1))\n", - "print(list2)" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 3, 5]\n" - ] - } - ], - "source": [ - "odds = lambda x: x%2 == 1\n", - "list1 = [1, 2, 3, 4, 5, 6]\n", - "list2 = list(filter(odds, list1))\n", - "print(list2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Lambda Function on a List using Map\n", - "Python's map function applies the lambda to every element in the list." - ] - }, - { - "cell_type": "code", - "execution_count": 74, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 4, 9, 16, 25, 36]\n" - ] - } - ], - "source": [ - "list1 = [1, 2, 3, 4, 5, 6]\n", - "list2 = list(map(lambda x: x ** 2, list1))\n", - "print(list2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Lambda Conditionals\n", - "**lambda args: a if boolean_expression else b** " - ] - }, - { - "cell_type": "code", - "execution_count": 70, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "starts_with_J = lambda x: True if x.startswith('J') else False\n", - "print(starts_with_J('Joey'))" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "and\n" - ] - } - ], - "source": [ - "wordb4 = lambda s, w: s.split()[s.split().index(w)-1] if w in s else None\n", - "sentence = 'Four score and seven years ago'\n", - "print(wordb4(sentence, 'seven'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Lambdas on DataTime Objects\n", - "You sometimes want to get just the year, month, date or time for comparision. \n", - "This would typically be most useful as a parameter in sort or filter functions." - ] - }, - { - "cell_type": "code", - "execution_count": 82, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2019-03-07 19:36:58.442863\n", - "2019\n" - ] - } - ], - "source": [ - "import datetime\n", - "\n", - "now = datetime.datetime.now()\n", - "print(now)\n", - "year = lambda x: x.year\n", - "print(year(now))" - ] - }, - { - "cell_type": "code", - "execution_count": 79, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4096\n", - "125\n" - ] - } - ], - "source": [ - "def do_something(f, val):\n", - " return f(val)\n", - "\n", - "func = lambda x: x**3\n", - "print(func(16))\n", - "print(do_something(func, 5))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Extreme Lambdas\n", - "This is probably a stretch -- you shouldn't be trying to do this much with Lambdas. \n", - "Some things are better done in a regular function. But this shows what's possible with Lambdas." - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "True\n", - "False\n", - "False\n", - "True\n", - "-1\n", - "-21.67 \n" - ] - } - ], - "source": [ - "isnum = lambda q: q.replace('.','',1).isdigit()\n", - "print(isnum('25983'))\n", - "print(isnum('3.1415'))\n", - "print(isnum('T57'))\n", - "print(isnum('-16'))\n", - "\n", - "is_num = lambda r: isnum(r[1:]) if r[0]=='-' else isnum(r)\n", - "print(is_num('-16.4'))\n", - "\n", - "tonum = lambda s: float(s) if is_num(s) else -1\n", - "print(tonum('30y'))\n", - "print(tonum('-21.67'), type(tonum('-21.67')))" - ] - } - ], - "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 -} From 51354d1dd4a362a33aaa044e158ac8c2eb51c923 Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 11 Mar 2019 19:42:12 -0700 Subject: [PATCH 13/75] Initial Upload - Datasets --- Datasets.txt | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Datasets.txt diff --git a/Datasets.txt b/Datasets.txt new file mode 100644 index 00000000..ce44cedb --- /dev/null +++ b/Datasets.txt @@ -0,0 +1,75 @@ +Data.gov +NOAA - https://www.ncdc.noaa.gov/cdo-web/ + atmospheric, ocean +Bureau of Labor Statistics - https://www.bls.gov/data/ + employment, inflation +US Census Data - https://www.census.gov/data.html + demographics, income, geo, time series +Bureau of Economic Analysis - http://www.bea.gov/data/gdp/gross-domestic-product + GDP, corporate profits, savings rates +Federal Reserve - https://fred.stlouisfed.org/ + curency, interest rates, payroll +Quandl - https://www.quandl.com/ + financial and economic + +Data.gov.uk +UK Dataservice - https://www.ukdataservice.ac.uk + Census data and much more +WorldBank - https://datacatalog.worldbank.org + census, demographics, geographic, health, income, GDP +IMF - https://www.imf.org/en/Data + economic, currency, finance, commodities, time series +OpenData.go.ke + Kenya govt data on agriculture, education, water, health, finance, … +https://data.world/ +Open Data for Africa - http://dataportal.opendataforafrica.org/ + agriculture, energy, environment, industry, … +Kaggle - https://www.kaggle.com/datasets + A huge variety of different datasets +Amazon Reviews - https://snap.stanford.edu/data/web-Amazon.html + 35M product reviews from 6.6M users +GroupLens - https://grouplens.org/datasets/movielens/ + 20M movie ratings +Yelp Reviews - https://www.yelp.com/dataset + 6.7M reviews, pictures, businesses +IMDB Reviews - http://ai.stanford.edu/~amaas/data/sentiment/ + 25k Movie reviews +Twitter Sentiment 140 - http://help.sentiment140.com/for-students/ + 160k Tweets +Airbnb - http://insideairbnb.com/get-the-data.html + A TON of data by geo +UCI ML Datasets - http://mlr.cs.umass.edu/ml/ + iris, wine, abalone, heart disease, poker hands, …. +Enron Email dataset - http://www.cs.cmu.edu/~enron/ + 500k emails from 150 people + From 2001 energy scandal. See the movie: The Smartest Guys in the Room. +Spambase - https://archive.ics.uci.edu/ml/datasets/Spambase + Emails +Jeopardy Questions - https://www.reddit.com/r/datasets/comments/1uyd0t/200000_jeopardy_questions_in_a_json_file/ + 200k Questions and answers in json +Gutenberg Ebooks - http://www.gutenberg.org/wiki/Gutenberg:Offline_Catalogs + Large collection of books + +IMAGES +ImageNet - http://image-net.org + 14M images of objects +Google - https://ai.googleblog.com/2016/09/introducing-open-images-dataset.html + 9M image URLs with labels +Microsoft Coco - http://cocodataset.org + 330k images, most labeled +Labelled Faces in the Wild - http://vis-www.cs.umass.edu/lfw/ + 13k face images with names +Stanford Dogs - http://vision.stanford.edu/aditya86/ImageNetDogs/ + 120 dog breeds, 20k images + +AUTONOMOUS CARS +Berkeley DeepDrive - https://bdd-data.berkeley.edu/ + Massive dataset including 100k videos with 1100 hours of hd driving +Belgian Traffic Signs - http://www.vision.ee.ethz.ch/~timofter/traffic_signs/ + 10k images +Bosch Small Traffic Signals - https://hci.iwr.uni-heidelberg.de/node/6132 + 5k training and 8k test images +WPI Traffic Light, Pedestrian, Lane-Keeping - http://computing.wpi.edu/dataset.html + 30GB of training and test data from Worcester, Mass +UCSD Lisa - http://cvrr.ucsd.edu/LISA/datasets.html + Vehicle detection, traffic signals From 56793e3780c99863e1d5215b9604109d74ff6209 Mon Sep 17 00:00:00 2001 From: Joe James Date: Thu, 14 Mar 2019 19:23:31 -0700 Subject: [PATCH 14/75] Happy Pi Day - calculating Pi --- Happy Pi Day.ipynb | 105 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Happy Pi Day.ipynb diff --git a/Happy Pi Day.ipynb b/Happy Pi Day.ipynb new file mode 100644 index 00000000..fd0c8e51 --- /dev/null +++ b/Happy Pi Day.ipynb @@ -0,0 +1,105 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Happy Pi Day!\n", + "\n", + "### Two Ways to Calculate Pi: \n", + "Real pi = 3.14159265359\n", + "\n", + "### 1. percentage of unit square random points that lie in unit circle\n", + "This method is only as good as our random number generator. And with number of iterations the accuracy improves, up to about 1 million." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.1419916\n" + ] + } + ], + "source": [ + "import random\n", + "in_square = in_circle = pi = 0\n", + "\n", + "for i in range(10000000):\n", + " x = random.random()\n", + " y = random.random()\n", + " dist = (x*x + y*y) ** 0.5\n", + "\n", + " in_square += 1\n", + " if dist <= 1.0:\n", + " in_circle += 1\n", + " \n", + "pi = 4 * in_circle / in_square\n", + "print(pi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. using series addition\n", + "pi = 4/1 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + 4/13 - 4/15 ... \n", + "This method is the more accurate of the two, and is faster. Its accuracy only depends on the size of n." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.1415924535897797\n" + ] + } + ], + "source": [ + "pi = 0.0\n", + "for i in range(1, 10000000, 4):\n", + " pi += 4/i\n", + " pi -= 4/(i+2)\n", + "print(pi)" + ] + }, + { + "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 +} From c289db10558858be576f8e6d5af1316a288fdb10 Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 18 Mar 2019 20:14:08 -0700 Subject: [PATCH 15/75] BeautifulSoup Jupyter notebook upload --- ... BeautifulSoup Web Scraping Tutorial.ipynb | 514 ++++++++++++++++++ 1 file changed, 514 insertions(+) create mode 100644 Web Data Mining/Python BeautifulSoup Web Scraping Tutorial.ipynb diff --git a/Web Data Mining/Python BeautifulSoup Web Scraping Tutorial.ipynb b/Web Data Mining/Python BeautifulSoup Web Scraping Tutorial.ipynb new file mode 100644 index 00000000..f7d55aa9 --- /dev/null +++ b/Web Data Mining/Python BeautifulSoup Web Scraping Tutorial.ipynb @@ -0,0 +1,514 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python BeautifulSoup Web Scraping Tutorial\n", + "Learn to scrape data from the web using the Python BeautifulSoup bs4 library. \n", + "BeautifulSoup makes it easy to parse useful data out of an HTML page. \n", + "First install the bs4 library on your system by running at the command line, \n", + "*pip install beautifulsoup4* or *easy_install beautifulsoup4* (or bs4) \n", + "See [BeautifulSoup official documentation](https://www.crummy.com/software/BeautifulSoup/bs4/doc/) for the complete set of functions.\n", + "\n", + "### Import requests so we can fetch the html content of the webpage\n", + "You can see our example page has about 28k characters." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "28556\n" + ] + } + ], + "source": [ + "import requests\n", + "r = requests.get('https://www.usclimatedata.com/climate/united-states/us')\n", + "print(len(r.text))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import BeautifulSoup, and convert your HTML into a bs4 object\n", + "Now we can access specific HTML tags on the page using dot, just like a JSON object." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Climate United States - normals and averages\n", + "Climate United States - normals and averages\n" + ] + } + ], + "source": [ + "from bs4 import BeautifulSoup\n", + "soup = BeautifulSoup(r.text)\n", + "print(soup.title)\n", + "print(soup.title.string)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Drill into the bs4 object to access page contents\n", + "soup.p will give you the contents of the first paragraph tag on the page. \n", + "soup.a gives you anchors / links on the page. \n", + "Get contents of an attribute inside an HTML tag using square brackets and perentheses. \n", + "Use .parent to get the parent object, and .next_sibling to get the next peer object. \n", + "**Use your browser's *inspect element* feature to find the tag for the data you want.**" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "

You are here: United States

\n", + "You are here: United States\n", + "\n", + "\"US\n", + "\n", + "US Climate Data on Facebook\n", + "\n", + "\n" + ] + } + ], + "source": [ + "print(soup.p)\n", + "print(soup.p.text)\n", + "print(soup.a)\n", + "print(soup.a['title'])\n", + "print()\n", + "print(soup.p.parent)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prettify() is handy for formatted printing \n", + "but note this works only on bs4 objects, not on strings, dicts or lists. For those you need to import pprint." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n" + ] + } + ], + "source": [ + "print(soup.p.parent.prettify())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### We need all the state links on this page\n", + "First we find_all anchor tags, and print out the href attribute, which is the actual link url. \n", + "But we see the result includes some links we don't want, so we need to filter those out." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://www.facebook.com/yourweatherservice/n", + "https://twitter.com/usclimatedata/n", + "http://www.usclimatedata.com/n", + "/climate/united-states/us\n", + "#summary\n", + "/climate/united-states/us\n", + "#\n", + "#\n", + "/climate/alabama/united-states/3170\n", + "/climate/kentucky/united-states/3187\n", + "/climate/north-dakota/united-states/3204\n", + "/climate/alaska/united-states/3171\n", + "/climate/louisiana/united-states/3188\n", + "/climate/ohio/united-states/3205\n", + "/climate/arizona/united-states/3172\n", + "/climate/maine/united-states/3189\n", + "/climate/oklahoma/united-states/3206\n", + "/climate/arkansas/united-states/3173\n", + "/climate/maryland/united-states/1872\n", + "/climate/oregon/united-states/3207\n", + "/climate/california/united-states/3174\n", + "/climate/massachusetts/united-states/3191\n", + "/climate/pennsylvania/united-states/3208\n", + "/climate/colorado/united-states/3175\n", + "/climate/michigan/united-states/3192\n", + "/climate/rhode-island/united-states/3209\n", + "/climate/connecticut/united-states/3176\n", + "/climate/minnesota/united-states/3193\n", + "/climate/south-carolina/united-states/3210\n", + "/climate/delaware/united-states/3177\n", + "/climate/mississippi/united-states/3194\n", + "/climate/south-dakota/united-states/3211\n", + "/climate/district-of-columbia/united-states/3178\n", + "/climate/missouri/united-states/3195\n", + "/climate/tennessee/united-states/3212\n", + "/climate/florida/united-states/3179\n", + "/climate/montana/united-states/919\n", + "/climate/texas/united-states/3213\n", + "/climate/georgia/united-states/3180\n", + "/climate/nebraska/united-states/3197\n", + "/climate/utah/united-states/3214\n", + "/climate/hawaii/united-states/3181\n", + "/climate/nevada/united-states/3198\n", + "/climate/vermont/united-states/3215\n", + "/climate/idaho/united-states/3182\n", + "/climate/new-hampshire/united-states/3199\n", + "/climate/virginia/united-states/3216\n", + "/climate/illinois/united-states/3183\n", + "/climate/new-jersey/united-states/3200\n", + "/climate/washington/united-states/3217\n", + "/climate/indiana/united-states/3184\n", + "/climate/new-mexico/united-states/3201\n", + "/climate/west-virginia/united-states/3218\n", + "/climate/iowa/united-states/3185\n", + "/climate/new-york/united-states/3202\n", + "/climate/wisconsin/united-states/3219\n", + "/climate/kansas/united-states/3186\n", + "/climate/north-carolina/united-states/3203\n", + "/climate/wyoming/united-states/3220\n", + "https://www.yourweatherservice.com/n", + "https://www.climatedata.eu/n", + "https://www.weernetwerk.nl/n", + "/about-us.php\n", + "/disclaimer.php\n", + "/cookies.php\n" + ] + } + ], + "source": [ + "for link in soup.find_all('a'):\n", + " print(link.get('href'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Filter urls using string functions\n", + "We just add an *if* to check conditions, then add the good ones to a list. \n", + "In the end we get 51 state links, including Washington DC." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "51\n" + ] + } + ], + "source": [ + "base_url = 'https://www.usclimatedata.com/'\n", + "state_links = []\n", + "for link in soup.find_all('a'):\n", + " url = link.get('href')\n", + " if url and '/climate/' in url and '/climate/united-states/us' not in url:\n", + " state_links.append(url)\n", + "print(len(state_links))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Test getting the data for one state\n", + "then print the title for that page." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Climate Ohio - temperature, rainfall and average\n" + ] + } + ], + "source": [ + "r = requests.get(base_url + state_links[5])\n", + "soup = BeautifulSoup(r.text)\n", + "print(soup.title.string)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The data we need is in *tr* tags\n", + "But look, there are 58 tr tags on the page, and we only want 2 of them - the *Average high* rows." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "58\n" + ] + } + ], + "source": [ + "rows = soup.find_all('tr')\n", + "print(len(rows))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Filter rows, and add temp data to a list\n", + "We use a list comprehension to filter the rows. \n", + "Then we have only 2 rows left. \n", + "We iterate through those 2 rows, and add all the temps from data cells (td) into a list." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "['36', '40', '52', '63', '73', '82', '85', '84', '77', '65', '52', '41']\n" + ] + } + ], + "source": [ + "rows = [row for row in rows if 'Average high' in str(row)]\n", + "print(len(rows))\n", + "\n", + "high_temps = []\n", + "for row in rows:\n", + " tds = row.find_all('td')\n", + " for i in range(1,7):\n", + " high_temps.append(tds[i].text)\n", + "print(high_temps)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get the name of the State\n", + "First attempt we just split the title string into a list, and grab the second word. \n", + "But that doesn't work for 2-word states like New York and North Carolina. \n", + "So instead we slice the string from first blank to the hyphen. " + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wyoming\n", + "Wyoming\n" + ] + } + ], + "source": [ + "state = soup.title.string.split()[1]\n", + "print(state)\n", + "s = soup.title.string\n", + "state = s[s.find(' '):s.find('-')].strip()\n", + "print(state)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add state name and temp list to the data dictionary\n", + "For a single state, this is what our scraped data looks like. \n", + "In this example we only got monthly highs by state, but you could drill into cities, and could get lows and precipitation. " + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Ohio': ['36', '40', '52', '63', '73', '82', '85', '84', '77', '65', '52', '41']}\n" + ] + } + ], + "source": [ + "data = {}\n", + "data[state] = high_temps\n", + "print(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Put it all together and iterate 51 states\n", + "We loop through our 51-state list, and get high temp data for each state, and add it to the data dict. \n", + "This combines all our work above into a single for loop. \n", + "The result is a dict with 51 states and a list of monthly highs for each." + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'Alabama': ['57', '62', '70', '77', '84', '90', '92', '92', '87', '78', '69', '60'], 'Kentucky': ['40', '45', '55', '66', '75', '83', '87', '86', '79', '68', '55', '44'], 'North Dakota': ['23', '28', '40', '57', '68', '77', '85', '83', '72', '58', '40', '26'], 'Alaska': ['23', '27', '34', '44', '56', '63', '65', '64', '55', '40', '28', '25'], 'Louisiana': ['62', '65', '72', '78', '85', '89', '91', '91', '87', '80', '72', '64'], 'Ohio': ['36', '40', '52', '63', '73', '82', '85', '84', '77', '65', '52', '41'], 'Arizona': ['67', '71', '77', '85', '95', '104', '106', '104', '100', '89', '76', '66'], 'Maine': ['28', '32', '40', '53', '65', '74', '79', '78', '70', '57', '45', '33'], 'Oklahoma': ['50', '55', '63', '72', '80', '88', '94', '93', '85', '73', '62', '51'], 'Arkansas': ['51', '55', '64', '73', '81', '89', '92', '93', '86', '75', '63', '52'], 'Maryland': ['42', '46', '54', '65', '75', '85', '89', '87', '80', '68', '58', '46'], 'Oregon': ['48', '52', '56', '61', '68', '74', '82', '82', '77', '64', '53', '46'], 'California': ['54', '60', '65', '71', '80', '87', '92', '91', '87', '78', '64', '54'], 'Massachusetts': ['36', '39', '45', '56', '66', '76', '81', '80', '72', '61', '51', '41'], 'Pennsylvania': ['40', '44', '53', '64', '74', '83', '87', '85', '78', '67', '56', '45'], 'Colorado': ['45', '46', '54', '61', '72', '82', '90', '88', '79', '66', '52', '45'], 'Michigan': ['30', '33', '44', '58', '69', '78', '82', '80', '73', '60', '47', '34'], 'Rhode Island': ['37', '40', '48', '59', '68', '78', '83', '81', '74', '63', '53', '42'], 'Connecticut': ['37', '40', '47', '58', '68', '77', '82', '81', '74', '63', '53', '42'], 'Minnesota': ['26', '31', '43', '58', '71', '80', '85', '82', '73', '59', '42', '29'], 'South Carolina': ['56', '60', '68', '76', '84', '90', '93', '91', '85', '76', '67', '58'], 'Delaware': ['43', '47', '55', '66', '75', '83', '87', '85', '79', '69', '58', '47'], 'Mississippi': ['56', '60', '69', '76', '83', '89', '92', '92', '87', '77', '67', '58'], 'South Dakota': ['22', '27', '39', '57', '69', '78', '84', '82', '72', '58', '39', '25'], 'District of Columbia': ['42', '44', '53', '64', '75', '83', '87', '84', '78', '67', '55', '45'], 'Missouri': ['40', '45', '56', '67', '75', '83', '88', '88', '80', '69', '56', '43'], 'Tennessee': ['50', '55', '64', '73', '81', '89', '92', '91', '85', '74', '63', '52'], 'Florida': ['64', '67', '74', '80', '87', '91', '92', '92', '88', '81', '73', '65'], 'Montana': ['33', '39', '48', '58', '67', '76', '86', '85', '73', '59', '43', '32'], 'Texas': ['62', '65', '72', '80', '87', '92', '96', '97', '91', '82', '71', '63'], 'Georgia': ['52', '57', '64', '72', '81', '86', '90', '88', '82', '73', '64', '54'], 'Nebraska': ['32', '37', '50', '63', '73', '84', '88', '86', '77', '64', '48', '36'], 'Utah': ['38', '44', '53', '61', '71', '82', '90', '89', '78', '65', '50', '40'], 'Hawaii': ['80', '80', '81', '83', '85', '87', '88', '89', '89', '87', '84', '81'], 'Nevada': ['45', '50', '57', '63', '71', '81', '90', '88', '80', '68', '54', '45'], 'Vermont': ['27', '31', '40', '55', '67', '76', '81', '79', '70', '57', '46', '33'], 'Idaho': ['38', '45', '55', '62', '72', '81', '91', '90', '79', '65', '48', '38'], 'New Hampshire': ['31', '35', '44', '57', '69', '77', '82', '81', '73', '60', '48', '36'], 'Virginia': ['47', '51', '60', '70', '78', '86', '90', '88', '81', '71', '61', '51'], 'Illinois': ['32', '36', '46', '59', '70', '81', '84', '82', '75', '63', '48', '36'], 'New Jersey': ['39', '42', '51', '62', '72', '82', '86', '84', '77', '65', '55', '44'], 'Washington': ['47', '50', '54', '58', '65', '70', '76', '76', '71', '60', '51', '46'], 'Indiana': ['35', '40', '51', '63', '73', '82', '85', '83', '77', '65', '52', '39'], 'New Mexico': ['44', '48', '56', '65', '74', '83', '86', '83', '78', '67', '53', '43'], 'West Virginia': ['42', '47', '56', '68', '75', '82', '85', '84', '78', '68', '57', '46'], 'Iowa': ['31', '36', '49', '62', '72', '82', '86', '84', '76', '63', '48', '34'], 'New York': ['39', '42', '50', '60', '71', '79', '85', '83', '76', '65', '54', '44'], 'Wisconsin': ['29', '33', '42', '54', '65', '75', '80', '78', '71', '59', '46', '33'], 'Kansas': ['40', '45', '56', '67', '76', '85', '89', '89', '80', '68', '55', '42'], 'North Carolina': ['51', '55', '63', '72', '79', '86', '89', '87', '81', '72', '62', '53'], 'Wyoming': ['40', '40', '47', '55', '65', '75', '83', '81', '72', '59', '47', '38']}\n" + ] + } + ], + "source": [ + "data = {}\n", + "for state_link in state_links:\n", + " url = base_url + state_link\n", + " r = requests.get(base_url + state_link)\n", + " soup = BeautifulSoup(r.text)\n", + " rows = soup.find_all('tr')\n", + " rows = [row for row in rows if 'Average high' in str(row)]\n", + " high_temps = []\n", + " for row in rows:\n", + " tds = row.find_all('td')\n", + " for i in range(1,7):\n", + " high_temps.append(tds[i].text)\n", + " s = soup.title.string\n", + " state = s[s.find(' '):s.find('-')].strip()\n", + " data[state] = high_temps\n", + "print(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Save to CSV file\n", + "Lastly, we might want to write all this data to a CSV file. \n", + "Here's a quick easy way to do that." + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [], + "source": [ + "import csv\n", + "\n", + "with open('high_temps.csv','w') as f:\n", + " w = csv.writer(f)\n", + " w.writerows(data.items())" + ] + } + ], + "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 +} From 4230ef2751fd9a3fdc07963410706b26b7512a32 Mon Sep 17 00:00:00 2001 From: Abdelrahman Ahmed Date: Wed, 17 Apr 2019 14:27:05 +0200 Subject: [PATCH 16/75] updated add_neighbor and add_edge method so that the graph is weighted --- graph_adjacency-list.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 From e3b3d1963980bbf85b4c3ce375b3482623d02171 Mon Sep 17 00:00:00 2001 From: tomas2310328 Date: Wed, 17 Apr 2019 14:45:34 +0200 Subject: [PATCH 17/75] Adding Keys function to return all values in hashtable --- HashMap.py | 93 +++++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/HashMap.py b/HashMap.py index 445509c5..c5808e00 100644 --- a/HashMap.py +++ b/HashMap.py @@ -1,55 +1,62 @@ # Hash Map class HashMap: - def __init__(self): - self.size = 6 - self.map = [None] * self.size + def __init__(self): + self.size = 6 + self.map = [None] * self.size - def _get_hash(self, key): - hash = 0 - for char in str(key): - hash += ord(char) - return hash % self.size + def _get_hash(self, key): + hash = 0 + for char in str(key): + hash += ord(char) + return hash % self.size - def add(self, key, value): - key_hash = self._get_hash(key) - key_value = [key, value] + def add(self, key, value): + key_hash = self._get_hash(key) + key_value = [key, value] - if self.map[key_hash] is None: - self.map[key_hash] = list([key_value]) - return True - else: - for pair in self.map[key_hash]: - if pair[0] == key: - pair[1] = value - return True - self.map[key_hash].append(key_value) - return True + if self.map[key_hash] is None: + self.map[key_hash] = list([key_value]) + return True + else: + for pair in self.map[key_hash]: + if pair[0] == key: + pair[1] = value + return True + self.map[key_hash].append(key_value) + return True - def get(self, key): - key_hash = self._get_hash(key) - if self.map[key_hash] is not None: - for pair in self.map[key_hash]: - if pair[0] == key: - return pair[1] - return None + def get(self, key): + key_hash = self._get_hash(key) + if self.map[key_hash] is not None: + for pair in self.map[key_hash]: + if pair[0] == key: + return pair[1] + return None - def delete(self, key): - key_hash = self._get_hash(key) + def delete(self, key): + key_hash = self._get_hash(key) - if self.map[key_hash] is None: - return False - for i in range (0, len(self.map[key_hash])): - if self.map[key_hash][i][0] == key: - self.map[key_hash].pop(i) - return True - return False + if self.map[key_hash] is None: + return False + for i in range (0, len(self.map[key_hash])): + if self.map[key_hash][i][0] == key: + self.map[key_hash].pop(i) + return True + return False + + def keys(self): + arr = [] + for i in range(0, len(self.map)): + if self.map[i]: + arr.append(self.map[i][0]) + return arr - def print(self): - print('---PHONEBOOK----') - for item in self.map: - if item is not None: - print(str(item)) + def print(self): + print('---PHONEBOOK----') + for item in self.map: + if item is not None: + print(str(item)) h = HashMap() h.add('Bob', '567-8888') @@ -64,4 +71,4 @@ def print(self): h.delete('Bob') h.print() print('Ming: ' + h.get('Ming')) - \ No newline at end of file +print(h.keys()) From 8098344f23ff7b3790f566db00913c77ea087ff1 Mon Sep 17 00:00:00 2001 From: tomas2310328 Date: Fri, 26 Apr 2019 20:07:29 +0200 Subject: [PATCH 18/75] Queues implementaion --- Queues implementaion.py | 73 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Queues implementaion.py diff --git a/Queues implementaion.py b/Queues implementaion.py new file mode 100644 index 00000000..da9bad1a --- /dev/null +++ b/Queues implementaion.py @@ -0,0 +1,73 @@ + +# 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()) From 7bf677341359514d9611fa41599bef3b10a264cf Mon Sep 17 00:00:00 2001 From: Manthan Gupta <42516515+Manthan109@users.noreply.github.com> Date: Tue, 1 Oct 2019 20:56:50 +0530 Subject: [PATCH 19/75] Added comments --- BinaryToDecimal.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) 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))) From 38f05bd2f07002f05cdec65b966426dcf21e48ec Mon Sep 17 00:00:00 2001 From: Abhishek garg <33170757+abhi01274@users.noreply.github.com> Date: Sun, 20 Oct 2019 15:41:00 +0530 Subject: [PATCH 20/75] Update Primes.py --- Primes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) From a7681007299c90dd26a9d64ce33ecb8922ce461f Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 4 May 2020 17:51:56 -0700 Subject: [PATCH 21/75] Add files via upload --- Strings/Using Python Strings.ipynb | 518 +++++++++++++++++++++++++++++ Strings/bands.txt | 38 +++ 2 files changed, 556 insertions(+) create mode 100644 Strings/Using Python Strings.ipynb create mode 100644 Strings/bands.txt 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 From efc50c69c1bde794d5ca1b812b0544f2a0fb0a3c Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 11 May 2020 19:15:44 -0700 Subject: [PATCH 22/75] Add string formatting notebook file --- String Formatting.ipynb | 444 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 444 insertions(+) create mode 100644 String Formatting.ipynb 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 +} From 81ff2ea134bfaf5c6ec541b499457ddf728fecf8 Mon Sep 17 00:00:00 2001 From: Joe James Date: Tue, 12 May 2020 09:34:36 -0700 Subject: [PATCH 23/75] Added Unpacking variables notebook file --- Unpacking Variables.ipynb | 360 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 Unpacking Variables.ipynb 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 +} From 4842f730320bae8ace4012eb517acb2c22d2da62 Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 13 May 2020 15:51:56 -0700 Subject: [PATCH 24/75] Added Python Random Number Module notebook --- Python Random Numbers Module.ipynb | 450 +++++++++++++++++++++++++++++ 1 file changed, 450 insertions(+) create mode 100644 Python Random Numbers Module.ipynb 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 +} From d195cd976b22a31b72692c18bd4f89d721065bc6 Mon Sep 17 00:00:00 2001 From: Joe James Date: Sun, 17 May 2020 10:43:09 -0700 Subject: [PATCH 25/75] Upload Python Bisect Jupyter notebook --- Python Bisect.ipynb | 267 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 Python Bisect.ipynb 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 +} From 916ef1a2893678ddcb90c69b206b29342dd24490 Mon Sep 17 00:00:00 2001 From: Joe James Date: Tue, 19 May 2020 15:27:09 -0700 Subject: [PATCH 26/75] upload Generators notebook --- Python Generators.ipynb | 224 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 Python Generators.ipynb 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 +} From a073c629bc57706872daffbf7c321c310f810d5f Mon Sep 17 00:00:00 2001 From: ChelseyOSU <50436670+ChelseyOSU@users.noreply.github.com> Date: Fri, 22 May 2020 01:31:09 -0700 Subject: [PATCH 27/75] Fix bug The current code would fail when remove the root element in a tree where right subtree only have right child. # 17 # 0 20 # -5 5 25 Current code would produce a result with duplicate elements # 20 # 0 20 # -5 5 25 Trick is to move one the assignment to root value to the bottom --- Trees/bst.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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() From b1828a7d0117ac2c910df827047f196482095eeb Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 25 May 2020 17:45:08 -0700 Subject: [PATCH 28/75] Initial upload --- Python List Iteration.ipynb | 197 +++++++++++++++++++ Python Set Comprehensions.ipynb | 331 ++++++++++++++++++++++++++++++++ 2 files changed, 528 insertions(+) create mode 100644 Python List Iteration.ipynb create mode 100644 Python Set Comprehensions.ipynb diff --git a/Python List Iteration.ipynb b/Python List Iteration.ipynb new file mode 100644 index 00000000..d680f54f --- /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 great if 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 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 +} From 0d97aa6a0be7938571078ddc0c35938fecbdce97 Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 25 May 2020 22:15:53 -0700 Subject: [PATCH 29/75] Stack queue heap file upload --- Stacks, Queues & Heaps.ipynb | 346 +++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 Stacks, Queues & Heaps.ipynb 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 +} From 1d0b24eff0aa445b906750d070d6233fa32fc721 Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 27 May 2020 10:01:14 -0700 Subject: [PATCH 30/75] added import json statement --- Web Data Mining/Python Requests.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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" ] }, { From b038e432cd2bd352a29dfa8b7df7d6481ccb0bee Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 27 May 2020 12:31:59 -0700 Subject: [PATCH 31/75] Revised QuickSort code, in Jupyter nb --- Sorting Algorithms/Python QuickSort.ipynb | 140 ++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 Sorting Algorithms/Python QuickSort.ipynb 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 +} From a52176b2bbc4ed5ab2ae644c545d6ed4869eddce Mon Sep 17 00:00:00 2001 From: Joe James Date: Tue, 9 Jun 2020 13:41:55 -0700 Subject: [PATCH 32/75] Add Pandas IO and Time Series notebooks --- Pandas/Python Pandas Input-Output.ipynb | 762 ++++++++++++++++ Pandas/Python Pandas Time Series Data.ipynb | 962 ++++++++++++++++++++ 2 files changed, 1724 insertions(+) create mode 100644 Pandas/Python Pandas Input-Output.ipynb create mode 100644 Pandas/Python Pandas Time Series Data.ipynb 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..1152cd3e --- /dev/null +++ b/Pandas/Python Pandas Time Series Data.ipynb @@ -0,0 +1,962 @@ +{ + "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": 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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \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
2020-06-070.816153
2020-06-140.142715
2020-06-210.883367
2020-06-280.042243
2020-07-050.902994
2020-07-120.122903
2020-07-190.883686
2020-07-260.599879
2020-08-020.585071
2020-08-090.487260
2020-08-160.577816
2020-08-230.217873
2020-08-300.642893
2020-09-060.269524
2020-09-130.681086
2020-09-200.066728
2020-09-270.192068
2020-10-040.430084
2020-10-110.673437
2020-10-180.216691
2020-10-250.172302
2020-11-010.034461
2020-11-080.764077
2020-11-150.166790
2020-11-220.379369
2020-11-290.026259
2020-12-060.215560
2020-12-130.912649
2020-12-200.752434
2020-12-270.129831
2021-01-030.307117
2021-01-100.119653
2021-01-170.385201
2021-01-240.219277
2021-01-310.962418
2021-02-070.265013
2021-02-140.178213
2021-02-210.833785
2021-02-280.668348
2021-03-070.826616
2021-03-140.345981
2021-03-210.619586
2021-03-280.362562
2021-04-040.765329
2021-04-110.800720
2021-04-180.156365
2021-04-250.988019
2021-05-020.587013
2021-05-090.709290
2021-05-160.862771
2021-05-230.475769
2021-05-300.860615
\n", + "
" + ], + "text/plain": [ + " 0\n", + "2020-06-07 0.816153\n", + "2020-06-14 0.142715\n", + "2020-06-21 0.883367\n", + "2020-06-28 0.042243\n", + "2020-07-05 0.902994\n", + "2020-07-12 0.122903\n", + "2020-07-19 0.883686\n", + "2020-07-26 0.599879\n", + "2020-08-02 0.585071\n", + "2020-08-09 0.487260\n", + "2020-08-16 0.577816\n", + "2020-08-23 0.217873\n", + "2020-08-30 0.642893\n", + "2020-09-06 0.269524\n", + "2020-09-13 0.681086\n", + "2020-09-20 0.066728\n", + "2020-09-27 0.192068\n", + "2020-10-04 0.430084\n", + "2020-10-11 0.673437\n", + "2020-10-18 0.216691\n", + "2020-10-25 0.172302\n", + "2020-11-01 0.034461\n", + "2020-11-08 0.764077\n", + "2020-11-15 0.166790\n", + "2020-11-22 0.379369\n", + "2020-11-29 0.026259\n", + "2020-12-06 0.215560\n", + "2020-12-13 0.912649\n", + "2020-12-20 0.752434\n", + "2020-12-27 0.129831\n", + "2021-01-03 0.307117\n", + "2021-01-10 0.119653\n", + "2021-01-17 0.385201\n", + "2021-01-24 0.219277\n", + "2021-01-31 0.962418\n", + "2021-02-07 0.265013\n", + "2021-02-14 0.178213\n", + "2021-02-21 0.833785\n", + "2021-02-28 0.668348\n", + "2021-03-07 0.826616\n", + "2021-03-14 0.345981\n", + "2021-03-21 0.619586\n", + "2021-03-28 0.362562\n", + "2021-04-04 0.765329\n", + "2021-04-11 0.800720\n", + "2021-04-18 0.156365\n", + "2021-04-25 0.988019\n", + "2021-05-02 0.587013\n", + "2021-05-09 0.709290\n", + "2021-05-16 0.862771\n", + "2021-05-23 0.475769\n", + "2021-05-30 0.860615" + ] + }, + "execution_count": 6, + "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" + ] + }, + { + "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": 9, + "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": 9, + "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.loc[:'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": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1998 10 10 0.4173998814595933\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": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0 1998-10-10 00:00:00\n", + "1 0.4174\n", + "Name: 5, dtype: object" + ] + }, + "execution_count": 11, + "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.loc[5]" + ] + }, + { + "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 +} From c48285101b74831e4e2cc61f17623e454a58db99 Mon Sep 17 00:00:00 2001 From: Joe James Date: Fri, 12 Jun 2020 09:59:37 -0700 Subject: [PATCH 33/75] Adding Data files --- Pandas/Python Pandas Time Series Data.ipynb | 424 ++++++++------------ Pandas/file01.csv | 8 + Pandas/outfile.csv | 4 + Pandas/outjson.txt | 1 + Pandas/pivot.csv | 2 + 5 files changed, 174 insertions(+), 265 deletions(-) create mode 100644 Pandas/file01.csv create mode 100644 Pandas/outfile.csv create mode 100644 Pandas/outjson.txt create mode 100644 Pandas/pivot.csv diff --git a/Pandas/Python Pandas Time Series Data.ipynb b/Pandas/Python Pandas Time Series Data.ipynb index 1152cd3e..3db1b4b4 100644 --- a/Pandas/Python Pandas Time Series Data.ipynb +++ b/Pandas/Python Pandas Time Series Data.ipynb @@ -217,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 61, "metadata": {}, "outputs": [ { @@ -246,212 +246,16 @@ " \n", " \n", " \n", - " 2020-06-07\n", - " 0.816153\n", - " \n", - " \n", - " 2020-06-14\n", - " 0.142715\n", - " \n", - " \n", - " 2020-06-21\n", - " 0.883367\n", - " \n", - " \n", - " 2020-06-28\n", - " 0.042243\n", - " \n", - " \n", - " 2020-07-05\n", - " 0.902994\n", - " \n", - " \n", " 2020-07-12\n", - " 0.122903\n", + " 0.581691\n", " \n", " \n", " 2020-07-19\n", - " 0.883686\n", + " 0.611492\n", " \n", " \n", " 2020-07-26\n", - " 0.599879\n", - " \n", - " \n", - " 2020-08-02\n", - " 0.585071\n", - " \n", - " \n", - " 2020-08-09\n", - " 0.487260\n", - " \n", - " \n", - " 2020-08-16\n", - " 0.577816\n", - " \n", - " \n", - " 2020-08-23\n", - " 0.217873\n", - " \n", - " \n", - " 2020-08-30\n", - " 0.642893\n", - " \n", - " \n", - " 2020-09-06\n", - " 0.269524\n", - " \n", - " \n", - " 2020-09-13\n", - " 0.681086\n", - " \n", - " \n", - " 2020-09-20\n", - " 0.066728\n", - " \n", - " \n", - " 2020-09-27\n", - " 0.192068\n", - " \n", - " \n", - " 2020-10-04\n", - " 0.430084\n", - " \n", - " \n", - " 2020-10-11\n", - " 0.673437\n", - " \n", - " \n", - " 2020-10-18\n", - " 0.216691\n", - " \n", - " \n", - " 2020-10-25\n", - " 0.172302\n", - " \n", - " \n", - " 2020-11-01\n", - " 0.034461\n", - " \n", - " \n", - " 2020-11-08\n", - " 0.764077\n", - " \n", - " \n", - " 2020-11-15\n", - " 0.166790\n", - " \n", - " \n", - " 2020-11-22\n", - " 0.379369\n", - " \n", - " \n", - " 2020-11-29\n", - " 0.026259\n", - " \n", - " \n", - " 2020-12-06\n", - " 0.215560\n", - " \n", - " \n", - " 2020-12-13\n", - " 0.912649\n", - " \n", - " \n", - " 2020-12-20\n", - " 0.752434\n", - " \n", - " \n", - " 2020-12-27\n", - " 0.129831\n", - " \n", - " \n", - " 2021-01-03\n", - " 0.307117\n", - " \n", - " \n", - " 2021-01-10\n", - " 0.119653\n", - " \n", - " \n", - " 2021-01-17\n", - " 0.385201\n", - " \n", - " \n", - " 2021-01-24\n", - " 0.219277\n", - " \n", - " \n", - " 2021-01-31\n", - " 0.962418\n", - " \n", - " \n", - " 2021-02-07\n", - " 0.265013\n", - " \n", - " \n", - " 2021-02-14\n", - " 0.178213\n", - " \n", - " \n", - " 2021-02-21\n", - " 0.833785\n", - " \n", - " \n", - " 2021-02-28\n", - " 0.668348\n", - " \n", - " \n", - " 2021-03-07\n", - " 0.826616\n", - " \n", - " \n", - " 2021-03-14\n", - " 0.345981\n", - " \n", - " \n", - " 2021-03-21\n", - " 0.619586\n", - " \n", - " \n", - " 2021-03-28\n", - " 0.362562\n", - " \n", - " \n", - " 2021-04-04\n", - " 0.765329\n", - " \n", - " \n", - " 2021-04-11\n", - " 0.800720\n", - " \n", - " \n", - " 2021-04-18\n", - " 0.156365\n", - " \n", - " \n", - " 2021-04-25\n", - " 0.988019\n", - " \n", - " \n", - " 2021-05-02\n", - " 0.587013\n", - " \n", - " \n", - " 2021-05-09\n", - " 0.709290\n", - " \n", - " \n", - " 2021-05-16\n", - " 0.862771\n", - " \n", - " \n", - " 2021-05-23\n", - " 0.475769\n", - " \n", - " \n", - " 2021-05-30\n", - " 0.860615\n", + " 0.933940\n", " \n", " \n", "\n", @@ -459,61 +263,12 @@ ], "text/plain": [ " 0\n", - "2020-06-07 0.816153\n", - "2020-06-14 0.142715\n", - "2020-06-21 0.883367\n", - "2020-06-28 0.042243\n", - "2020-07-05 0.902994\n", - "2020-07-12 0.122903\n", - "2020-07-19 0.883686\n", - "2020-07-26 0.599879\n", - "2020-08-02 0.585071\n", - "2020-08-09 0.487260\n", - "2020-08-16 0.577816\n", - "2020-08-23 0.217873\n", - "2020-08-30 0.642893\n", - "2020-09-06 0.269524\n", - "2020-09-13 0.681086\n", - "2020-09-20 0.066728\n", - "2020-09-27 0.192068\n", - "2020-10-04 0.430084\n", - "2020-10-11 0.673437\n", - "2020-10-18 0.216691\n", - "2020-10-25 0.172302\n", - "2020-11-01 0.034461\n", - "2020-11-08 0.764077\n", - "2020-11-15 0.166790\n", - "2020-11-22 0.379369\n", - "2020-11-29 0.026259\n", - "2020-12-06 0.215560\n", - "2020-12-13 0.912649\n", - "2020-12-20 0.752434\n", - "2020-12-27 0.129831\n", - "2021-01-03 0.307117\n", - "2021-01-10 0.119653\n", - "2021-01-17 0.385201\n", - "2021-01-24 0.219277\n", - "2021-01-31 0.962418\n", - "2021-02-07 0.265013\n", - "2021-02-14 0.178213\n", - "2021-02-21 0.833785\n", - "2021-02-28 0.668348\n", - "2021-03-07 0.826616\n", - "2021-03-14 0.345981\n", - "2021-03-21 0.619586\n", - "2021-03-28 0.362562\n", - "2021-04-04 0.765329\n", - "2021-04-11 0.800720\n", - "2021-04-18 0.156365\n", - "2021-04-25 0.988019\n", - "2021-05-02 0.587013\n", - "2021-05-09 0.709290\n", - "2021-05-16 0.862771\n", - "2021-05-23 0.475769\n", - "2021-05-30 0.860615" + "2020-07-12 0.581691\n", + "2020-07-19 0.611492\n", + "2020-07-26 0.933940" ] }, - "execution_count": 6, + "execution_count": 61, "metadata": {}, "output_type": "execute_result" } @@ -522,7 +277,7 @@ "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" + "df['2020-07-10':'2020-07-28']" ] }, { @@ -661,7 +416,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 63, "metadata": {}, "outputs": [ { @@ -724,7 +479,7 @@ "2020-05-31 5.09 12" ] }, - "execution_count": 9, + "execution_count": 63, "metadata": {}, "output_type": "execute_result" } @@ -734,7 +489,7 @@ "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.loc[:'2020/05/31']" + "df[:'2020/05/31']" ] }, { @@ -747,14 +502,14 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "1998 10 10 0.4173998814595933\n" + "2017 12 7 0.970109923902562\n" ] } ], @@ -768,18 +523,74 @@ }, { "cell_type": "code", - "execution_count": 11, + "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 1998-10-10 00:00:00\n", - "1 0.4174\n", - "Name: 5, dtype: object" + " 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": 11, + "execution_count": 64, "metadata": {}, "output_type": "execute_result" } @@ -789,7 +600,90 @@ "df1 = pd.to_datetime(df1) \n", "df2 = pd.Series(data)\n", "df = pd.concat([df1, df2], axis=1)\n", - "df.loc[5]" + "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()" ] }, { 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/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 From 0db1d49f4a1f55d50107ecc8f988679c87eb2c0d Mon Sep 17 00:00:00 2001 From: Joe James Date: Thu, 18 Jun 2020 12:54:45 -0700 Subject: [PATCH 34/75] Add files via upload --- Pandas/Pandas - Change Column Names.ipynb | 364 +++++++++ ...ndas - Delete Columns from DataFrame.ipynb | 757 ++++++++++++++++++ ...Pandas - Iterate Rows of a DataFrame.ipynb | 723 +++++++++++++++++ Pandas/iris.data | 151 ++++ 4 files changed, 1995 insertions(+) create mode 100644 Pandas/Pandas - Change Column Names.ipynb create mode 100644 Pandas/Pandas - Delete Columns from DataFrame.ipynb create mode 100644 Pandas/Pandas - Iterate Rows of a DataFrame.ipynb create mode 100644 Pandas/iris.data 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..e728b3bf --- /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", + "df.drop('col_name', axis=1) \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 - 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/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 + From a097b552b60efb914ba57aa9464445bb159a093e Mon Sep 17 00:00:00 2001 From: Joe James Date: Thu, 18 Jun 2020 22:48:32 -0700 Subject: [PATCH 35/75] Add files via upload --- ...das - Delete NaN Rows from DataFrame.ipynb | 655 ++++++++++++++++++ .../Pandas Reorder Columns in DataFrame.ipynb | 420 +++++++++++ 2 files changed, 1075 insertions(+) create mode 100644 Pandas/Pandas - Delete NaN Rows from DataFrame.ipynb create mode 100644 Pandas/Pandas Reorder Columns in DataFrame.ipynb 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 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 +} From 4ed5a68b4dd4d0ed50476d8c001f2a345fb6de38 Mon Sep 17 00:00:00 2001 From: saksham044 <72141820+saksham044@users.noreply.github.com> Date: Wed, 30 Sep 2020 18:40:38 +0530 Subject: [PATCH 36/75] Update .gitattributes --- .gitattributes | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 5bd1af68d3d47649459a45a13ecc17ad9d00aff0 Mon Sep 17 00:00:00 2001 From: Ashish0931 <40832481+Ashish0931@users.noreply.github.com> Date: Wed, 30 Sep 2020 21:02:12 +0530 Subject: [PATCH 37/75] Update Pandas - Delete Columns from DataFrame.ipynb --- Pandas/Pandas - Delete Columns from DataFrame.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pandas/Pandas - Delete Columns from DataFrame.ipynb b/Pandas/Pandas - Delete Columns from DataFrame.ipynb index e728b3bf..28293203 100644 --- a/Pandas/Pandas - Delete Columns from DataFrame.ipynb +++ b/Pandas/Pandas - Delete Columns from DataFrame.ipynb @@ -174,8 +174,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 1) to drop a single column\n", - "df.drop('col_name', axis=1) \n", + "### 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." ] }, From 00e9b3859533f2702dc6b38c6322c60907493dc3 Mon Sep 17 00:00:00 2001 From: Jayant123-Joker <72143741+Jayant123-Joker@users.noreply.github.com> Date: Wed, 30 Sep 2020 21:31:01 +0530 Subject: [PATCH 38/75] Update graph_adjacency-matrix.py --- graph_adjacency-matrix.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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() From 62d2bc8d665bcfbf101227817b5910db14fee486 Mon Sep 17 00:00:00 2001 From: Parmodsihag <68704187+Parmodsihag@users.noreply.github.com> Date: Wed, 30 Sep 2020 21:53:30 +0530 Subject: [PATCH 39/75] added else statement with try except also added some more explanation --- exception-handling.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) 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 + From 8c6e715df625ca125a365f7fcfe976d515a24c36 Mon Sep 17 00:00:00 2001 From: OpensourceContributor07 <69769312+OpensourceContributor07@users.noreply.github.com> Date: Thu, 1 Oct 2020 00:12:30 +0530 Subject: [PATCH 40/75] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6f0d92be..f0c8d233 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ and are mainly intended for educational purposes. You are invited to subscribe to my video channel, 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!!!!!!!!! Joe James. Fremont, California. From 1c8e553935e7d13301f9de44ca18e4c0721752bd Mon Sep 17 00:00:00 2001 From: SaiSuvamPatnaik <63333249+SaiSuvamPatnaik@users.noreply.github.com> Date: Thu, 1 Oct 2020 01:10:13 +0530 Subject: [PATCH 41/75] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6f0d92be..cbfbb2e0 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,4 @@ Feel free to post any comments on my YouTube channel. Joe James. Fremont, California. Copyright (C) 2015-2019, Joe James +HELLO From 85c2146e1c595f4c19352b8144736290ae3853a7 Mon Sep 17 00:00:00 2001 From: JAI ARORA <64232138+JAI-ARORA@users.noreply.github.com> Date: Thu, 1 Oct 2020 03:08:35 +0530 Subject: [PATCH 42/75] Update factorial.py --- factorial.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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)) From 78ae3b4aa8de92e77af540f2efa8af89e6fba8ae Mon Sep 17 00:00:00 2001 From: anay2310 <70628601+anay2310@users.noreply.github.com> Date: Thu, 1 Oct 2020 09:07:07 +0530 Subject: [PATCH 43/75] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f0d92be..760428bf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Python +# 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. From 3677438558ebf2af5cef2fc7fb20f2dbef2b481f Mon Sep 17 00:00:00 2001 From: AmanKumar05032005 <72191898+AmanKumar05032005@users.noreply.github.com> Date: Thu, 1 Oct 2020 14:26:15 +0530 Subject: [PATCH 44/75] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f0d92be..a3544ea3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 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. From dc5c7aaf735b6656c0ce24206e7958569623f4bc Mon Sep 17 00:00:00 2001 From: Aniket Gupta <63919139+aniketguptaa@users.noreply.github.com> Date: Thu, 1 Oct 2020 15:20:20 +0530 Subject: [PATCH 45/75] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6f0d92be..b8ce25de 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ You are invited to subscribe to my video channel, and to download and use any co this Python repository, according to the MIT License. Feel free to post any comments on my YouTube channel. + +This source codes are 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 be better python programmer and remember "Try to learn something about everything and everything about something". + +Thank you for reviewing my repositories and keep practising. Joe James. Fremont, California. Copyright (C) 2015-2019, Joe James From 33182dd11d1c66a4a46071a650851ebb16179f74 Mon Sep 17 00:00:00 2001 From: beingritik <72251017+beingritik@users.noreply.github.com> Date: Fri, 2 Oct 2020 14:16:14 +0530 Subject: [PATCH 46/75] change the information --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f0d92be..9f0a1d95 100644 --- a/README.md +++ b/README.md @@ -7,5 +7,5 @@ this Python repository, according to the MIT License. Feel free to post any comments on my YouTube channel. Joe James. -Fremont, California. +Fremont, CA. Copyright (C) 2015-2019, Joe James From 67ed35cf3cc1755ba09649fff201b8d85884b750 Mon Sep 17 00:00:00 2001 From: Aiswarya29 <72244069+Aiswarya29@users.noreply.github.com> Date: Fri, 2 Oct 2020 17:47:45 +0530 Subject: [PATCH 47/75] Create Heapsort.py --- Sorting Algorithms/Heapsort.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Sorting Algorithms/Heapsort.py 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=" ") From 6f4622e530df36920567565380582d37e26bcd75 Mon Sep 17 00:00:00 2001 From: Ethan Palani <46998848+Ethan0507@users.noreply.github.com> Date: Fri, 2 Oct 2020 21:23:00 +0530 Subject: [PATCH 48/75] Update CircularLinkedList.py Overwriting the inbuilt '__str__' method to print the Node, rather than creating a new method and calling it. --- LinkedLists/CircularLinkedList.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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() From b02dd159c8d711fd862f6abf5a2fdc4b5f972686 Mon Sep 17 00:00:00 2001 From: Govindrajewar <72288656+Govindrajewar@users.noreply.github.com> Date: Sat, 3 Oct 2020 09:00:21 +0530 Subject: [PATCH 49/75] Create python oriented programming This is all Program which I run in python --- python oriented programming | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 python oriented programming 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() + From b46ea8082cf485c60519cd5f73578bba1c59a2ce Mon Sep 17 00:00:00 2001 From: PRAJESH <47695045+Prajesh-Srivastava@users.noreply.github.com> Date: Sun, 4 Oct 2020 08:18:29 +0530 Subject: [PATCH 50/75] Create Some Basic Terminologies in Python Data Structure --- ...sic Terminologies in Python Data Structure | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Intro to Python Data Structures/Some Basic Terminologies in Python Data Structure 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. From 42ff89e35a280ef9f8e6e5ff049081a36212a39b Mon Sep 17 00:00:00 2001 From: Ritik <63651014+ritik1234@users.noreply.github.com> Date: Mon, 5 Oct 2020 09:02:43 +0530 Subject: [PATCH 51/75] just made the content easier to read for the user. (#45) --- Python List Iteration.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python List Iteration.ipynb b/Python List Iteration.ipynb index d680f54f..7361caaf 100644 --- a/Python List Iteration.ipynb +++ b/Python List Iteration.ipynb @@ -13,7 +13,7 @@ "metadata": {}, "source": [ "----\n", - "The standard for loop works great if inside the loop you only need the item and not its index." + "The standard for loop works well if it is used inside the loop you only need the item and not its index." ] }, { From 49f05ba131f7525f24208c8138b8351875928f37 Mon Sep 17 00:00:00 2001 From: sid2631 <69759968+sid2631@users.noreply.github.com> Date: Mon, 5 Oct 2020 15:33:43 +0530 Subject: [PATCH 52/75] Create addition of two number addition of two number --- addition of two number | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 addition of two number 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)) From d0ebf11ae6223e2259dd471d52c41af4f8a5c648 Mon Sep 17 00:00:00 2001 From: PRAJESH <47695045+Prajesh-Srivastava@users.noreply.github.com> Date: Thu, 8 Oct 2020 09:39:20 +0530 Subject: [PATCH 53/75] Update Date_Time_Timestamp.py --- Date Time Timestamp/Date_Time_Timestamp.py | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) 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) From 9aa8a9a31cd5e33dda4150736a84658515d55187 Mon Sep 17 00:00:00 2001 From: Sh1710 <72331454+Sh1710@users.noreply.github.com> Date: Thu, 8 Oct 2020 11:56:34 +0530 Subject: [PATCH 54/75] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5dc9c6ad..22d802cb 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ You are invited to subscribe to my video channel-Joe James, and to download and 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 my channel for more tutorial videos. This source codes are 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 be better python programmer and remember "Try to learn something about everything and everything about something". @@ -15,3 +15,4 @@ Joe James. Fremont, CA. Copyright (C) 2015-2019, Joe James HELLO +## Happy coding guys!😀 From 576c4ead4535179969a5daca7e54234e41d0c8f2 Mon Sep 17 00:00:00 2001 From: Joe James Date: Fri, 9 Oct 2020 21:50:51 -0700 Subject: [PATCH 55/75] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 22d802cb..3c0ced97 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@ and are mainly intended for educational purposes. 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 my channel for more tutorial videos. +i am very happy to see you there on my you tube channel. excited!!!!!!!!! +## Subscribe to my channel for more tutorial videos. This source codes are 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 be better python programmer and remember "Try to learn something about everything and everything about something". -Thank you for reviewing my repositories and keep practising. +Thank you for reviewing my repositories and keep practicing. Joe James. Fremont, CA. -Copyright (C) 2015-2019, Joe James -HELLO +Copyright (C) 2015-2020, Joe James + ## Happy coding guys!😀 From 56045c1a7ecd4579e51aed358861abbaa7a8dee9 Mon Sep 17 00:00:00 2001 From: gopesanjay772 <72152228+gopesanjay772@users.noreply.github.com> Date: Sat, 17 Oct 2020 10:03:45 +0530 Subject: [PATCH 56/75] Update lcm.py --- lcm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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))) From e7f9b1ad920e3ec4eb2945fbc98d22de298b7d8b Mon Sep 17 00:00:00 2001 From: Aniket Gupta <63919139+aniketguptaa@users.noreply.github.com> Date: Sun, 18 Oct 2020 00:32:44 +0530 Subject: [PATCH 57/75] Update Queues implementaion.py --- Queues implementaion.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Queues implementaion.py b/Queues implementaion.py index da9bad1a..63170c8c 100644 --- a/Queues implementaion.py +++ b/Queues implementaion.py @@ -54,15 +54,6 @@ def display(self): for i in self.items: ar.append(i) return ar - - - - - - - - - que = Queue() que.enqueue('google') que.enqueue('youtube') From 6c2897775348d3151bc1d87dd1c10bdd9ec29a20 Mon Sep 17 00:00:00 2001 From: princerajputana6 <37314665+princerajputana6@users.noreply.github.com> Date: Wed, 21 Oct 2020 03:07:55 +0530 Subject: [PATCH 58/75] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3c0ced97..c520b85f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +#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 From ad6cab029a28aac7e1c2fbd6fb7e773e10390a97 Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 21 Oct 2020 11:48:34 -0700 Subject: [PATCH 59/75] Add files via upload --- Sorting Algorithms/Radix_Sort.ipynb | 113 ++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 Sorting Algorithms/Radix_Sort.ipynb diff --git a/Sorting Algorithms/Radix_Sort.ipynb b/Sorting Algorithms/Radix_Sort.ipynb new file mode 100644 index 00000000..4862a2e5 --- /dev/null +++ b/Sorting Algorithms/Radix_Sort.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Radix Sort\n", + "(c) 2020, Joe James" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "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": 6, + "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": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def radix(A, num_digits):\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": 9, + "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", + " num_digits = __get_num_digits(A)\n", + " A = radix(A, num_digits)\n", + " print(A)\n", + " \n", + " B = [i for i in range(1000000)]\n", + " from random import shuffle\n", + " shuffle(B)\n", + " B = radix(B, __get_num_digits(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 +} From f97b3a239189d7c66bb019790e65a0b5ff879f30 Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 21 Oct 2020 19:57:42 -0700 Subject: [PATCH 60/75] Revised function call. Moved __get_num_digits() function call into the radix() function, so the only parameter when calling radix() is a List. --- Sorting Algorithms/Radix_Sort.ipynb | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Sorting Algorithms/Radix_Sort.ipynb b/Sorting Algorithms/Radix_Sort.ipynb index 4862a2e5..0b701528 100644 --- a/Sorting Algorithms/Radix_Sort.ipynb +++ b/Sorting Algorithms/Radix_Sort.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -34,13 +34,22 @@ " 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": 7, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ - "def radix(A, num_digits):\n", + "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", @@ -53,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -68,14 +77,13 @@ "source": [ "def main():\n", " A = [55, 45, 3, 289, 213, 1, 288, 53, 2]\n", - " num_digits = __get_num_digits(A)\n", - " A = radix(A, num_digits)\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, __get_num_digits(B))\n", + " B = radix(B)\n", " print(B[:6], B[-6:])\n", "\n", "main()" From f7893b62e479182590acd4fcdb7af277099e47b9 Mon Sep 17 00:00:00 2001 From: Varun Shrivastava Date: Sat, 27 Feb 2021 20:28:14 +0530 Subject: [PATCH 61/75] Added a new .py file for classes in python(OOP) --- .../building our first class.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Object Oriented Programming/building our first class.py 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) + + + + From 779b27f990a0e21ce6ede0f49b4cd1228ae5f73d Mon Sep 17 00:00:00 2001 From: Varun Shrivastava Date: Mon, 1 Mar 2021 19:41:36 +0530 Subject: [PATCH 62/75] Added contributing file --- Contributing.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Contributing.txt diff --git a/Contributing.txt b/Contributing.txt new file mode 100644 index 00000000..50913f5c --- /dev/null +++ b/Contributing.txt @@ -0,0 +1,19 @@ +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]` + + \ No newline at end of file From 02d3f3dd02cc3041bbf2bafd284503deb92397b7 Mon Sep 17 00:00:00 2001 From: Varun Shrivastava Date: Tue, 2 Mar 2021 19:31:29 +0530 Subject: [PATCH 63/75] updated Contributing.txt --- Contributing.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Contributing.txt b/Contributing.txt index 50913f5c..52d1fd31 100644 --- a/Contributing.txt +++ b/Contributing.txt @@ -16,4 +16,6 @@ GIT COMMANDS FOR CONTRIBUTING - 5. To push changes `git push [remote branch] [new branch]` +HAPPY CONTRIBUTION!!!!!!!! + \ No newline at end of file From 4b7f7777518d20309c9f0dd64aa7f0b20451f58b Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 13 Oct 2021 15:28:41 -0700 Subject: [PATCH 64/75] Added Python 10 match statements notebook --- match statements.ipynb | 222 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 match statements.ipynb diff --git a/match statements.ipynb b/match statements.ipynb new file mode 100644 index 00000000..2bc9b2dd --- /dev/null +++ b/match statements.ipynb @@ -0,0 +1,222 @@ +{ + "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": "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": [ + "#### The Default case _ \n", + "The default case, using underscore, is optional. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "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", + "if statements and or (using bar) are supported in case statements." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "small\n" + ] + } + ], + "source": [ + "var = 2\n", + "\n", + "match var:\n", + " case x if x<=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", + "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": 4, + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "welcome to the business program!\n", + "welcome to the science program!\n" + ] + } + ], + "source": [ + "class Student:\n", + " def __init__(self, n, i, m):\n", + " self.name = n\n", + " self.id = i\n", + " self.major = m\n", + "\n", + "def welcome(student):\n", + " match student.major:\n", + " case 'engineering':\n", + " print('welcome to the engineering program!')\n", + " case 'business':\n", + " print('welcome to the business program!')\n", + " case 'pharmacy':\n", + " print('welcome to the pharmacy program!')\n", + " case x:\n", + " print(f'welcome to the {x} program!')\n", + " \n", + "new_student = Student('Suresh', 5723, 'business')\n", + "welcome(new_student)\n", + "\n", + "new_student = Student('Britney', 5724, 'science')\n", + "welcome(new_student)" + ] + }, + { + "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 +} From 71cc10b4e2063d6b8811e5f16004e207ecfd28c4 Mon Sep 17 00:00:00 2001 From: Joe James Date: Wed, 13 Oct 2021 15:31:36 -0700 Subject: [PATCH 65/75] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c520b85f..939de1ed 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,14 @@ and are mainly intended for educational purposes. 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!!!!!!!!! +I am very happy to see you there on my you tube channel. excited!!!!!!!!! ## Subscribe to my channel for more tutorial videos. -This source codes are 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 be better python programmer and remember "Try to learn something about everything and everything about something". +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, CA. -Copyright (C) 2015-2020, Joe James +Copyright (C) 2015-2021, Joe James ## Happy coding guys!😀 From e897fb6703f9672bf3aa353ed7f490f1e5591717 Mon Sep 17 00:00:00 2001 From: Joe James Date: Fri, 15 Oct 2021 21:06:47 -0700 Subject: [PATCH 66/75] updated match-case notebook --- match statements.ipynb | 154 ++++++++++++++++++++++++++++++++++------- 1 file changed, 128 insertions(+), 26 deletions(-) diff --git a/match statements.ipynb b/match statements.ipynb index 2bc9b2dd..eaccdc9f 100644 --- a/match statements.ipynb +++ b/match statements.ipynb @@ -11,6 +11,13 @@ "[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, @@ -36,6 +43,103 @@ " 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": {}, @@ -46,7 +150,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -74,12 +178,12 @@ "metadata": {}, "source": [ "#### Conditionals in case \n", - "if statements and or (using bar) are supported in case statements." + "*if* statements and *or* (using bar) are supported in case statements." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -112,7 +216,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -153,41 +257,39 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "welcome to the business program!\n", - "welcome to the science program!\n" + "medium\n", + "Size XL is not recognized.\n" ] } ], "source": [ - "class Student:\n", - " def __init__(self, n, i, m):\n", - " self.name = n\n", - " self.id = i\n", - " self.major = m\n", + "class T_shirt:\n", + " def __init__(self, s):\n", + " self.size = s\n", "\n", - "def welcome(student):\n", - " match student.major:\n", - " case 'engineering':\n", - " print('welcome to the engineering program!')\n", - " case 'business':\n", - " print('welcome to the business program!')\n", - " case 'pharmacy':\n", - " print('welcome to the pharmacy program!')\n", - " case x:\n", - " print(f'welcome to the {x} program!')\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", - "new_student = Student('Suresh', 5723, 'business')\n", - "welcome(new_student)\n", + "shirt1 = T_shirt('Med')\n", + "shirt1.order()\n", "\n", - "new_student = Student('Britney', 5724, 'science')\n", - "welcome(new_student)" + "shirt2 = T_shirt('XL')\n", + "shirt2.order()" ] }, { From 500c2099fa3a4c679b225656baadc0cf861db58e Mon Sep 17 00:00:00 2001 From: Joe James Date: Sun, 17 Oct 2021 17:34:13 -0700 Subject: [PATCH 67/75] 2nd update to match statements notebook --- match statements.ipynb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/match statements.ipynb b/match statements.ipynb index eaccdc9f..a8fc422d 100644 --- a/match statements.ipynb +++ b/match statements.ipynb @@ -178,7 +178,7 @@ "metadata": {}, "source": [ "#### Conditionals in case \n", - "*if* statements and *or* (using bar) are supported in case statements." + "*or* conditions (using bar) are supported in case statements." ] }, { @@ -198,7 +198,7 @@ "var = 2\n", "\n", "match var:\n", - " case x if x<=3:\n", + " case 2 | 3:\n", " print('small')\n", " case 4 | 5 | 6:\n", " print('medium')\n", @@ -211,6 +211,8 @@ "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." ] }, @@ -252,7 +254,8 @@ "metadata": {}, "source": [ "#### Python Objects \n", - "match statements can also use Python objects and instance variables." + "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." ] }, { From ccb7bdf4b9369e06c4cd5860d368546365836d50 Mon Sep 17 00:00:00 2001 From: Joe James Date: Thu, 28 Oct 2021 17:20:21 -0700 Subject: [PATCH 68/75] Create temp --- Iris Dataset/temp | 1 + 1 file changed, 1 insertion(+) create mode 100644 Iris Dataset/temp diff --git a/Iris Dataset/temp b/Iris Dataset/temp new file mode 100644 index 00000000..9c595a6f --- /dev/null +++ b/Iris Dataset/temp @@ -0,0 +1 @@ +temp From 763ba2befbd41a8c66870c58e3b9b6fe08f72a43 Mon Sep 17 00:00:00 2001 From: Joe James Date: Thu, 28 Oct 2021 17:23:16 -0700 Subject: [PATCH 69/75] Add files via upload --- Iris Dataset/Iris_Dataset.ipynb | 1174 +++++++++++++++++++++++++++++++ Iris Dataset/iris.data | 151 ++++ 2 files changed, 1325 insertions(+) create mode 100644 Iris Dataset/Iris_Dataset.ipynb create mode 100644 Iris Dataset/iris.data 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": "iVBORw0KGgoAAAANSUhEUgAAAXAAAAD4CAYAAAD1jb0+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAQl0lEQVR4nO3df6zddX3H8efLggMRAccdqRRXokZKbCzmDnUY40AMClFMjIFspllI6hJdYJo58B8x2WJNVNwfi0kFpMsQ7fgRDDInQQwj2dBbqLRwcSJWba30GuXXsugK7/1xv5VLubf39Nxz7jkf+nwkNz3ne77ne14p7YtPP9/v53xTVUiS2vOSUQeQJPXHApekRlngktQoC1ySGmWBS1KjjljODzvxxBNr9erVy/mRktS8rVu3/qqqJg7cvqwFvnr1aqamppbzIyWpeUl+Ot92p1AkqVEWuCQ1ygKXpEZZ4JLUKAtckhplgUtSoyxwSWqUBS5JjbLAJalRy7oScymmT1vT035rHp4echJJGg+OwCWpUT0XeJIVSe5Pclv3/NQk9yZ5JMnXk7x0eDElSQc6lBH4pcDc+YnPAldV1WuB3wCXDDKYJOngeirwJKuA84Gru+cBzgZu7HbZDFw4jICSpPn1OgL/IvAJ4Nnu+R8Cj1fVvu75LuDk+d6YZEOSqSRTMzMzSworSXrOogWe5AJgb1Vt7ecDqmpTVU1W1eTExAu+j1yS1KdeLiM8C3hvkvcARwGvAP4ROD7JEd0ofBWwe3gxJUkHWnQEXlVXVNWqqloNXAR8p6r+HLgL+EC323rg1qGllCS9wFKuA/874GNJHmF2TvyawUSSJPXikFZiVtV3ge92jx8Fzhx8JElSL1yJKUmNssAlqVEWuCQ1ygKXpEY183WyatyVx/WwzxPDzyG9iDgCl6RGWeCS1CgLXJIaZYFLUqM8idmHtZvXDu3Y29dvH9qxJb24OAKXpEZZ4JLUKAtckhplgUtSoyxwSWqUBS5JjerlpsZHJflekh8keTDJp7vt1yX5SZJt3c+64ceVJO3Xy3XgvwXOrqqnkxwJ3JPk37rX/raqbhxePEnSQhYt8Koq4Onu6ZHdTw0zlCRpcT3NgSdZkWQbsBe4o6ru7V76hyQPJLkqyR8s8N4NSaaSTM3MzAwotiSppwKvqmeqah2wCjgzyRuAK4DTgD8BXsnsXerne++mqpqsqsmJiYkBxZYkHdJVKFX1OHAXcF5V7alZvwW+gneol6Rl1ctVKBNJju8eHw2cCzycZGW3LcCFwI5hBpUkPV8vV6GsBDYnWcFs4W+pqtuSfCfJBBBgG/BXQ8wpSTpAL1ehPACcMc/2s4eSSJLUE1diSlKjLHBJapQFLkmNssAlqVHeE3MZbPnMvkX3+eAV/qeQdGgcgUtSoyxwSWqUBS5JjbLAJalRFrgkNcoCl6RGWeCS1CgLXJIaZYFLUqNc/qfxceVxPezzxPBzSI1wBC5JjerllmpHJflekh8keTDJp7vtpya5N8kjSb6e5KXDjytJ2q+XEfhvgbOr6o3AOuC8JG8BPgtcVVWvBX4DXDK8mJKkAy1a4N2d55/unh7Z/RRwNnBjt30zszc2liQtk57mwJOsSLIN2AvcAfwYeLyq9n9P6i7g5AXeuyHJVJKpmZmZQWSWJNFjgVfVM1W1DlgFnAmc1usHVNWmqpqsqsmJiYk+Y0qSDnRIV6FU1ePAXcBbgeOT7L8McRWwe8DZJEkH0ctVKBNJju8eHw2cC0wzW+Qf6HZbD9w6rJCSpBfqZSHPSmBzkhXMFv6WqrotyUPA15L8PXA/cM0Qc0qSDrBogVfVA8AZ82x/lNn5cEnzWLt57dCOvX399qEdW+1wJaYkNcoCl6RGWeCS1CgLXJIaZYFLUqMscElqlAUuSY2ywCWpURa4JDXKe2JKL2KrL/9mX+/bufH8ASfRMDgCl6RGWeCS1CgLXJIaZYFLUqM8ianD2jC/8vVw5EnT5eUIXJIa1cst1U5JcleSh5I8mOTSbvuVSXYn2db9vGf4cSVJ+/UyhbIP+HhV3ZfkWGBrkju6166qqs8NL54kaSG93FJtD7Cne/xUkmng5GEHkyQd3CHNgSdZzez9Me/tNn00yQNJrk1ywoCzSZIOoucCT/Jy4Cbgsqp6EvgS8BpgHbMj9M8v8L4NSaaSTM3MzAwgsiQJeizwJEcyW97XV9XNAFX1WFU9U1XPAl9mgTvUV9WmqpqsqsmJiYlB5Zakw14vV6EEuAaYrqovzNm+cs5u7wd2DD6eJGkhvVyFchbwIWB7km3dtk8CFydZBxSwE/jwUBJKkubVy1Uo9wCZ56XbBx9HktQrl9Jraa48btQJpMOWS+klqVEWuCQ1ygKXpEZZ4JLUKE9iNmb6tDWL7rPm4ellSCJp1ByBS1KjLHBJapQFLkmNssAlqVGexNTCXGUpjTVH4JLUKAtckhplgUtSoyxwSWqUBS5JjbLAJalRvdwT85QkdyV5KMmDSS7ttr8yyR1JftT9esLw40qS9utlBL4P+HhVnQ68BfhIktOBy4E7q+p1wJ3dc0nSMlm0wKtqT1Xd1z1+CpgGTgbeB2zudtsMXDiskJKkFzqkOfAkq4EzgHuBk6pqT/fSL4GTFnjPhiRTSaZmZmaWEFWSNFfPBZ7k5cBNwGVV9eTc16qqgJrvfVW1qaomq2pyYmJiSWElSc/pqcCTHMlseV9fVTd3mx9LsrJ7fSWwdzgRJUnz6eUqlADXANNV9YU5L30DWN89Xg/cOvh4kqSF9PJthGcBHwK2J9nWbfsksBHYkuQS4KfAB4cTUZI0n0ULvKruAbLAy+cMNo4kqVeuxJSkRlngktQoC1ySGmWBS1KjvCem1KC1m9f2tN+xaw792E9Nbzz0Ny3R6su/2df7dm48f8BJ2uIIXJIaZYFLUqMscElqlAUuSY2ywCWpURa4JDXKApekRlngktQoC1ySGuVKTEkv0O/KSC0vR+CS1Khebql2bZK9SXbM2XZlkt1JtnU/7xluTEnSgXoZgV8HnDfP9quqal33c/tgY0mSFrNogVfV3cCvlyGLJOkQLGUO/KNJHuimWE5YaKckG5JMJZmamZlZwsdJkubqt8C/BLwGWAfsAT6/0I5VtamqJqtqcmJios+PkyQdqK8Cr6rHquqZqnoW+DJw5mBjSZIW01eBJ1k55+n7gR0L7StJGo5FF/IkuQF4B3Bikl3Ap4B3JFkHFLAT+PAQM0qS5rFogVfVxfNsvmYIWbSMpk/r5WaJr2LNRb8YehZJ/XElpiQ1ygKXpEZZ4JLUKAtckhrl18mOmbWb1x709S1LOMb29dv7SCRpXDkCl6RGWeCS1CgLXJIaZYFLUqMscElqlAUuSY2ywCWpURa4JDXKApekRrkSUy9OVx7Xwz5PDD9Hg45dc/nQjv3U9MahHftw5Ahckhq1aIF3d53fm2THnG2vTHJHkh91vy54V3pJ0nD0MgK/DjjvgG2XA3dW1euAO7vnkqRltGiBV9XdwK8P2Pw+YHP3eDNw4YBzSZIW0e8c+ElVtad7/EvgpIV2TLIhyVSSqZmZmT4/TpJ0oCWfxKyqYvbu9Au9vqmqJqtqcmJiYqkfJ0nq9FvgjyVZCdD9undwkSRJvei3wL8BrO8erwduHUwcSVKvermM8AbgP4HXJ9mV5BJgI3Bukh8B7+yeS5KW0aIrMavq4gVeOmfAWTQgWz6zb97t059Zs8xJhqCXFZbSYcKVmJLUKAtckhplgUtSoyxwSWrUi+7rZKdPW/xE3ZqHpwf2eQudMNTgrD311cM58Oa1wzmutEwcgUtSoyxwSWqUBS5JjbLAJalRL7qTmINysJOhW5YxhyQtxBG4JDXKApekRlngktQoC1ySGuVJzDHhik7p0K2+/Jt9vW/nxvOX9fOW8pkH4whckhq1pBF4kp3AU8AzwL6qmhxEKEnS4gYxhfJnVfWrARxHknQInEKRpEYttcAL+HaSrUk2DCKQJKk3S51CeVtV7U7yR8AdSR6uqrvn7tAV+waAV796SN/rLKkJx665fKjHf2p6Y0/7LeVqknGypBF4Ve3uft0L3AKcOc8+m6pqsqomJyYmlvJxkqQ5+i7wJMckOXb/Y+BdwI5BBZMkHdxSplBOAm5Jsv84X62qbw0klSRpUX0XeFU9CrxxgFkkSYfAywglqVEWuCQ1ygKXpEZZ4JLUKAtckhrl94FrINae6ipbabk5ApekRlngktQoC1ySGmWBS1KjLHBJapQFLkmNssAlqVEWuCQ1ygKXpEYdlisxp09bM+oIkrRkjsAlqVFLKvAk5yX5YZJHkgz3dtOSpOdZyk2NVwD/BLwbOB24OMnpgwomSTq4pYzAzwQeqapHq+p3wNeA9w0mliRpMUs5iXky8PM5z3cBbz5wpyQbgA3d06eT/LDH458I/GoJ+Ybp8Mn26V533NHLTofP79tgma1nF8x9MlbZ8tnnPT3UbH8838ahX4VSVZuATYf6viRTVTU5hEhLZrb+mK0/ZuvP4ZBtKVMou4FT5jxf1W2TJC2DpRT494HXJTk1yUuBi4BvDCaWJGkxfU+hVNW+JB8F/h1YAVxbVQ8OLFkf0y7LyGz9MVt/zNafF322VNUgjiNJWmauxJSkRlngktSosSzwcV2in+TaJHuT9HTR83JKckqSu5I8lOTBJJeOOtN+SY5K8r0kP+iy9Xx1+XJJsiLJ/UluG3WWuZLsTLI9ybYkU6POM1eS45PcmOThJNNJ3jrqTABJXt/9fu3/eTLJZaPOtV+Sv+n+HuxIckOSo/o+1rjNgXdL9P8bOJfZxUHfBy6uqodGGgxI8nbgaeCfq+oNo84zV5KVwMqqui/JscBW4MIx+X0LcExVPZ3kSOAe4NKq+q8RR/u9JB8DJoFXVNUFi+2/XJLsBCaramwWpOyXZDPwH1V1dXcl2suq6vFR55qr65PdwJur6qdjkOdkZv/8n15V/5tkC3B7VV3Xz/HGcQQ+tkv0q+pu4NejzjGfqtpTVfd1j58CppldLTtyNevp7umR3c/YjBySrALOB64edZZWJDkOeDtwDUBV/W7cyrtzDvDjcSjvOY4Ajk5yBPAy4Bf9HmgcC3y+JfpjUUStSLIaOAO4d7RJntNNUWwD9gJ3VNXYZAO+CHwCeHbUQeZRwLeTbO2+lmJcnArMAF/ppp6uTnLMqEPN4yLghlGH2K+qdgOfA34G7AGeqKpv93u8cSxwLUGSlwM3AZdV1ZOjzrNfVT1TVeuYXbF7ZpKxmIJKcgGwt6q2jjrLAt5WVW9i9ls/P9JN442DI4A3AV+qqjOA/wHG5nwVQDet817gX0edZb8kJzA7o3Aq8CrgmCR/0e/xxrHAXaLfp25++Sbg+qq6edR55tP9M/su4LxRZ+mcBby3m2v+GnB2kn8ZbaTndCM2qmovcAuzU4zjYBewa86/pG5kttDHybuB+6rqsVEHmeOdwE+qaqaq/g+4GfjTfg82jgXuEv0+dCcKrwGmq+oLo84zV5KJJMd3j49m9gT1w6NNNauqrqiqVVW1mtk/a9+pqr5HRIOU5JjuhDTd9MS76PFrH4etqn4J/DzJ67tN5wAjP2F+gIsZo+mTzs+AtyR5Wfd39hxmz1f1ZezuibkMS/T7luQG4B3AiUl2AZ+qqmtGm+r3zgI+BGzv5poBPllVt48w034rgc3dFQEvAbZU1VhdrjemTgJumf17zhHAV6vqW6ON9Dx/DVzfDbQeBf5yxHl+r/sf3rnAh0edZa6qujfJjcB9wD7gfpawrH7sLiOUJPVmHKdQJEk9sMAlqVEWuCQ1ygKXpEZZ4JLUKAtckhplgUtSo/4f/wVTKgh22i0AAAAASUVORK5CYII=\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": "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\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/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 From 9823f4ecf5e01874399aaa1cc03b3b958aa9b3b4 Mon Sep 17 00:00:00 2001 From: Joe James Date: Thu, 28 Oct 2021 17:23:40 -0700 Subject: [PATCH 70/75] Delete temp --- Iris Dataset/temp | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Iris Dataset/temp diff --git a/Iris Dataset/temp b/Iris Dataset/temp deleted file mode 100644 index 9c595a6f..00000000 --- a/Iris Dataset/temp +++ /dev/null @@ -1 +0,0 @@ -temp From ca9255abe4f071632a89caaf684719488f3525ff Mon Sep 17 00:00:00 2001 From: Joe James Date: Sat, 6 Nov 2021 13:12:09 -0700 Subject: [PATCH 71/75] Add Iris KNN notebook --- Iris Dataset/KNN-IrisData.ipynb | 629 ++++++++++++++++++++++++++++++++ 1 file changed, 629 insertions(+) create mode 100644 Iris Dataset/KNN-IrisData.ipynb 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 +} From 87f407702a4a8ba18591daeb10fb8a1e5fced93d Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 1 May 2023 12:35:08 -0700 Subject: [PATCH 72/75] Add files via upload --- flatten_list.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 flatten_list.py 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)) + + From 57dd4054fa11b8188cb414453e12541fd7b0adf8 Mon Sep 17 00:00:00 2001 From: Joe James Date: Tue, 9 May 2023 11:04:27 -0700 Subject: [PATCH 73/75] Add files via upload --- dict_comprehensions.py | 54 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 dict_comprehensions.py 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) + + + + From 4f3e3a8180e9f9f0ce41ef12ea6d716510c4d7c7 Mon Sep 17 00:00:00 2001 From: Joe James Date: Thu, 11 May 2023 12:11:57 -0700 Subject: [PATCH 74/75] Add files via upload --- remove_from_list.py | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 remove_from_list.py 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) + + + + + + + + From fa2904f71169871485b5fec8f0be0441a8b23f1a Mon Sep 17 00:00:00 2001 From: Joe James Date: Mon, 15 May 2023 11:07:11 -0700 Subject: [PATCH 75/75] Add files via upload --- deep_copy.ipynb | 248 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 deep_copy.ipynb 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 +}