From ba1b1c0800e6c51dcbec5e9310ed018d4ce47095 Mon Sep 17 00:00:00 2001 From: Hui-Min Wang <38481514+Hem-W@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:17:54 +0800 Subject: [PATCH 1/7] Create binder.yml --- .github/workflows/binder.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/binder.yml diff --git a/.github/workflows/binder.yml b/.github/workflows/binder.yml new file mode 100644 index 0000000..232ad2a --- /dev/null +++ b/.github/workflows/binder.yml @@ -0,0 +1,16 @@ +name: Build Notebook Container +on: [push] # You may want to trigger this Action on other things than a push. +jobs: + build: + runs-on: ubuntu-latest + steps: + + - name: checkout files in repo + uses: actions/checkout@master + + - name: update jupyter dependencies with repo2docker + uses: jupyterhub/repo2docker-action@0.2 + with: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + MYBINDERORG_CACHE: true From 7dab57204369b990a076f61644b45b2e852ea511 Mon Sep 17 00:00:00 2001 From: Hui-Min Wang <38481514+Hem-W@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:27:05 +0800 Subject: [PATCH 2/7] Update binder.yml --- .github/workflows/binder.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/binder.yml b/.github/workflows/binder.yml index 232ad2a..6d24512 100644 --- a/.github/workflows/binder.yml +++ b/.github/workflows/binder.yml @@ -4,13 +4,15 @@ jobs: build: runs-on: ubuntu-latest steps: - - - name: checkout files in repo - uses: actions/checkout@master + - name: Checkout Code + uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: update jupyter dependencies with repo2docker - uses: jupyterhub/repo2docker-action@0.2 + uses: jupyterhub/repo2docker-action@master with: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} - MYBINDERORG_CACHE: true + BINDER_CACHE: true + PUBLIC_REGISTRY_CHECK: true From 643073d373f7abd77976dfcb877562daee9ffce0 Mon Sep 17 00:00:00 2001 From: Hui-Min Wang <38481514+Hem-W@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:06:44 +0800 Subject: [PATCH 3/7] Update binder.yml --- .github/workflows/binder.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/binder.yml b/.github/workflows/binder.yml index 6d24512..7538c96 100644 --- a/.github/workflows/binder.yml +++ b/.github/workflows/binder.yml @@ -6,8 +6,6 @@ jobs: steps: - name: Checkout Code uses: actions/checkout@v2 - with: - ref: ${{ github.event.pull_request.head.sha }} - name: update jupyter dependencies with repo2docker uses: jupyterhub/repo2docker-action@master From 76e22b71600dcb0348eefe3e5e60012276965747 Mon Sep 17 00:00:00 2001 From: Hui-Min Wang <38481514+Hem-W@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:12:40 +0800 Subject: [PATCH 4/7] Update binder.yml --- .github/workflows/binder.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/binder.yml b/.github/workflows/binder.yml index 7538c96..0eb83a5 100644 --- a/.github/workflows/binder.yml +++ b/.github/workflows/binder.yml @@ -10,7 +10,7 @@ jobs: - name: update jupyter dependencies with repo2docker uses: jupyterhub/repo2docker-action@master with: - DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} - BINDER_CACHE: true - PUBLIC_REGISTRY_CHECK: true + NO_PUSH: true + MYBINDERORG_TAG: ${{ github.event.pull_request.head.ref }} + # BINDER_CACHE: true + # PUBLIC_REGISTRY_CHECK: true From 8d4625d696d689425f543ead3054bd53878e9b4e Mon Sep 17 00:00:00 2001 From: Hui-Min Wang <38481514+Hem-W@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:42:04 +0800 Subject: [PATCH 5/7] Update binder.yml --- .github/workflows/binder.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/binder.yml b/.github/workflows/binder.yml index 0eb83a5..ff8601e 100644 --- a/.github/workflows/binder.yml +++ b/.github/workflows/binder.yml @@ -12,5 +12,6 @@ jobs: with: NO_PUSH: true MYBINDERORG_TAG: ${{ github.event.pull_request.head.ref }} + IMAGE_NAME: ${{ github.repository }} # BINDER_CACHE: true # PUBLIC_REGISTRY_CHECK: true From 14436c2414f38caf7c0115c476ce0f13aa287a4a Mon Sep 17 00:00:00 2001 From: Hui-Min Wang <38481514+Hem-W@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:51:25 +0800 Subject: [PATCH 6/7] Update binder.yml --- .github/workflows/binder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/binder.yml b/.github/workflows/binder.yml index ff8601e..b31589a 100644 --- a/.github/workflows/binder.yml +++ b/.github/workflows/binder.yml @@ -12,6 +12,6 @@ jobs: with: NO_PUSH: true MYBINDERORG_TAG: ${{ github.event.pull_request.head.ref }} - IMAGE_NAME: ${{ github.repository }} + IMAGE_NAME: xiaoganghe/python-climate-visuals # fixed var because Docker not allow uppercases # BINDER_CACHE: true # PUBLIC_REGISTRY_CHECK: true From 8f07fd5a4ef13d060288c55cf43fce9cc0e95cd7 Mon Sep 17 00:00:00 2001 From: Niu Zhixiao Date: Wed, 11 Oct 2023 19:07:22 +0800 Subject: [PATCH 7/7] update solutions upload solutions for tutorial Python & NumPy --- _toc.yml | 8 +- chapters/data-analytics/numpy-solution.ipynb | 109 +++++++++ chapters/data-analytics/python-solution.ipynb | 221 ++++++++++++++++++ 3 files changed, 334 insertions(+), 4 deletions(-) create mode 100644 chapters/data-analytics/numpy-solution.ipynb create mode 100644 chapters/data-analytics/python-solution.ipynb diff --git a/_toc.yml b/_toc.yml index d0c7bca..8e9c7d9 100644 --- a/_toc.yml +++ b/_toc.yml @@ -13,8 +13,8 @@ parts: title: Tutorial - file: chapters/data-analytics/python-exercise title: Exercise - #- file: chapters/data-analytics/python-solution - #title: Solution + - file: chapters/data-analytics/python-solution + title: Solution - file: chapters/data-analytics/numpy title: NumPy sections: @@ -22,8 +22,8 @@ parts: title: Tutorial - file: chapters/data-analytics/numpy-exercise title: Exercise - #- file: chapters/data-analytics/numpy-solution - #title: Solution + - file: chapters/data-analytics/numpy-solution + title: Solution - file: chapters/data-analytics/pandas title: Pandas sections: diff --git a/chapters/data-analytics/numpy-solution.ipynb b/chapters/data-analytics/numpy-solution.ipynb new file mode 100644 index 0000000..a2ffd96 --- /dev/null +++ b/chapters/data-analytics/numpy-solution.ipynb @@ -0,0 +1,109 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5202ee2c", + "metadata": {}, + "source": [ + "# NumPy Solution" + ] + }, + { + "cell_type": "markdown", + "id": "fe90719f", + "metadata": {}, + "source": [ + "## Task\n", + "In machine learning tasks, when we deal with data from different features, it is very common that we need to normalize data so that the different units among features would not affect the performances of machine learning algorithms.\n", + "\n", + "Now we have temperature and precipitation observations from 7 sites. Write a line of code to accomplish Min-Max normalization for each feature.\n", + "\n", + "Hint: The equation of Min-Max normalization to $x$ is \n", + "$\n", + "\\begin{align}\n", + "x_{norm} = \\frac{x-\\min(x)}{\\max(x)-\\min(x)}\n", + "\\end{align}\n", + "$" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3ae47cdd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.08860759, 0.39240506, 1. , 0. , 0.48101266,\n", + " 0.6835443 , 0.72151899],\n", + " [0.69892473, 0.07168459, 0.28673835, 0.34050179, 0. ,\n", + " 1. , 0.43010753]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "data = np.array([[25.1, 27.5, 32.3, 24.4, 28.2, 29.8, 30.1], # a row of temperature\n", + " [20.0, 2.5, 8.5, 10.0, 0.5, 28.4, 12.5]]) # a row of precipitation\n", + "\n", + "# Your solution goes here.\n", + "norm = (data - np.min(data, axis=1).reshape(2, 1)) / np.ptp(data, axis=1).reshape(2, 1)" + ] + } + ], + "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.9.12" + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/chapters/data-analytics/python-solution.ipynb b/chapters/data-analytics/python-solution.ipynb new file mode 100644 index 0000000..2038ff2 --- /dev/null +++ b/chapters/data-analytics/python-solution.ipynb @@ -0,0 +1,221 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5202ee2c", + "metadata": {}, + "source": [ + "# Solutions to Python Exercise" + ] + }, + { + "cell_type": "markdown", + "id": "6fcaf59d", + "metadata": {}, + "source": [ + ":::{note} *The solution to each task is not exclusive*. Depending on the purpose of our programming, we may wish our scripts to be intuitive or concise or fast or flexible. There should be many other ways to accomplish the following programming tasks." + ] + }, + { + "cell_type": "markdown", + "id": "fe90719f", + "metadata": {}, + "source": [ + "## Task 1 (Containers)\n", + "For a list which contains three sublists `precipitation = [[0, 0, 3.0], [1.1, 4.8, 0], [0, 0, 0]]`, write a program to find the maximum for each sublist and print it as a dictionary whose key is `sublist_n` (where `n` is the index of sublist) and value is the corresponding maximum. \n", + "\n", + "Hint: use `max()` to obtain the maximum of a list. You could also try to use dictionary comprehension to accomplish this task within one line of code." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3ae47cdd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'sublist_0': 3.0, 'sublist_1': 4.8, 'sublist_2': 0}\n" + ] + } + ], + "source": [ + "# Your solution goes here.\n", + "\n", + "precipitation = [[0, 0, 3.0], [1.1, 4.8, 0], [0, 0, 0]]\n", + "\n", + "print({\"sublist_{}\".format(x): max(precipitation[x]) for x in range(0, len(precipitation))})" + ] + }, + { + "cell_type": "markdown", + "id": "2703e903", + "metadata": {}, + "source": [ + ":::{note} `len()` is a Python built-in function that returns the number of elements in a list. We may use `help(len)` to see the description and usage of this function." + ] + }, + { + "cell_type": "markdown", + "id": "69ba12e4", + "metadata": {}, + "source": [ + "## Task 2 (Control flows)\n", + "Write a program to print all prime numbers within the range `range(25, 50)`.\n", + "\n", + "Hint: a prime number is a natural number greater than 1 that is not a product of two smaller natural numbers. You may wish to use the following statements:\n", + "+ use `for num in range(25, 50)` to iterate over all numbers;\n", + "+ for a specific number, use `for i in range(2, num)` to iterate over potential factors except 1;\n", + "+ use `(num % i) == 0` to determine whether `i` is truly a factor of `num` (if it is true, `num` is not a prime number); and\n", + "+ use `break` to stop one loop." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2b40dc9f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "29\n", + "31\n", + "37\n", + "41\n", + "43\n", + "47\n" + ] + } + ], + "source": [ + "# Your solution goes here.\n", + "\n", + "for num in range(25, 50):\n", + " if num > 1: # all prime numbers are greater than 1\n", + " for i in range(2, num): # check for factors\n", + " if (num % i) == 0: # not a prime number, so break inner loop\n", + " break\n", + " else:\n", + " print(num)" + ] + }, + { + "cell_type": "markdown", + "id": "39b0cec5", + "metadata": {}, + "source": [ + ":::{note} It is not common to use `for-else` loops. `else` here means that the following algorithms will be run when the `for` loop ends. Normally, if we want to run specific algorithms after loops, we just need to script them after loops. However, if `break` exists in the loop, the algorithms in `else` will not execute when `break` happens, because the loop do not reach its end. Thus, `for-else` loops is useful only when there exists `break` statements within loops.\n", + "\n", + "In addition, please mind the indents before each line. Python relies on indents to identify code blocks, so a wrong slip in indents may cause errors or even unanticipated results. You may try adding indents before `else:` and `print(num)` to see what will happen." + ] + }, + { + "cell_type": "markdown", + "id": "90b49490", + "metadata": {}, + "source": [ + "## Task 3 (Functions)\n", + "Following Task 2, define a function that returns the list of prime numbers for a specified range. Then, use this function to print the prime numbers within the ranges `range(25, 50)` and `range(50, 100)` respectively.\n", + "\n", + "Hint: in the function, you may define an empty list `prime_num = []` at first and use the `append` method to add prime numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d0d5b046", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[29, 31, 37, 41, 43, 47]\n", + "[53, 59, 61, 67, 71, 73, 79, 83, 89, 97]\n" + ] + } + ], + "source": [ + "# Your solution goes here.\n", + "\n", + "def findprime(rangelist):\n", + " prime_num = []\n", + " for num in rangelist:\n", + " if num > 1:\n", + " for i in range(2, num):\n", + " if (num % i) == 0:\n", + " break\n", + " else:\n", + " prime_num.append(num)\n", + " return prime_num\n", + "\n", + "\n", + "print(findprime(range(25, 50)))\n", + "print(findprime(range(50, 100)))" + ] + }, + { + "cell_type": "markdown", + "id": "13043cf3", + "metadata": {}, + "source": [ + "## Bonus Task\n", + "Still remember the example `quicksort()` programming at the beginning of Python Tutorial? Try to comprehend how this function sorts a list. This function was run in a recursive manner (i.e. the function was used within its own codes). This brings effects quite alike as loops; you could try adding a printing function `print(left, middle, right)` to see what happened in each step." + ] + } + ], + "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.8.8" + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}