├── .gitignore ├── README.md ├── archive ├── anotherfile.txt ├── lecture1_with_notes.ipynb ├── lecture2_with_notes.ipynb ├── lecture3.ipynb ├── lecture3_with_notes.ipynb ├── lecture4.ipynb ├── lecture4_with_notes.ipynb ├── lecture5.ipynb ├── lecture5_with_notes.ipynb ├── myfile.txt └── yetanotherfile.txt ├── data ├── 20000101_20161231-NO2.csv ├── bikes.csv └── titanic.csv ├── lecture1.ipynb ├── lecture1_with_notes.ipynb ├── lecture2.ipynb ├── lecture2_with_notes.ipynb ├── lecture3.ipynb ├── lecture3_with_notes.ipynb ├── lecture4.ipynb └── lecture4_with_notes.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | __pycache__/ 3 | *.html 4 | build 5 | dist 6 | pynare.egg-info 7 | .ipynb_checkpoints/ 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # ![Logo](https://avatars3.githubusercontent.com/u/37739145?s=60&v=4) OSE Computing Primer 3 | 4 | by [Gregor Boehl](https://gregorboehl.com). 5 | 6 | This course is a generic introduction to (scientific) programming in economics, covering the essentials: 7 | 8 | * variables 9 | * conditionals 10 | * loops 11 | * functions 12 | * scientific programming (with `numpy`) 13 | * plotting 14 | * basics of data analysis (with `pandas`) 15 | * some perspectives (performance, parallelization, ...) 16 | 17 | The examples cover Python code. 18 | 19 | We will conduct all course communications using [Zulip](https://zulip.com/), so please be sure to join us there. Simply clicking the button below will take you to the proper channel. There I also post the link to the online lectures using [ZOOM](https://zoom.us/). 20 | 21 | [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://bonn-econ-teaching.zulipchat.com/#narrow/stream/284046-Computing-Primer.202021) 22 | 23 | 24 | Timeline 25 | -------- 26 | 27 | | Date (Thursday 12:15 pm) | Topic | 28 | | ----------| --------------------------------------------------------- | 29 | | 15/04/21 | Installation (by Prof. v. Gaudecker) | 30 | | 22/04/21 | Introduction + basic types | 31 | | 29/04/21 | Loops and functions | 32 | | 06/05/21 | Scientific programming | 33 | | 20/05/21 | Plotting + Basics in data science | 34 | | 27/05/21 | Perspectives | 35 | 36 | 37 | Ressources 38 | ---------- 39 | 40 | * the OSE [repos](https://ose-resources.readthedocs.io/en/latest/miscellaneous.html) 41 | * the [QuantEcon](https://python.quantecon.org/) Initative 42 | * Prof. [google](https://google.com) is your very best friend 43 | * ... 44 | 45 | ### lecture 1 (introduction): 46 | 47 | * motivation 48 | * `"hello wörld"` 49 | * variables & lists 50 | * strings 51 | * conditionals 52 | * where to get help (aka. how-to-google-errors) 53 | 54 | ### lecture 2 (loops and functions) 55 | 56 | * collections (tuples + dicts) 57 | * mutability 58 | * loops 59 | * functions 60 | 61 | ### lecture 3 (scientific programming): 62 | 63 | * numpy 64 | * linear algebra 65 | 66 | ### lecture 4 (data science): 67 | 68 | * plotting 69 | * pandas 70 | * loading data 71 | 72 | ### lecture 5 (perspectives): 73 | 74 | * optimization 75 | * distributions 76 | * debugging 77 | * further sources/resources 78 | * modules 79 | * optional stuff (history of programming in econ, which language is for me? IDEs, ...) 80 | -------------------------------------------------------------------------------- /archive/anotherfile.txt: -------------------------------------------------------------------------------- 1 | a new file! How awesome -------------------------------------------------------------------------------- /archive/lecture3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Lecture 3: Scientific programming" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Content\n", 15 | " \n", 16 | "* Summary of lecture 2\n", 17 | "* `numpy`: \n", 18 | " * the `array`\n", 19 | " * indexing\n", 20 | " * some standard operations/methods\n", 21 | " * linear algebra `<3`\n", 22 | "* plotting with `matplotlib`\n", 23 | "* `scipy`:\n", 24 | " * distributions\n", 25 | " * Nonlinear solvers\n", 26 | " * Nonlinear optimization" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## Summary of lecture 2\n", 34 | "\n", 35 | "* Collections: `tuple` & `dict`\n", 36 | "* Mutabillity\n", 37 | "* Loops: `for`\n", 38 | "& `while` loop\n", 39 | "* Functions" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 55, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "#" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": { 54 | "colab_type": "text", 55 | "id": "3cfrOV4dL9hW" 56 | }, 57 | "source": [ 58 | "## Numpy" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": { 64 | "colab_type": "text", 65 | "id": "fY12nHhyL9hX" 66 | }, 67 | "source": [ 68 | "Numpy is the core library for scientific computing in Python. It provides a high-performance multidimensional array object, and tools for working with these arrays. If you are already familiar with MATLAB, you might find this [tutorial](http://wiki.scipy.org/NumPy_for_Matlab_Users) useful to get started with Numpy." 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "The `numpy` package (module) is used in almost all numerical computation using Python. It is a package that provide high-performance vector, matrix and higher-dimensional data structures for Python. It is implemented in C and Fortran so when calculations are vectorized (formulated with vectors and matrices), performance is very good. \n", 76 | "\n", 77 | "To use `numpy` you need to import the module, using for example:" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 29, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "import numpy as np" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "In the `numpy` package the terminology used for vectors, matrices and higher-dimensional data sets is *array*. \n", 94 | "\n" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "## Creating `numpy` arrays" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "There are a number of ways to initialize new numpy arrays, for example from\n", 109 | "\n", 110 | "* a Python list or tuples\n", 111 | "* using functions that are dedicated to generating numpy arrays, such as `arange`, `linspace`, etc.\n", 112 | "* reading data from files" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "### From lists/tuples" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "For example, to create new vector and matrix arrays from Python lists we can use the `numpy.array` function." 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 1, 132 | "metadata": {}, 133 | "outputs": [], 134 | "source": [ 135 | "#" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "The `v` and `M` objects are both of the type `ndarray` that the `numpy` module provides." 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 5, 148 | "metadata": {}, 149 | "outputs": [ 150 | { 151 | "data": { 152 | "text/plain": [ 153 | "(numpy.ndarray, numpy.ndarray)" 154 | ] 155 | }, 156 | "execution_count": 5, 157 | "metadata": {}, 158 | "output_type": "execute_result" 159 | } 160 | ], 161 | "source": [ 162 | "#" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "The difference between the `v` and `M` arrays is only their shapes. We can get information about the shape of an array by using the `ndarray.shape` property." 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 3, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [ 178 | "#" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "Equivalently, we could use the function `numpy.shape`" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": 5, 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "#" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "So far the `numpy.ndarray` looks awefully much like a Python list (or nested list). Why not simply use Python lists for computations instead of creating a new array type? \n", 202 | "\n", 203 | "There are several reasons:\n", 204 | "\n", 205 | "* Python lists are very general. They can contain any kind of object. They are dynamically typed. They do not support mathematical functions such as matrix and dot multiplications, etc. Implementing such functions for Python lists would not be very efficient because of the dynamic typing.\n", 206 | "* Numpy arrays are **statically typed** and **homogeneous**. The type of the elements is determined when the array is created.\n", 207 | "* Numpy arrays are memory efficient.\n", 208 | "* Because of the static typing, fast implementation of mathematical functions such as multiplication and addition of `numpy` arrays can be implemented in a compiled language (C and Fortran is used).\n", 209 | "\n", 210 | "Using the `dtype` (data type) property of an `ndarray`, we can see what type the data of an array has:" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": 6, 216 | "metadata": {}, 217 | "outputs": [], 218 | "source": [ 219 | "#" 220 | ] 221 | }, 222 | { 223 | "cell_type": "markdown", 224 | "metadata": {}, 225 | "source": [ 226 | "We get an error if we try to assign a value of the wrong type to an element in a numpy array:" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 7, 232 | "metadata": {}, 233 | "outputs": [], 234 | "source": [ 235 | "#" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "### Using array-generating functions" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "For larger arrays it is inpractical to initialize the data manually, using explicit python lists. Instead we can use one of the many functions in `numpy` that generate arrays of different forms. Some of the more common are:" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": {}, 255 | "source": [ 256 | "#### `np.arange`" 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": 8, 262 | "metadata": {}, 263 | "outputs": [], 264 | "source": [ 265 | "#" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "#### `np.linspace`" 273 | ] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "execution_count": 9, 278 | "metadata": {}, 279 | "outputs": [], 280 | "source": [ 281 | "#" 282 | ] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "metadata": {}, 287 | "source": [ 288 | "#### random data" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": 10, 294 | "metadata": {}, 295 | "outputs": [], 296 | "source": [ 297 | "#" 298 | ] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "metadata": {}, 303 | "source": [ 304 | "#### zeros and ones" 305 | ] 306 | }, 307 | { 308 | "cell_type": "code", 309 | "execution_count": 26, 310 | "metadata": {}, 311 | "outputs": [ 312 | { 313 | "data": { 314 | "text/plain": [ 315 | "array([[ 0., 0., 0.],\n", 316 | " [ 0., 0., 0.],\n", 317 | " [ 0., 0., 0.]])" 318 | ] 319 | }, 320 | "execution_count": 26, 321 | "metadata": {}, 322 | "output_type": "execute_result" 323 | } 324 | ], 325 | "source": [ 326 | "#" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "metadata": {}, 332 | "source": [ 333 | "#### Creating arrays: Exercises" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "a) Create an array with only even numbers of lengh 10." 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": 9, 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [ 349 | "#" 350 | ] 351 | }, 352 | { 353 | "cell_type": "markdown", 354 | "metadata": {}, 355 | "source": [ 356 | "b) Create an array of `[0,10,...,100]`." 357 | ] 358 | }, 359 | { 360 | "cell_type": "code", 361 | "execution_count": null, 362 | "metadata": {}, 363 | "outputs": [], 364 | "source": [ 365 | "#" 366 | ] 367 | }, 368 | { 369 | "cell_type": "markdown", 370 | "metadata": {}, 371 | "source": [ 372 | "## Manipulating arrays" 373 | ] 374 | }, 375 | { 376 | "cell_type": "markdown", 377 | "metadata": {}, 378 | "source": [ 379 | "### Indexing" 380 | ] 381 | }, 382 | { 383 | "cell_type": "markdown", 384 | "metadata": {}, 385 | "source": [ 386 | "We can index elements in an array using square brackets and indices:" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": 11, 392 | "metadata": {}, 393 | "outputs": [], 394 | "source": [ 395 | "#" 396 | ] 397 | }, 398 | { 399 | "cell_type": "markdown", 400 | "metadata": {}, 401 | "source": [ 402 | "If we omit an index of a multidimensional array it returns the whole row (or, in general, a N-1 dimensional array) " 403 | ] 404 | }, 405 | { 406 | "cell_type": "code", 407 | "execution_count": 12, 408 | "metadata": {}, 409 | "outputs": [], 410 | "source": [ 411 | "#" 412 | ] 413 | }, 414 | { 415 | "cell_type": "markdown", 416 | "metadata": {}, 417 | "source": [ 418 | "The same thing can be achieved with using `:` instead of an index: " 419 | ] 420 | }, 421 | { 422 | "cell_type": "code", 423 | "execution_count": 13, 424 | "metadata": {}, 425 | "outputs": [], 426 | "source": [ 427 | "#" 428 | ] 429 | }, 430 | { 431 | "cell_type": "markdown", 432 | "metadata": {}, 433 | "source": [ 434 | "We can assign new values to elements in an array using indexing:" 435 | ] 436 | }, 437 | { 438 | "cell_type": "code", 439 | "execution_count": 14, 440 | "metadata": {}, 441 | "outputs": [], 442 | "source": [ 443 | "#" 444 | ] 445 | }, 446 | { 447 | "cell_type": "markdown", 448 | "metadata": {}, 449 | "source": [ 450 | "### Index slicing" 451 | ] 452 | }, 453 | { 454 | "cell_type": "markdown", 455 | "metadata": {}, 456 | "source": [ 457 | "Index slicing is the technical name for the syntax `M[lower:upper:step]` to extract part of an array:" 458 | ] 459 | }, 460 | { 461 | "cell_type": "code", 462 | "execution_count": 15, 463 | "metadata": {}, 464 | "outputs": [], 465 | "source": [ 466 | "#" 467 | ] 468 | }, 469 | { 470 | "cell_type": "markdown", 471 | "metadata": {}, 472 | "source": [ 473 | "Array slices are *mutable*: if they are assigned a new value the original array from which the slice was extracted is modified:" 474 | ] 475 | }, 476 | { 477 | "cell_type": "code", 478 | "execution_count": 16, 479 | "metadata": {}, 480 | "outputs": [], 481 | "source": [ 482 | "#" 483 | ] 484 | }, 485 | { 486 | "cell_type": "markdown", 487 | "metadata": {}, 488 | "source": [ 489 | "We can omit any of the three parameters in `M[lower:upper:step]`:" 490 | ] 491 | }, 492 | { 493 | "cell_type": "code", 494 | "execution_count": 17, 495 | "metadata": {}, 496 | "outputs": [], 497 | "source": [ 498 | "#" 499 | ] 500 | }, 501 | { 502 | "cell_type": "markdown", 503 | "metadata": {}, 504 | "source": [ 505 | "Negative indices counts from the end of the array (positive index from the begining):" 506 | ] 507 | }, 508 | { 509 | "cell_type": "code", 510 | "execution_count": 18, 511 | "metadata": {}, 512 | "outputs": [], 513 | "source": [ 514 | "#" 515 | ] 516 | }, 517 | { 518 | "cell_type": "markdown", 519 | "metadata": {}, 520 | "source": [ 521 | "Index slicing works exactly the same way for multidimensional arrays:" 522 | ] 523 | }, 524 | { 525 | "cell_type": "code", 526 | "execution_count": 19, 527 | "metadata": {}, 528 | "outputs": [], 529 | "source": [ 530 | "#" 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": {}, 536 | "source": [ 537 | "### Fancy indexing" 538 | ] 539 | }, 540 | { 541 | "cell_type": "markdown", 542 | "metadata": {}, 543 | "source": [ 544 | "Fancy indexing is the name for when an array or list is used in-place of an index: " 545 | ] 546 | }, 547 | { 548 | "cell_type": "code", 549 | "execution_count": 20, 550 | "metadata": {}, 551 | "outputs": [], 552 | "source": [ 553 | "#" 554 | ] 555 | }, 556 | { 557 | "cell_type": "markdown", 558 | "metadata": {}, 559 | "source": [ 560 | "We can also use index masks: If the index mask is an Numpy array of data type `bool`, then an element is selected (True) or not (False) depending on the value of the index mask at the position of each element: " 561 | ] 562 | }, 563 | { 564 | "cell_type": "code", 565 | "execution_count": 21, 566 | "metadata": {}, 567 | "outputs": [], 568 | "source": [ 569 | "#" 570 | ] 571 | }, 572 | { 573 | "cell_type": "markdown", 574 | "metadata": {}, 575 | "source": [ 576 | "This feature is very useful to conditionally select elements from an array, using for example comparison operators:" 577 | ] 578 | }, 579 | { 580 | "cell_type": "code", 581 | "execution_count": 22, 582 | "metadata": {}, 583 | "outputs": [], 584 | "source": [ 585 | "#" 586 | ] 587 | }, 588 | { 589 | "cell_type": "markdown", 590 | "metadata": {}, 591 | "source": [ 592 | "#### Exercises: indexing\n", 593 | "a) create an array `a` from 0 to 9" 594 | ] 595 | }, 596 | { 597 | "cell_type": "code", 598 | "execution_count": 11, 599 | "metadata": {}, 600 | "outputs": [], 601 | "source": [ 602 | "#" 603 | ] 604 | }, 605 | { 606 | "cell_type": "markdown", 607 | "metadata": {}, 608 | "source": [ 609 | "b) get only the first 3 values of `a`" 610 | ] 611 | }, 612 | { 613 | "cell_type": "code", 614 | "execution_count": 12, 615 | "metadata": {}, 616 | "outputs": [], 617 | "source": [ 618 | "#" 619 | ] 620 | }, 621 | { 622 | "cell_type": "markdown", 623 | "metadata": {}, 624 | "source": [ 625 | "c) create a random array `b` of size 9 with $b_i \\sim N(0,1)$." 626 | ] 627 | }, 628 | { 629 | "cell_type": "code", 630 | "execution_count": null, 631 | "metadata": {}, 632 | "outputs": [], 633 | "source": [ 634 | "#" 635 | ] 636 | }, 637 | { 638 | "cell_type": "markdown", 639 | "metadata": {}, 640 | "source": [ 641 | "d) get all the values of `b` that are larger than one." 642 | ] 643 | }, 644 | { 645 | "cell_type": "code", 646 | "execution_count": 13, 647 | "metadata": {}, 648 | "outputs": [], 649 | "source": [ 650 | "#" 651 | ] 652 | }, 653 | { 654 | "cell_type": "markdown", 655 | "metadata": {}, 656 | "source": [ 657 | "## Some standard operations" 658 | ] 659 | }, 660 | { 661 | "cell_type": "markdown", 662 | "metadata": {}, 663 | "source": [ 664 | "Lets us create some very precious data that we want to learn more about." 665 | ] 666 | }, 667 | { 668 | "cell_type": "code", 669 | "execution_count": 23, 670 | "metadata": {}, 671 | "outputs": [], 672 | "source": [ 673 | "#" 674 | ] 675 | }, 676 | { 677 | "cell_type": "markdown", 678 | "metadata": {}, 679 | "source": [ 680 | "#### sum" 681 | ] 682 | }, 683 | { 684 | "cell_type": "code", 685 | "execution_count": 24, 686 | "metadata": {}, 687 | "outputs": [], 688 | "source": [ 689 | "#" 690 | ] 691 | }, 692 | { 693 | "cell_type": "markdown", 694 | "metadata": {}, 695 | "source": [ 696 | "#### mean" 697 | ] 698 | }, 699 | { 700 | "cell_type": "code", 701 | "execution_count": 25, 702 | "metadata": {}, 703 | "outputs": [], 704 | "source": [ 705 | "#" 706 | ] 707 | }, 708 | { 709 | "cell_type": "markdown", 710 | "metadata": {}, 711 | "source": [ 712 | "#### standard deviations and variance" 713 | ] 714 | }, 715 | { 716 | "cell_type": "code", 717 | "execution_count": 26, 718 | "metadata": {}, 719 | "outputs": [], 720 | "source": [ 721 | "#" 722 | ] 723 | }, 724 | { 725 | "cell_type": "markdown", 726 | "metadata": {}, 727 | "source": [ 728 | "#### min and max" 729 | ] 730 | }, 731 | { 732 | "cell_type": "code", 733 | "execution_count": 27, 734 | "metadata": {}, 735 | "outputs": [], 736 | "source": [ 737 | "#" 738 | ] 739 | }, 740 | { 741 | "cell_type": "markdown", 742 | "metadata": {}, 743 | "source": [ 744 | "Many other functions and methods in the `array` and `matrix` classes accept the same (optional) `axis` keyword argument." 745 | ] 746 | }, 747 | { 748 | "cell_type": "code", 749 | "execution_count": 28, 750 | "metadata": {}, 751 | "outputs": [], 752 | "source": [ 753 | "#" 754 | ] 755 | }, 756 | { 757 | "cell_type": "markdown", 758 | "metadata": {}, 759 | "source": [ 760 | "### Reshaping and stacking arrays" 761 | ] 762 | }, 763 | { 764 | "cell_type": "markdown", 765 | "metadata": {}, 766 | "source": [ 767 | "The shape of an Numpy array can be modified without copying the underlaying data, which makes it a fast operation even for large arrays. Let us create `A`." 768 | ] 769 | }, 770 | { 771 | "cell_type": "code", 772 | "execution_count": 30, 773 | "metadata": {}, 774 | "outputs": [], 775 | "source": [ 776 | "#" 777 | ] 778 | }, 779 | { 780 | "cell_type": "markdown", 781 | "metadata": {}, 782 | "source": [ 783 | "#### Standard operations: exercises\n", 784 | "a) create a random array `b` of size 9 with $b_i \\sim N(0,1)$." 785 | ] 786 | }, 787 | { 788 | "cell_type": "code", 789 | "execution_count": 14, 790 | "metadata": {}, 791 | "outputs": [], 792 | "source": [ 793 | "#" 794 | ] 795 | }, 796 | { 797 | "cell_type": "markdown", 798 | "metadata": {}, 799 | "source": [ 800 | "b) get the lowest and highest value of `b`." 801 | ] 802 | }, 803 | { 804 | "cell_type": "code", 805 | "execution_count": 15, 806 | "metadata": {}, 807 | "outputs": [], 808 | "source": [ 809 | "#" 810 | ] 811 | }, 812 | { 813 | "cell_type": "markdown", 814 | "metadata": {}, 815 | "source": [ 816 | "c) create an array `c` of size 9 and stack it horizontally on `b`. Call the result `d`." 817 | ] 818 | }, 819 | { 820 | "cell_type": "code", 821 | "execution_count": 17, 822 | "metadata": {}, 823 | "outputs": [], 824 | "source": [ 825 | "#" 826 | ] 827 | }, 828 | { 829 | "cell_type": "markdown", 830 | "metadata": {}, 831 | "source": [ 832 | "d) get the mean of `d`." 833 | ] 834 | }, 835 | { 836 | "cell_type": "code", 837 | "execution_count": 18, 838 | "metadata": {}, 839 | "outputs": [], 840 | "source": [ 841 | "#" 842 | ] 843 | }, 844 | { 845 | "cell_type": "markdown", 846 | "metadata": {}, 847 | "source": [ 848 | "## Copy and \"deep copy\"" 849 | ] 850 | }, 851 | { 852 | "cell_type": "markdown", 853 | "metadata": {}, 854 | "source": [ 855 | "To achieve high performance, assignments in Python usually do not copy the underlaying objects. This is important for example when objects are passed between functions, to avoid an excessive amount of memory copying when it is not necessary (technical term: pass by reference). " 856 | ] 857 | }, 858 | { 859 | "cell_type": "code", 860 | "execution_count": 31, 861 | "metadata": {}, 862 | "outputs": [], 863 | "source": [ 864 | "#" 865 | ] 866 | }, 867 | { 868 | "cell_type": "markdown", 869 | "metadata": {}, 870 | "source": [ 871 | "If we want to avoid this behavior, so that when we get a new completely independent object `B` copied from `A`, then we need to do a so-called \"deep copy\" using the function `copy`:" 872 | ] 873 | }, 874 | { 875 | "cell_type": "code", 876 | "execution_count": 32, 877 | "metadata": {}, 878 | "outputs": [], 879 | "source": [ 880 | "#" 881 | ] 882 | }, 883 | { 884 | "cell_type": "markdown", 885 | "metadata": {}, 886 | "source": [ 887 | "## Linear algebra" 888 | ] 889 | }, 890 | { 891 | "cell_type": "markdown", 892 | "metadata": {}, 893 | "source": [ 894 | "Vectorizing code is the key to writing efficient numerical calculation with Python/Numpy. That means that as much as possible of a program should be formulated in terms of matrix and vector operations, like matrix-matrix multiplication." 895 | ] 896 | }, 897 | { 898 | "cell_type": "markdown", 899 | "metadata": {}, 900 | "source": [ 901 | "### Scalar-array operations" 902 | ] 903 | }, 904 | { 905 | "cell_type": "markdown", 906 | "metadata": {}, 907 | "source": [ 908 | "We can use the usual arithmetic operators to multiply, add, subtract, and divide arrays with scalar numbers." 909 | ] 910 | }, 911 | { 912 | "cell_type": "code", 913 | "execution_count": 81, 914 | "metadata": {}, 915 | "outputs": [], 916 | "source": [ 917 | "#" 918 | ] 919 | }, 920 | { 921 | "cell_type": "markdown", 922 | "metadata": {}, 923 | "source": [ 924 | "### Element-wise array-array operations" 925 | ] 926 | }, 927 | { 928 | "cell_type": "markdown", 929 | "metadata": {}, 930 | "source": [ 931 | "When we add, subtract, multiply and divide arrays with each other, the default behaviour is **element-wise** operations:" 932 | ] 933 | }, 934 | { 935 | "cell_type": "code", 936 | "execution_count": 33, 937 | "metadata": {}, 938 | "outputs": [], 939 | "source": [ 940 | "#" 941 | ] 942 | }, 943 | { 944 | "cell_type": "markdown", 945 | "metadata": {}, 946 | "source": [ 947 | "If we multiply arrays with compatible shapes, we get an element-wise multiplication of each row:" 948 | ] 949 | }, 950 | { 951 | "cell_type": "code", 952 | "execution_count": 34, 953 | "metadata": {}, 954 | "outputs": [], 955 | "source": [ 956 | "#" 957 | ] 958 | }, 959 | { 960 | "cell_type": "markdown", 961 | "metadata": {}, 962 | "source": [ 963 | "What about matrix mutiplication? There are two ways. We can either use the `dot` function, which applies a matrix-matrix, matrix-vector, or inner vector multiplication to its two arguments: " 964 | ] 965 | }, 966 | { 967 | "cell_type": "code", 968 | "execution_count": 35, 969 | "metadata": {}, 970 | "outputs": [], 971 | "source": [ 972 | "#" 973 | ] 974 | }, 975 | { 976 | "cell_type": "markdown", 977 | "metadata": {}, 978 | "source": [ 979 | "See also the related functions: `inner`, `outer`, `cross`, `kron`, `tensordot`. Try for example `help(kron)`." 980 | ] 981 | }, 982 | { 983 | "cell_type": "code", 984 | "execution_count": 36, 985 | "metadata": { 986 | "colab": { 987 | "base_uri": "https://localhost:8080/", 988 | "height": 52 989 | }, 990 | "colab_type": "code", 991 | "id": "I3FnmoSeL9iu", 992 | "outputId": "46f4575a-2e5e-4347-a34e-0cc5bd280110" 993 | }, 994 | "outputs": [], 995 | "source": [ 996 | "#" 997 | ] 998 | }, 999 | { 1000 | "cell_type": "markdown", 1001 | "metadata": { 1002 | "colab_type": "text", 1003 | "id": "vmxPbrHASVeA" 1004 | }, 1005 | "source": [ 1006 | "You can also use the `@` operator which is equivalent to numpy's `dot` operator." 1007 | ] 1008 | }, 1009 | { 1010 | "cell_type": "code", 1011 | "execution_count": 37, 1012 | "metadata": { 1013 | "colab": { 1014 | "base_uri": "https://localhost:8080/", 1015 | "height": 69 1016 | }, 1017 | "colab_type": "code", 1018 | "id": "zvUODeTxL9iw", 1019 | "outputId": "4093fc76-094f-4453-a421-a212b5226968" 1020 | }, 1021 | "outputs": [], 1022 | "source": [ 1023 | "#" 1024 | ] 1025 | }, 1026 | { 1027 | "cell_type": "markdown", 1028 | "metadata": { 1029 | "colab_type": "text", 1030 | "id": "FbE-1If_L9i0" 1031 | }, 1032 | "source": [ 1033 | "Numpy provides many useful functions for performing computations on arrays; one of the most useful is `sum`:" 1034 | ] 1035 | }, 1036 | { 1037 | "cell_type": "code", 1038 | "execution_count": 38, 1039 | "metadata": { 1040 | "colab": { 1041 | "base_uri": "https://localhost:8080/", 1042 | "height": 69 1043 | }, 1044 | "colab_type": "code", 1045 | "id": "DZUdZvPrL9i0", 1046 | "outputId": "99cad470-d692-4b25-91c9-a57aa25f4c6e" 1047 | }, 1048 | "outputs": [], 1049 | "source": [ 1050 | "#" 1051 | ] 1052 | }, 1053 | { 1054 | "cell_type": "markdown", 1055 | "metadata": { 1056 | "colab_type": "text", 1057 | "id": "ahdVW4iUL9i3" 1058 | }, 1059 | "source": [ 1060 | "You can find the full list of mathematical functions provided by numpy in the [documentation](http://docs.scipy.org/doc/numpy/reference/routines.math.html).\n", 1061 | "\n", 1062 | "Apart from computing mathematical functions using arrays, we frequently need to reshape or otherwise manipulate data in arrays. The simplest example of this type of operation is transposing a matrix; to transpose a matrix, simply use the T attribute of an array object:" 1063 | ] 1064 | }, 1065 | { 1066 | "cell_type": "code", 1067 | "execution_count": 39, 1068 | "metadata": { 1069 | "colab": { 1070 | "base_uri": "https://localhost:8080/", 1071 | "height": 104 1072 | }, 1073 | "colab_type": "code", 1074 | "id": "mkk03eNIL9i4", 1075 | "outputId": "499eec5a-55b7-473a-d4aa-9d023d63885a" 1076 | }, 1077 | "outputs": [], 1078 | "source": [ 1079 | "#" 1080 | ] 1081 | }, 1082 | { 1083 | "cell_type": "markdown", 1084 | "metadata": {}, 1085 | "source": [ 1086 | "#### `np.diag`" 1087 | ] 1088 | }, 1089 | { 1090 | "cell_type": "code", 1091 | "execution_count": 40, 1092 | "metadata": {}, 1093 | "outputs": [], 1094 | "source": [ 1095 | "#" 1096 | ] 1097 | }, 1098 | { 1099 | "cell_type": "markdown", 1100 | "metadata": {}, 1101 | "source": [ 1102 | "Let us experiment with matrices\n", 1103 | "\n", 1104 | "$$ \n", 1105 | " A = \\begin{bmatrix} 2 & -1 \\\\ 3 & 0 \\end{bmatrix} \n", 1106 | " \\quad \\text{and} \\quad\n", 1107 | " b = \\begin{bmatrix} 1 \\\\ 1 \\end{bmatrix}\n", 1108 | "$$" 1109 | ] 1110 | }, 1111 | { 1112 | "cell_type": "code", 1113 | "execution_count": 319, 1114 | "metadata": {}, 1115 | "outputs": [], 1116 | "source": [ 1117 | "A = [[2, -1],\n", 1118 | " [3, 0]]\n", 1119 | "A = np.array(A) # Convert from list to NumPy array\n", 1120 | "b = np.ones((2, 1)) # Shape is 2 x 1" 1121 | ] 1122 | }, 1123 | { 1124 | "cell_type": "markdown", 1125 | "metadata": {}, 1126 | "source": [ 1127 | "#### Inverse" 1128 | ] 1129 | }, 1130 | { 1131 | "cell_type": "code", 1132 | "execution_count": 42, 1133 | "metadata": {}, 1134 | "outputs": [], 1135 | "source": [ 1136 | "#" 1137 | ] 1138 | }, 1139 | { 1140 | "cell_type": "markdown", 1141 | "metadata": {}, 1142 | "source": [ 1143 | "#### Determinant" 1144 | ] 1145 | }, 1146 | { 1147 | "cell_type": "code", 1148 | "execution_count": 19, 1149 | "metadata": {}, 1150 | "outputs": [], 1151 | "source": [ 1152 | "#" 1153 | ] 1154 | }, 1155 | { 1156 | "cell_type": "code", 1157 | "execution_count": 43, 1158 | "metadata": {}, 1159 | "outputs": [], 1160 | "source": [ 1161 | "#" 1162 | ] 1163 | }, 1164 | { 1165 | "cell_type": "markdown", 1166 | "metadata": {}, 1167 | "source": [ 1168 | "#### Eigenvalues and eigenvectors" 1169 | ] 1170 | }, 1171 | { 1172 | "cell_type": "code", 1173 | "execution_count": 41, 1174 | "metadata": {}, 1175 | "outputs": [], 1176 | "source": [ 1177 | "#" 1178 | ] 1179 | }, 1180 | { 1181 | "cell_type": "markdown", 1182 | "metadata": {}, 1183 | "source": [ 1184 | "Let us solve (for $x$) the problem \n", 1185 | "$$A x = b$$" 1186 | ] 1187 | }, 1188 | { 1189 | "cell_type": "code", 1190 | "execution_count": 44, 1191 | "metadata": {}, 1192 | "outputs": [], 1193 | "source": [ 1194 | "#" 1195 | ] 1196 | }, 1197 | { 1198 | "cell_type": "markdown", 1199 | "metadata": {}, 1200 | "source": [ 1201 | "#### Linear Algebra: Exercises\n", 1202 | "a) solve the linear equation system \n", 1203 | "$$x + y = 0\\\\\n", 1204 | "2x - y = 1$$" 1205 | ] 1206 | }, 1207 | { 1208 | "cell_type": "markdown", 1209 | "metadata": {}, 1210 | "source": [ 1211 | "b) check if the linear equation system \n", 1212 | "$$1x + 0y = 1\\\\\n", 1213 | "-2x + 0y = 3$$\n", 1214 | "has a solution." 1215 | ] 1216 | }, 1217 | { 1218 | "cell_type": "code", 1219 | "execution_count": 20, 1220 | "metadata": {}, 1221 | "outputs": [], 1222 | "source": [ 1223 | "#" 1224 | ] 1225 | } 1226 | ], 1227 | "metadata": { 1228 | "kernelspec": { 1229 | "display_name": "Python 3", 1230 | "language": "python", 1231 | "name": "python3" 1232 | }, 1233 | "language_info": { 1234 | "codemirror_mode": { 1235 | "name": "ipython", 1236 | "version": 3 1237 | }, 1238 | "file_extension": ".py", 1239 | "mimetype": "text/x-python", 1240 | "name": "python", 1241 | "nbconvert_exporter": "python", 1242 | "pygments_lexer": "ipython3", 1243 | "version": "3.8.2" 1244 | } 1245 | }, 1246 | "nbformat": 4, 1247 | "nbformat_minor": 2 1248 | } 1249 | -------------------------------------------------------------------------------- /archive/lecture3_with_notes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Lecture 3: Scientific programming" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Content\n", 15 | " \n", 16 | "* Summary of lecture 2\n", 17 | "* `numpy`: \n", 18 | " * the `array`\n", 19 | " * indexing\n", 20 | " * some standard operations/methods\n", 21 | " * linear algebra `<3`\n", 22 | "* plotting with `matplotlib`\n", 23 | "* `scipy`:\n", 24 | " * distributions\n", 25 | " * Nonlinear solvers\n", 26 | " * Nonlinear optimization" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## Summary of lecture 2\n", 34 | "\n", 35 | "* Collections: `tuple` & `dict`\n", 36 | "* Mutabillity\n", 37 | "* Loops: `for`\n", 38 | "& `while` loop\n", 39 | "* Functions" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "t = (2,3)" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "t" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "type(t)" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "t[0] = 1" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [ 84 | "d = {'o1':1,'o2':2}" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "d" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "d['o1'] = 2" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "d" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "for some_variable in t:\n", 121 | " # do stuff with it\n", 122 | " \n", 123 | " print(some_variable + 1)" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "x = 2\n", 133 | "\n", 134 | "while x < 100:\n", 135 | " # do more stuff\n", 136 | " x = x**2\n", 137 | " print(x)\n", 138 | " print(x<100)" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": null, 144 | "metadata": {}, 145 | "outputs": [], 146 | "source": [ 147 | "def my_function(number):\n", 148 | " print('compeltely unrelated message')\n", 149 | " return number**2 + 1" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "my_function(2)" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": { 164 | "colab_type": "text", 165 | "id": "3cfrOV4dL9hW" 166 | }, 167 | "source": [ 168 | "## Numpy" 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "metadata": { 174 | "colab_type": "text", 175 | "id": "fY12nHhyL9hX" 176 | }, 177 | "source": [ 178 | "Numpy is the core library for scientific computing in Python. It provides a high-performance multidimensional array object, and tools for working with these arrays. If you are already familiar with MATLAB, you might find this [tutorial](http://wiki.scipy.org/NumPy_for_Matlab_Users) useful to get started with Numpy." 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "The `numpy` package (module) is used in almost all numerical computation using Python. It is a package that provide high-performance vector, matrix and higher-dimensional data structures for Python. It is implemented in C and Fortran so when calculations are vectorized (formulated with vectors and matrices), performance is very good. \n", 186 | "\n", 187 | "To use `numpy` you need to import the module, using for example:" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": null, 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [ 196 | "import numpy as np" 197 | ] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": {}, 202 | "source": [ 203 | "In the `numpy` package the terminology used for vectors, matrices and higher-dimensional data sets is *array*. \n", 204 | "\n" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "## Creating `numpy` arrays" 212 | ] 213 | }, 214 | { 215 | "cell_type": "markdown", 216 | "metadata": {}, 217 | "source": [ 218 | "There are a number of ways to initialize new numpy arrays, for example from\n", 219 | "\n", 220 | "* a Python list or tuples\n", 221 | "* using functions that are dedicated to generating numpy arrays, such as `np.arange`, `np.linspace`, etc.\n", 222 | "* reading data from files" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "### From lists/tuples" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "For example, to create new vector and matrix arrays from Python lists we can use the `numpy.array` function." 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [ 245 | "v = np.array([1,2,3])" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": {}, 252 | "outputs": [], 253 | "source": [ 254 | "v" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": {}, 261 | "outputs": [], 262 | "source": [ 263 | "M = np.array([[1,2],\n", 264 | " [3,4]])" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": null, 270 | "metadata": {}, 271 | "outputs": [], 272 | "source": [ 273 | "M" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "The `v` and `M` objects are both of the type `ndarray` that the `numpy` module provides." 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": null, 286 | "metadata": {}, 287 | "outputs": [], 288 | "source": [ 289 | "type(v)" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [ 298 | "type(M)" 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "metadata": {}, 304 | "source": [ 305 | "The difference between the `v` and `M` arrays is only their shapes. We can get information about the shape of an array by using the `ndarray.shape` property." 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": {}, 312 | "outputs": [], 313 | "source": [ 314 | "v.shape" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": null, 320 | "metadata": {}, 321 | "outputs": [], 322 | "source": [ 323 | "M.shape" 324 | ] 325 | }, 326 | { 327 | "cell_type": "markdown", 328 | "metadata": {}, 329 | "source": [ 330 | "Equivalently, we could use the function `numpy.shape`" 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": null, 336 | "metadata": {}, 337 | "outputs": [], 338 | "source": [ 339 | "np.shape(M)" 340 | ] 341 | }, 342 | { 343 | "cell_type": "markdown", 344 | "metadata": {}, 345 | "source": [ 346 | "So far the `numpy.ndarray` looks awefully much like a Python list (or nested list). Why not simply use Python lists for computations instead of creating a new array type? \n", 347 | "\n", 348 | "There are several reasons:\n", 349 | "\n", 350 | "* Python lists are very general. They can contain any kind of object. They are dynamically typed. They do not support mathematical functions such as matrix and dot multiplications, etc. Implementing such functions for Python lists would not be very efficient because of the dynamic typing.\n", 351 | "* Numpy arrays are **statically typed** and **homogeneous**. The type of the elements is determined when the array is created.\n", 352 | "* Numpy arrays are memory efficient.\n", 353 | "* Because of the static typing, fast implementation of mathematical functions such as multiplication and addition of `numpy` arrays can be implemented in a compiled language (C and Fortran is used).\n", 354 | "\n", 355 | "Using the `dtype` (data type) property of an `ndarray`, we can see what type the data of an array has:" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": null, 361 | "metadata": {}, 362 | "outputs": [], 363 | "source": [ 364 | "M.dtype" 365 | ] 366 | }, 367 | { 368 | "cell_type": "markdown", 369 | "metadata": {}, 370 | "source": [ 371 | "We get an error if we try to assign a value of the wrong type to an element in a numpy array:" 372 | ] 373 | }, 374 | { 375 | "cell_type": "code", 376 | "execution_count": null, 377 | "metadata": {}, 378 | "outputs": [], 379 | "source": [ 380 | "M[0,0] = 'assign me'" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": null, 386 | "metadata": {}, 387 | "outputs": [], 388 | "source": [ 389 | "a = np.array((1,2))" 390 | ] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": {}, 395 | "source": [ 396 | "### Using array-generating functions" 397 | ] 398 | }, 399 | { 400 | "cell_type": "markdown", 401 | "metadata": {}, 402 | "source": [ 403 | "For larger arrays it is inpractical to initialize the data manually, using explicit python lists. Instead we can use one of the many functions in `numpy` that generate arrays of different forms. Some of the more common are:" 404 | ] 405 | }, 406 | { 407 | "cell_type": "markdown", 408 | "metadata": {}, 409 | "source": [ 410 | "#### `np.arange`" 411 | ] 412 | }, 413 | { 414 | "cell_type": "code", 415 | "execution_count": null, 416 | "metadata": {}, 417 | "outputs": [], 418 | "source": [ 419 | "x = np.arange(0,10)" 420 | ] 421 | }, 422 | { 423 | "cell_type": "code", 424 | "execution_count": null, 425 | "metadata": {}, 426 | "outputs": [], 427 | "source": [ 428 | "x" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": null, 434 | "metadata": {}, 435 | "outputs": [], 436 | "source": [ 437 | "np.arange(-1,2)" 438 | ] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "execution_count": null, 443 | "metadata": {}, 444 | "outputs": [], 445 | "source": [ 446 | "np.arange(-1,1,0.1) # arange(start, stop, step)" 447 | ] 448 | }, 449 | { 450 | "cell_type": "markdown", 451 | "metadata": {}, 452 | "source": [ 453 | "#### `np.linspace`" 454 | ] 455 | }, 456 | { 457 | "cell_type": "code", 458 | "execution_count": null, 459 | "metadata": {}, 460 | "outputs": [], 461 | "source": [ 462 | "np.linspace(0,10,25) # linspace(start,stop,number)" 463 | ] 464 | }, 465 | { 466 | "cell_type": "markdown", 467 | "metadata": {}, 468 | "source": [ 469 | "#### random data" 470 | ] 471 | }, 472 | { 473 | "cell_type": "code", 474 | "execution_count": null, 475 | "metadata": {}, 476 | "outputs": [], 477 | "source": [ 478 | "np.random.rand(3,3)" 479 | ] 480 | }, 481 | { 482 | "cell_type": "code", 483 | "execution_count": null, 484 | "metadata": {}, 485 | "outputs": [], 486 | "source": [ 487 | "np.random.randn(2,4)" 488 | ] 489 | }, 490 | { 491 | "cell_type": "markdown", 492 | "metadata": {}, 493 | "source": [ 494 | "#### zeros and ones" 495 | ] 496 | }, 497 | { 498 | "cell_type": "code", 499 | "execution_count": null, 500 | "metadata": {}, 501 | "outputs": [], 502 | "source": [ 503 | "np.zeros(9)" 504 | ] 505 | }, 506 | { 507 | "cell_type": "code", 508 | "execution_count": null, 509 | "metadata": {}, 510 | "outputs": [], 511 | "source": [ 512 | "np.ones((3,3))" 513 | ] 514 | }, 515 | { 516 | "cell_type": "markdown", 517 | "metadata": {}, 518 | "source": [ 519 | "#### Creating arrays: Exercises" 520 | ] 521 | }, 522 | { 523 | "cell_type": "markdown", 524 | "metadata": {}, 525 | "source": [ 526 | "a) Create an array with only even numbers of lengh 10." 527 | ] 528 | }, 529 | { 530 | "cell_type": "code", 531 | "execution_count": null, 532 | "metadata": {}, 533 | "outputs": [], 534 | "source": [ 535 | "np.arange(0,11,2)" 536 | ] 537 | }, 538 | { 539 | "cell_type": "markdown", 540 | "metadata": {}, 541 | "source": [ 542 | "b) Create an array of `[0,10,...,100]`." 543 | ] 544 | }, 545 | { 546 | "cell_type": "code", 547 | "execution_count": null, 548 | "metadata": {}, 549 | "outputs": [], 550 | "source": [ 551 | "np.arange(0,110,10)" 552 | ] 553 | }, 554 | { 555 | "cell_type": "markdown", 556 | "metadata": {}, 557 | "source": [ 558 | "## Manipulating arrays" 559 | ] 560 | }, 561 | { 562 | "cell_type": "markdown", 563 | "metadata": {}, 564 | "source": [ 565 | "### Indexing" 566 | ] 567 | }, 568 | { 569 | "cell_type": "markdown", 570 | "metadata": {}, 571 | "source": [ 572 | "We can index elements in an array using square brackets and indices:" 573 | ] 574 | }, 575 | { 576 | "cell_type": "code", 577 | "execution_count": null, 578 | "metadata": {}, 579 | "outputs": [], 580 | "source": [ 581 | "v[0]" 582 | ] 583 | }, 584 | { 585 | "cell_type": "code", 586 | "execution_count": null, 587 | "metadata": {}, 588 | "outputs": [], 589 | "source": [ 590 | "M" 591 | ] 592 | }, 593 | { 594 | "cell_type": "code", 595 | "execution_count": null, 596 | "metadata": {}, 597 | "outputs": [], 598 | "source": [ 599 | "M[0,1]" 600 | ] 601 | }, 602 | { 603 | "cell_type": "markdown", 604 | "metadata": {}, 605 | "source": [ 606 | "If we omit an index of a multidimensional array it returns the whole row (or, in general, a N-1 dimensional array) " 607 | ] 608 | }, 609 | { 610 | "cell_type": "code", 611 | "execution_count": null, 612 | "metadata": {}, 613 | "outputs": [], 614 | "source": [ 615 | "M[1]" 616 | ] 617 | }, 618 | { 619 | "cell_type": "markdown", 620 | "metadata": {}, 621 | "source": [ 622 | "The same thing can be achieved with using `:` instead of an index: " 623 | ] 624 | }, 625 | { 626 | "cell_type": "code", 627 | "execution_count": null, 628 | "metadata": {}, 629 | "outputs": [], 630 | "source": [ 631 | "M[1,:]" 632 | ] 633 | }, 634 | { 635 | "cell_type": "code", 636 | "execution_count": null, 637 | "metadata": {}, 638 | "outputs": [], 639 | "source": [ 640 | "M[:,0]" 641 | ] 642 | }, 643 | { 644 | "cell_type": "markdown", 645 | "metadata": {}, 646 | "source": [ 647 | "We can assign new values to elements in an array using indexing:" 648 | ] 649 | }, 650 | { 651 | "cell_type": "code", 652 | "execution_count": null, 653 | "metadata": {}, 654 | "outputs": [], 655 | "source": [ 656 | "M[0,0] = 99" 657 | ] 658 | }, 659 | { 660 | "cell_type": "code", 661 | "execution_count": null, 662 | "metadata": {}, 663 | "outputs": [], 664 | "source": [ 665 | "M" 666 | ] 667 | }, 668 | { 669 | "cell_type": "code", 670 | "execution_count": null, 671 | "metadata": {}, 672 | "outputs": [], 673 | "source": [ 674 | "M[:,0] = 0" 675 | ] 676 | }, 677 | { 678 | "cell_type": "code", 679 | "execution_count": null, 680 | "metadata": {}, 681 | "outputs": [], 682 | "source": [ 683 | "0" 684 | ] 685 | }, 686 | { 687 | "cell_type": "markdown", 688 | "metadata": {}, 689 | "source": [ 690 | "### Index slicing" 691 | ] 692 | }, 693 | { 694 | "cell_type": "markdown", 695 | "metadata": {}, 696 | "source": [ 697 | "Index slicing is the technical name for the syntax `M[lower:upper:step]` to extract part of an array:" 698 | ] 699 | }, 700 | { 701 | "cell_type": "code", 702 | "execution_count": null, 703 | "metadata": {}, 704 | "outputs": [], 705 | "source": [ 706 | "A = np.arange(5)" 707 | ] 708 | }, 709 | { 710 | "cell_type": "code", 711 | "execution_count": null, 712 | "metadata": {}, 713 | "outputs": [], 714 | "source": [ 715 | "A" 716 | ] 717 | }, 718 | { 719 | "cell_type": "code", 720 | "execution_count": null, 721 | "metadata": {}, 722 | "outputs": [], 723 | "source": [ 724 | "A[1:4]" 725 | ] 726 | }, 727 | { 728 | "cell_type": "markdown", 729 | "metadata": {}, 730 | "source": [ 731 | "Array slices are *mutable*: if they are assigned a new value the original array from which the slice was extracted is modified:" 732 | ] 733 | }, 734 | { 735 | "cell_type": "code", 736 | "execution_count": null, 737 | "metadata": {}, 738 | "outputs": [], 739 | "source": [ 740 | "A[1:3] = [-1,-2]" 741 | ] 742 | }, 743 | { 744 | "cell_type": "code", 745 | "execution_count": null, 746 | "metadata": {}, 747 | "outputs": [], 748 | "source": [ 749 | "A" 750 | ] 751 | }, 752 | { 753 | "cell_type": "markdown", 754 | "metadata": {}, 755 | "source": [ 756 | "We can omit any of the three parameters in `M[lower:upper:step]`:" 757 | ] 758 | }, 759 | { 760 | "cell_type": "code", 761 | "execution_count": null, 762 | "metadata": {}, 763 | "outputs": [], 764 | "source": [ 765 | "A = np.arange(9)" 766 | ] 767 | }, 768 | { 769 | "cell_type": "code", 770 | "execution_count": null, 771 | "metadata": {}, 772 | "outputs": [], 773 | "source": [ 774 | "A" 775 | ] 776 | }, 777 | { 778 | "cell_type": "code", 779 | "execution_count": null, 780 | "metadata": {}, 781 | "outputs": [], 782 | "source": [ 783 | "A[::2]" 784 | ] 785 | }, 786 | { 787 | "cell_type": "code", 788 | "execution_count": null, 789 | "metadata": {}, 790 | "outputs": [], 791 | "source": [ 792 | "A[1:7:2]" 793 | ] 794 | }, 795 | { 796 | "cell_type": "markdown", 797 | "metadata": {}, 798 | "source": [ 799 | "Negative indices counts from the end of the array (positive index from the begining):" 800 | ] 801 | }, 802 | { 803 | "cell_type": "code", 804 | "execution_count": null, 805 | "metadata": {}, 806 | "outputs": [], 807 | "source": [ 808 | "A[-1]" 809 | ] 810 | }, 811 | { 812 | "cell_type": "code", 813 | "execution_count": null, 814 | "metadata": {}, 815 | "outputs": [], 816 | "source": [ 817 | "A[-2:]" 818 | ] 819 | }, 820 | { 821 | "cell_type": "code", 822 | "execution_count": null, 823 | "metadata": {}, 824 | "outputs": [], 825 | "source": [ 826 | "A = np.array(((1,2,3),(4,5,6),(7,8,9)))" 827 | ] 828 | }, 829 | { 830 | "cell_type": "code", 831 | "execution_count": null, 832 | "metadata": {}, 833 | "outputs": [], 834 | "source": [ 835 | "A" 836 | ] 837 | }, 838 | { 839 | "cell_type": "markdown", 840 | "metadata": {}, 841 | "source": [ 842 | "### Fancy indexing" 843 | ] 844 | }, 845 | { 846 | "cell_type": "markdown", 847 | "metadata": {}, 848 | "source": [ 849 | "Fancy indexing is the name for when an array or list is used in-place of an index: " 850 | ] 851 | }, 852 | { 853 | "cell_type": "code", 854 | "execution_count": null, 855 | "metadata": {}, 856 | "outputs": [], 857 | "source": [ 858 | "row_inds = [1,2]" 859 | ] 860 | }, 861 | { 862 | "cell_type": "code", 863 | "execution_count": null, 864 | "metadata": {}, 865 | "outputs": [], 866 | "source": [ 867 | "A[row_inds]" 868 | ] 869 | }, 870 | { 871 | "cell_type": "code", 872 | "execution_count": null, 873 | "metadata": {}, 874 | "outputs": [], 875 | "source": [ 876 | "col_inds = [0,2]" 877 | ] 878 | }, 879 | { 880 | "cell_type": "code", 881 | "execution_count": null, 882 | "metadata": {}, 883 | "outputs": [], 884 | "source": [ 885 | "A[row_inds][:,col_inds]" 886 | ] 887 | }, 888 | { 889 | "cell_type": "markdown", 890 | "metadata": {}, 891 | "source": [ 892 | "We can also use index masks: If the index mask is an Numpy array of data type `bool`, then an element is selected (True) or not (False) depending on the value of the index mask at the position of each element: " 893 | ] 894 | }, 895 | { 896 | "cell_type": "code", 897 | "execution_count": null, 898 | "metadata": {}, 899 | "outputs": [], 900 | "source": [ 901 | "mask = [True, False, True]" 902 | ] 903 | }, 904 | { 905 | "cell_type": "code", 906 | "execution_count": null, 907 | "metadata": {}, 908 | "outputs": [], 909 | "source": [ 910 | "A[mask]" 911 | ] 912 | }, 913 | { 914 | "cell_type": "code", 915 | "execution_count": null, 916 | "metadata": {}, 917 | "outputs": [], 918 | "source": [ 919 | "A[:,mask]" 920 | ] 921 | }, 922 | { 923 | "cell_type": "markdown", 924 | "metadata": {}, 925 | "source": [ 926 | "This feature is very useful to conditionally select elements from an array, using for example comparison operators:" 927 | ] 928 | }, 929 | { 930 | "cell_type": "code", 931 | "execution_count": null, 932 | "metadata": {}, 933 | "outputs": [], 934 | "source": [ 935 | "a = np.arange(4)" 936 | ] 937 | }, 938 | { 939 | "cell_type": "code", 940 | "execution_count": null, 941 | "metadata": {}, 942 | "outputs": [], 943 | "source": [ 944 | "a" 945 | ] 946 | }, 947 | { 948 | "cell_type": "code", 949 | "execution_count": null, 950 | "metadata": {}, 951 | "outputs": [], 952 | "source": [ 953 | "v_o_b = a > 1" 954 | ] 955 | }, 956 | { 957 | "cell_type": "code", 958 | "execution_count": null, 959 | "metadata": {}, 960 | "outputs": [], 961 | "source": [ 962 | "a[v_o_b]" 963 | ] 964 | }, 965 | { 966 | "cell_type": "code", 967 | "execution_count": null, 968 | "metadata": {}, 969 | "outputs": [], 970 | "source": [ 971 | "b = np.linspace(0,1,10)" 972 | ] 973 | }, 974 | { 975 | "cell_type": "code", 976 | "execution_count": null, 977 | "metadata": {}, 978 | "outputs": [], 979 | "source": [ 980 | "b" 981 | ] 982 | }, 983 | { 984 | "cell_type": "code", 985 | "execution_count": null, 986 | "metadata": {}, 987 | "outputs": [], 988 | "source": [ 989 | "uuu = (b > 0.1) & (b < 0.8)" 990 | ] 991 | }, 992 | { 993 | "cell_type": "code", 994 | "execution_count": null, 995 | "metadata": {}, 996 | "outputs": [], 997 | "source": [ 998 | "b[uuu]" 999 | ] 1000 | }, 1001 | { 1002 | "cell_type": "markdown", 1003 | "metadata": {}, 1004 | "source": [ 1005 | "#### Exercises: indexing\n", 1006 | "a) create an array `a` from 0 to 9" 1007 | ] 1008 | }, 1009 | { 1010 | "cell_type": "code", 1011 | "execution_count": null, 1012 | "metadata": {}, 1013 | "outputs": [], 1014 | "source": [ 1015 | "a = np.arange(9)" 1016 | ] 1017 | }, 1018 | { 1019 | "cell_type": "markdown", 1020 | "metadata": {}, 1021 | "source": [ 1022 | "b) get only the first 3 values of `a`" 1023 | ] 1024 | }, 1025 | { 1026 | "cell_type": "code", 1027 | "execution_count": null, 1028 | "metadata": {}, 1029 | "outputs": [], 1030 | "source": [ 1031 | "a[:3]" 1032 | ] 1033 | }, 1034 | { 1035 | "cell_type": "markdown", 1036 | "metadata": {}, 1037 | "source": [ 1038 | "c) create a random array `b` of size 9 with $b_i \\sim N(0,1)$." 1039 | ] 1040 | }, 1041 | { 1042 | "cell_type": "code", 1043 | "execution_count": null, 1044 | "metadata": {}, 1045 | "outputs": [], 1046 | "source": [ 1047 | "b = np.random.randn(9)" 1048 | ] 1049 | }, 1050 | { 1051 | "cell_type": "code", 1052 | "execution_count": null, 1053 | "metadata": {}, 1054 | "outputs": [], 1055 | "source": [ 1056 | "b" 1057 | ] 1058 | }, 1059 | { 1060 | "cell_type": "markdown", 1061 | "metadata": {}, 1062 | "source": [ 1063 | "d) get all the values of `b` that are larger than one." 1064 | ] 1065 | }, 1066 | { 1067 | "cell_type": "code", 1068 | "execution_count": null, 1069 | "metadata": {}, 1070 | "outputs": [], 1071 | "source": [ 1072 | "ind = b > 1" 1073 | ] 1074 | }, 1075 | { 1076 | "cell_type": "code", 1077 | "execution_count": null, 1078 | "metadata": {}, 1079 | "outputs": [], 1080 | "source": [ 1081 | "ind" 1082 | ] 1083 | }, 1084 | { 1085 | "cell_type": "code", 1086 | "execution_count": null, 1087 | "metadata": {}, 1088 | "outputs": [], 1089 | "source": [ 1090 | "b[ind]" 1091 | ] 1092 | }, 1093 | { 1094 | "cell_type": "code", 1095 | "execution_count": null, 1096 | "metadata": {}, 1097 | "outputs": [], 1098 | "source": [ 1099 | "b[b>1]" 1100 | ] 1101 | }, 1102 | { 1103 | "cell_type": "markdown", 1104 | "metadata": {}, 1105 | "source": [ 1106 | "## Some standard operations" 1107 | ] 1108 | }, 1109 | { 1110 | "cell_type": "markdown", 1111 | "metadata": {}, 1112 | "source": [ 1113 | "Lets us create some very precious data that we want to learn more about." 1114 | ] 1115 | }, 1116 | { 1117 | "cell_type": "code", 1118 | "execution_count": null, 1119 | "metadata": {}, 1120 | "outputs": [], 1121 | "source": [ 1122 | "import numpy as np" 1123 | ] 1124 | }, 1125 | { 1126 | "cell_type": "code", 1127 | "execution_count": null, 1128 | "metadata": {}, 1129 | "outputs": [], 1130 | "source": [ 1131 | "data = np.random.randn(100,3)*2 + 1" 1132 | ] 1133 | }, 1134 | { 1135 | "cell_type": "code", 1136 | "execution_count": null, 1137 | "metadata": { 1138 | "scrolled": true 1139 | }, 1140 | "outputs": [], 1141 | "source": [ 1142 | "data" 1143 | ] 1144 | }, 1145 | { 1146 | "cell_type": "code", 1147 | "execution_count": null, 1148 | "metadata": {}, 1149 | "outputs": [], 1150 | "source": [ 1151 | "data.shape" 1152 | ] 1153 | }, 1154 | { 1155 | "cell_type": "markdown", 1156 | "metadata": {}, 1157 | "source": [ 1158 | "#### sum" 1159 | ] 1160 | }, 1161 | { 1162 | "cell_type": "code", 1163 | "execution_count": null, 1164 | "metadata": {}, 1165 | "outputs": [], 1166 | "source": [ 1167 | "np.sum(data)" 1168 | ] 1169 | }, 1170 | { 1171 | "cell_type": "code", 1172 | "execution_count": null, 1173 | "metadata": {}, 1174 | "outputs": [], 1175 | "source": [ 1176 | "np.sum(data[0])" 1177 | ] 1178 | }, 1179 | { 1180 | "cell_type": "code", 1181 | "execution_count": null, 1182 | "metadata": {}, 1183 | "outputs": [], 1184 | "source": [ 1185 | "np.sum(data,0)" 1186 | ] 1187 | }, 1188 | { 1189 | "cell_type": "markdown", 1190 | "metadata": {}, 1191 | "source": [ 1192 | "#### mean" 1193 | ] 1194 | }, 1195 | { 1196 | "cell_type": "code", 1197 | "execution_count": null, 1198 | "metadata": {}, 1199 | "outputs": [], 1200 | "source": [ 1201 | "np.mean(data,0)" 1202 | ] 1203 | }, 1204 | { 1205 | "cell_type": "code", 1206 | "execution_count": null, 1207 | "metadata": {}, 1208 | "outputs": [], 1209 | "source": [ 1210 | "np.sum(data,0)/100" 1211 | ] 1212 | }, 1213 | { 1214 | "cell_type": "markdown", 1215 | "metadata": {}, 1216 | "source": [ 1217 | "#### standard deviations and variance" 1218 | ] 1219 | }, 1220 | { 1221 | "cell_type": "code", 1222 | "execution_count": null, 1223 | "metadata": {}, 1224 | "outputs": [], 1225 | "source": [ 1226 | "np.std(data)" 1227 | ] 1228 | }, 1229 | { 1230 | "cell_type": "code", 1231 | "execution_count": null, 1232 | "metadata": {}, 1233 | "outputs": [], 1234 | "source": [ 1235 | "np.var(data, 0)" 1236 | ] 1237 | }, 1238 | { 1239 | "cell_type": "markdown", 1240 | "metadata": {}, 1241 | "source": [ 1242 | "#### min and max" 1243 | ] 1244 | }, 1245 | { 1246 | "cell_type": "code", 1247 | "execution_count": null, 1248 | "metadata": {}, 1249 | "outputs": [], 1250 | "source": [ 1251 | "np.min(data)" 1252 | ] 1253 | }, 1254 | { 1255 | "cell_type": "code", 1256 | "execution_count": null, 1257 | "metadata": {}, 1258 | "outputs": [], 1259 | "source": [ 1260 | "np.max(data[:,0])" 1261 | ] 1262 | }, 1263 | { 1264 | "cell_type": "markdown", 1265 | "metadata": {}, 1266 | "source": [ 1267 | "### Reshaping and stacking arrays" 1268 | ] 1269 | }, 1270 | { 1271 | "cell_type": "markdown", 1272 | "metadata": {}, 1273 | "source": [ 1274 | "The shape of an Numpy array can be modified without copying the underlaying data, which makes it a fast operation even for large arrays. Let us create `A`." 1275 | ] 1276 | }, 1277 | { 1278 | "cell_type": "code", 1279 | "execution_count": null, 1280 | "metadata": {}, 1281 | "outputs": [], 1282 | "source": [ 1283 | "a = np.arange(4*4)" 1284 | ] 1285 | }, 1286 | { 1287 | "cell_type": "code", 1288 | "execution_count": null, 1289 | "metadata": {}, 1290 | "outputs": [], 1291 | "source": [ 1292 | "a" 1293 | ] 1294 | }, 1295 | { 1296 | "cell_type": "code", 1297 | "execution_count": null, 1298 | "metadata": {}, 1299 | "outputs": [], 1300 | "source": [ 1301 | "b = np.reshape(a, (4,4))" 1302 | ] 1303 | }, 1304 | { 1305 | "cell_type": "code", 1306 | "execution_count": null, 1307 | "metadata": {}, 1308 | "outputs": [], 1309 | "source": [ 1310 | "c = np.reshape(a, (4,5))" 1311 | ] 1312 | }, 1313 | { 1314 | "cell_type": "code", 1315 | "execution_count": null, 1316 | "metadata": {}, 1317 | "outputs": [], 1318 | "source": [ 1319 | "b" 1320 | ] 1321 | }, 1322 | { 1323 | "cell_type": "code", 1324 | "execution_count": null, 1325 | "metadata": {}, 1326 | "outputs": [], 1327 | "source": [ 1328 | "c = np.arange(3)" 1329 | ] 1330 | }, 1331 | { 1332 | "cell_type": "code", 1333 | "execution_count": null, 1334 | "metadata": {}, 1335 | "outputs": [], 1336 | "source": [ 1337 | "d = np.zeros(3)" 1338 | ] 1339 | }, 1340 | { 1341 | "cell_type": "code", 1342 | "execution_count": null, 1343 | "metadata": {}, 1344 | "outputs": [], 1345 | "source": [ 1346 | "np.hstack((c,d))" 1347 | ] 1348 | }, 1349 | { 1350 | "cell_type": "code", 1351 | "execution_count": null, 1352 | "metadata": {}, 1353 | "outputs": [], 1354 | "source": [ 1355 | "np.vstack((c,d))" 1356 | ] 1357 | }, 1358 | { 1359 | "cell_type": "markdown", 1360 | "metadata": {}, 1361 | "source": [ 1362 | "#### Standard operations: exercises\n", 1363 | "a) create a random array `b` of size 9 with $b_i \\sim N(0,1)$." 1364 | ] 1365 | }, 1366 | { 1367 | "cell_type": "code", 1368 | "execution_count": null, 1369 | "metadata": {}, 1370 | "outputs": [], 1371 | "source": [ 1372 | "b = np.random.randn(9)" 1373 | ] 1374 | }, 1375 | { 1376 | "cell_type": "markdown", 1377 | "metadata": {}, 1378 | "source": [ 1379 | "b) get the lowest and highest value of `b`." 1380 | ] 1381 | }, 1382 | { 1383 | "cell_type": "code", 1384 | "execution_count": null, 1385 | "metadata": {}, 1386 | "outputs": [], 1387 | "source": [ 1388 | "np.max(b)" 1389 | ] 1390 | }, 1391 | { 1392 | "cell_type": "code", 1393 | "execution_count": null, 1394 | "metadata": {}, 1395 | "outputs": [], 1396 | "source": [ 1397 | "np.min(b)" 1398 | ] 1399 | }, 1400 | { 1401 | "cell_type": "markdown", 1402 | "metadata": {}, 1403 | "source": [ 1404 | "c) create an array `c` of size 9 and stack it horizontally on `b`. Call the result `d`." 1405 | ] 1406 | }, 1407 | { 1408 | "cell_type": "code", 1409 | "execution_count": null, 1410 | "metadata": {}, 1411 | "outputs": [], 1412 | "source": [ 1413 | "c = np.arange(9)" 1414 | ] 1415 | }, 1416 | { 1417 | "cell_type": "code", 1418 | "execution_count": null, 1419 | "metadata": {}, 1420 | "outputs": [], 1421 | "source": [ 1422 | "d = np.hstack((c,b))" 1423 | ] 1424 | }, 1425 | { 1426 | "cell_type": "markdown", 1427 | "metadata": {}, 1428 | "source": [ 1429 | "d) get the mean of `d`." 1430 | ] 1431 | }, 1432 | { 1433 | "cell_type": "code", 1434 | "execution_count": null, 1435 | "metadata": {}, 1436 | "outputs": [], 1437 | "source": [ 1438 | "np.mean(d)" 1439 | ] 1440 | }, 1441 | { 1442 | "cell_type": "markdown", 1443 | "metadata": {}, 1444 | "source": [ 1445 | "## Copy and \"deep copy\"" 1446 | ] 1447 | }, 1448 | { 1449 | "cell_type": "markdown", 1450 | "metadata": {}, 1451 | "source": [ 1452 | "To achieve high performance, assignments in Python usually do not copy the underlaying objects. This is important for example when objects are passed between functions, to avoid an excessive amount of memory copying when it is not necessary (technical term: pass by reference). " 1453 | ] 1454 | }, 1455 | { 1456 | "cell_type": "code", 1457 | "execution_count": null, 1458 | "metadata": {}, 1459 | "outputs": [], 1460 | "source": [ 1461 | "A = np.array(((1,2),(3,4)))" 1462 | ] 1463 | }, 1464 | { 1465 | "cell_type": "code", 1466 | "execution_count": null, 1467 | "metadata": {}, 1468 | "outputs": [], 1469 | "source": [ 1470 | "A" 1471 | ] 1472 | }, 1473 | { 1474 | "cell_type": "code", 1475 | "execution_count": null, 1476 | "metadata": {}, 1477 | "outputs": [], 1478 | "source": [ 1479 | "B = A" 1480 | ] 1481 | }, 1482 | { 1483 | "cell_type": "code", 1484 | "execution_count": null, 1485 | "metadata": {}, 1486 | "outputs": [], 1487 | "source": [ 1488 | "B[0,0] = 10" 1489 | ] 1490 | }, 1491 | { 1492 | "cell_type": "code", 1493 | "execution_count": null, 1494 | "metadata": {}, 1495 | "outputs": [], 1496 | "source": [ 1497 | "B" 1498 | ] 1499 | }, 1500 | { 1501 | "cell_type": "code", 1502 | "execution_count": null, 1503 | "metadata": {}, 1504 | "outputs": [], 1505 | "source": [ 1506 | "A" 1507 | ] 1508 | }, 1509 | { 1510 | "cell_type": "markdown", 1511 | "metadata": {}, 1512 | "source": [ 1513 | "If we want to avoid this behavior, so that when we get a new completely independent object `B` copied from `A`, then we need to do a so-called \"deep copy\" using the function `copy`:" 1514 | ] 1515 | }, 1516 | { 1517 | "cell_type": "code", 1518 | "execution_count": null, 1519 | "metadata": {}, 1520 | "outputs": [], 1521 | "source": [ 1522 | "B = np.copy(A)" 1523 | ] 1524 | }, 1525 | { 1526 | "cell_type": "code", 1527 | "execution_count": null, 1528 | "metadata": {}, 1529 | "outputs": [], 1530 | "source": [ 1531 | "B[1,1] = -999" 1532 | ] 1533 | }, 1534 | { 1535 | "cell_type": "code", 1536 | "execution_count": null, 1537 | "metadata": {}, 1538 | "outputs": [], 1539 | "source": [ 1540 | "B" 1541 | ] 1542 | }, 1543 | { 1544 | "cell_type": "code", 1545 | "execution_count": null, 1546 | "metadata": {}, 1547 | "outputs": [], 1548 | "source": [ 1549 | "A" 1550 | ] 1551 | }, 1552 | { 1553 | "cell_type": "markdown", 1554 | "metadata": {}, 1555 | "source": [ 1556 | "## Linear algebra" 1557 | ] 1558 | }, 1559 | { 1560 | "cell_type": "markdown", 1561 | "metadata": {}, 1562 | "source": [ 1563 | "Vectorizing code is the key to writing efficient numerical calculation with Python/Numpy. That means that as much as possible of a program should be formulated in terms of matrix and vector operations, like matrix-matrix multiplication." 1564 | ] 1565 | }, 1566 | { 1567 | "cell_type": "markdown", 1568 | "metadata": {}, 1569 | "source": [ 1570 | "### Scalar-array operations" 1571 | ] 1572 | }, 1573 | { 1574 | "cell_type": "markdown", 1575 | "metadata": {}, 1576 | "source": [ 1577 | "We can use the usual arithmetic operators to multiply, add, subtract, and divide arrays with scalar numbers." 1578 | ] 1579 | }, 1580 | { 1581 | "cell_type": "code", 1582 | "execution_count": null, 1583 | "metadata": {}, 1584 | "outputs": [], 1585 | "source": [ 1586 | "v1 = np.arange(5)" 1587 | ] 1588 | }, 1589 | { 1590 | "cell_type": "code", 1591 | "execution_count": null, 1592 | "metadata": {}, 1593 | "outputs": [], 1594 | "source": [ 1595 | "v1" 1596 | ] 1597 | }, 1598 | { 1599 | "cell_type": "code", 1600 | "execution_count": null, 1601 | "metadata": {}, 1602 | "outputs": [], 1603 | "source": [ 1604 | "v1*2" 1605 | ] 1606 | }, 1607 | { 1608 | "cell_type": "code", 1609 | "execution_count": null, 1610 | "metadata": {}, 1611 | "outputs": [], 1612 | "source": [ 1613 | "mylist = [0,1,2,3]" 1614 | ] 1615 | }, 1616 | { 1617 | "cell_type": "code", 1618 | "execution_count": null, 1619 | "metadata": {}, 1620 | "outputs": [], 1621 | "source": [ 1622 | "mylist*2" 1623 | ] 1624 | }, 1625 | { 1626 | "cell_type": "code", 1627 | "execution_count": null, 1628 | "metadata": {}, 1629 | "outputs": [], 1630 | "source": [ 1631 | "v1 + 2" 1632 | ] 1633 | }, 1634 | { 1635 | "cell_type": "code", 1636 | "execution_count": null, 1637 | "metadata": {}, 1638 | "outputs": [], 1639 | "source": [ 1640 | "A*3 - 4" 1641 | ] 1642 | }, 1643 | { 1644 | "cell_type": "code", 1645 | "execution_count": null, 1646 | "metadata": {}, 1647 | "outputs": [], 1648 | "source": [ 1649 | "a = np.arange(4).reshape(2,2)" 1650 | ] 1651 | }, 1652 | { 1653 | "cell_type": "markdown", 1654 | "metadata": {}, 1655 | "source": [ 1656 | "### Element-wise array-array operations" 1657 | ] 1658 | }, 1659 | { 1660 | "cell_type": "markdown", 1661 | "metadata": {}, 1662 | "source": [ 1663 | "When we add, subtract, multiply and divide arrays with each other, the default behaviour is **element-wise** operations:" 1664 | ] 1665 | }, 1666 | { 1667 | "cell_type": "code", 1668 | "execution_count": null, 1669 | "metadata": {}, 1670 | "outputs": [], 1671 | "source": [ 1672 | "a * a " 1673 | ] 1674 | }, 1675 | { 1676 | "cell_type": "code", 1677 | "execution_count": null, 1678 | "metadata": {}, 1679 | "outputs": [], 1680 | "source": [ 1681 | "v2 = np.array((-1,2))" 1682 | ] 1683 | }, 1684 | { 1685 | "cell_type": "code", 1686 | "execution_count": null, 1687 | "metadata": {}, 1688 | "outputs": [], 1689 | "source": [ 1690 | "v2" 1691 | ] 1692 | }, 1693 | { 1694 | "cell_type": "markdown", 1695 | "metadata": {}, 1696 | "source": [ 1697 | "If we multiply arrays with compatible shapes, we get an element-wise multiplication of each row:" 1698 | ] 1699 | }, 1700 | { 1701 | "cell_type": "code", 1702 | "execution_count": null, 1703 | "metadata": {}, 1704 | "outputs": [], 1705 | "source": [ 1706 | "a.shape" 1707 | ] 1708 | }, 1709 | { 1710 | "cell_type": "code", 1711 | "execution_count": null, 1712 | "metadata": {}, 1713 | "outputs": [], 1714 | "source": [ 1715 | "v2.shape" 1716 | ] 1717 | }, 1718 | { 1719 | "cell_type": "code", 1720 | "execution_count": null, 1721 | "metadata": {}, 1722 | "outputs": [], 1723 | "source": [ 1724 | "a" 1725 | ] 1726 | }, 1727 | { 1728 | "cell_type": "code", 1729 | "execution_count": null, 1730 | "metadata": {}, 1731 | "outputs": [], 1732 | "source": [ 1733 | "a*v2" 1734 | ] 1735 | }, 1736 | { 1737 | "cell_type": "markdown", 1738 | "metadata": {}, 1739 | "source": [ 1740 | "What about matrix mutiplication? There are two ways. We can either use the `dot` function, which applies a matrix-matrix, matrix-vector, or inner vector multiplication to its two arguments: " 1741 | ] 1742 | }, 1743 | { 1744 | "cell_type": "code", 1745 | "execution_count": null, 1746 | "metadata": {}, 1747 | "outputs": [], 1748 | "source": [ 1749 | "a @ v2" 1750 | ] 1751 | }, 1752 | { 1753 | "cell_type": "markdown", 1754 | "metadata": {}, 1755 | "source": [ 1756 | "See also the related functions: `inner`, `outer`, `cross`, `kron`, `tensordot`. Try for example `help(kron)`." 1757 | ] 1758 | }, 1759 | { 1760 | "cell_type": "code", 1761 | "execution_count": null, 1762 | "metadata": { 1763 | "colab": { 1764 | "base_uri": "https://localhost:8080/", 1765 | "height": 52 1766 | }, 1767 | "colab_type": "code", 1768 | "id": "I3FnmoSeL9iu", 1769 | "outputId": "46f4575a-2e5e-4347-a34e-0cc5bd280110" 1770 | }, 1771 | "outputs": [], 1772 | "source": [ 1773 | "#" 1774 | ] 1775 | }, 1776 | { 1777 | "cell_type": "markdown", 1778 | "metadata": { 1779 | "colab_type": "text", 1780 | "id": "vmxPbrHASVeA" 1781 | }, 1782 | "source": [ 1783 | "You can also use the `@` operator which is equivalent to numpy's `dot` operator." 1784 | ] 1785 | }, 1786 | { 1787 | "cell_type": "code", 1788 | "execution_count": null, 1789 | "metadata": { 1790 | "colab": { 1791 | "base_uri": "https://localhost:8080/", 1792 | "height": 69 1793 | }, 1794 | "colab_type": "code", 1795 | "id": "zvUODeTxL9iw", 1796 | "outputId": "4093fc76-094f-4453-a421-a212b5226968" 1797 | }, 1798 | "outputs": [], 1799 | "source": [ 1800 | "#" 1801 | ] 1802 | }, 1803 | { 1804 | "cell_type": "markdown", 1805 | "metadata": { 1806 | "colab_type": "text", 1807 | "id": "FbE-1If_L9i0" 1808 | }, 1809 | "source": [ 1810 | "Numpy provides many useful functions for performing computations on arrays; one of the most useful is `sum`:" 1811 | ] 1812 | }, 1813 | { 1814 | "cell_type": "code", 1815 | "execution_count": null, 1816 | "metadata": { 1817 | "colab": { 1818 | "base_uri": "https://localhost:8080/", 1819 | "height": 69 1820 | }, 1821 | "colab_type": "code", 1822 | "id": "DZUdZvPrL9i0", 1823 | "outputId": "99cad470-d692-4b25-91c9-a57aa25f4c6e" 1824 | }, 1825 | "outputs": [], 1826 | "source": [ 1827 | "#" 1828 | ] 1829 | }, 1830 | { 1831 | "cell_type": "markdown", 1832 | "metadata": { 1833 | "colab_type": "text", 1834 | "id": "ahdVW4iUL9i3" 1835 | }, 1836 | "source": [ 1837 | "You can find the full list of mathematical functions provided by numpy in the [documentation](http://docs.scipy.org/doc/numpy/reference/routines.math.html).\n", 1838 | "\n", 1839 | "Apart from computing mathematical functions using arrays, we frequently need to reshape or otherwise manipulate data in arrays. The simplest example of this type of operation is transposing a matrix; to transpose a matrix, simply use the T attribute of an array object:" 1840 | ] 1841 | }, 1842 | { 1843 | "cell_type": "code", 1844 | "execution_count": null, 1845 | "metadata": { 1846 | "colab": { 1847 | "base_uri": "https://localhost:8080/", 1848 | "height": 104 1849 | }, 1850 | "colab_type": "code", 1851 | "id": "mkk03eNIL9i4", 1852 | "outputId": "499eec5a-55b7-473a-d4aa-9d023d63885a" 1853 | }, 1854 | "outputs": [], 1855 | "source": [ 1856 | "#" 1857 | ] 1858 | }, 1859 | { 1860 | "cell_type": "markdown", 1861 | "metadata": {}, 1862 | "source": [ 1863 | "#### `np.diag`" 1864 | ] 1865 | }, 1866 | { 1867 | "cell_type": "code", 1868 | "execution_count": null, 1869 | "metadata": {}, 1870 | "outputs": [], 1871 | "source": [ 1872 | "v2" 1873 | ] 1874 | }, 1875 | { 1876 | "cell_type": "code", 1877 | "execution_count": null, 1878 | "metadata": {}, 1879 | "outputs": [], 1880 | "source": [ 1881 | "np.diag(v2)" 1882 | ] 1883 | }, 1884 | { 1885 | "cell_type": "markdown", 1886 | "metadata": {}, 1887 | "source": [ 1888 | "Let us experiment with matrices\n", 1889 | "\n", 1890 | "$$ \n", 1891 | " A = \\begin{bmatrix} 2 & -1 \\\\ 3 & 0 \\end{bmatrix} \n", 1892 | " \\quad \\text{and} \\quad\n", 1893 | " b = \\begin{bmatrix} 2 \\\\ 1 \\end{bmatrix}\n", 1894 | "$$" 1895 | ] 1896 | }, 1897 | { 1898 | "cell_type": "code", 1899 | "execution_count": null, 1900 | "metadata": {}, 1901 | "outputs": [], 1902 | "source": [ 1903 | "A = [[2, -1],\n", 1904 | " [3, 0]]\n", 1905 | "A = np.array(A) # Convert from list to NumPy array\n", 1906 | "b = np.ones((2, 1)) # Shape is 2 x 1" 1907 | ] 1908 | }, 1909 | { 1910 | "cell_type": "markdown", 1911 | "metadata": {}, 1912 | "source": [ 1913 | "#### Inverse" 1914 | ] 1915 | }, 1916 | { 1917 | "cell_type": "code", 1918 | "execution_count": null, 1919 | "metadata": {}, 1920 | "outputs": [], 1921 | "source": [ 1922 | "np.linalg.inv(A)" 1923 | ] 1924 | }, 1925 | { 1926 | "cell_type": "markdown", 1927 | "metadata": {}, 1928 | "source": [ 1929 | "#### Determinant" 1930 | ] 1931 | }, 1932 | { 1933 | "cell_type": "code", 1934 | "execution_count": null, 1935 | "metadata": {}, 1936 | "outputs": [], 1937 | "source": [ 1938 | "np.linalg.det(A)" 1939 | ] 1940 | }, 1941 | { 1942 | "cell_type": "markdown", 1943 | "metadata": {}, 1944 | "source": [ 1945 | "#### Eigenvalues and eigenvectors" 1946 | ] 1947 | }, 1948 | { 1949 | "cell_type": "code", 1950 | "execution_count": null, 1951 | "metadata": {}, 1952 | "outputs": [], 1953 | "source": [ 1954 | "#" 1955 | ] 1956 | }, 1957 | { 1958 | "cell_type": "markdown", 1959 | "metadata": {}, 1960 | "source": [ 1961 | "Let us solve (for $x$) the problem \n", 1962 | "$$A x = b$$" 1963 | ] 1964 | }, 1965 | { 1966 | "cell_type": "code", 1967 | "execution_count": null, 1968 | "metadata": {}, 1969 | "outputs": [], 1970 | "source": [ 1971 | "#" 1972 | ] 1973 | }, 1974 | { 1975 | "cell_type": "markdown", 1976 | "metadata": {}, 1977 | "source": [ 1978 | "#### Linear Algebra: Exercises\n", 1979 | "(TBD)" 1980 | ] 1981 | }, 1982 | { 1983 | "cell_type": "code", 1984 | "execution_count": null, 1985 | "metadata": {}, 1986 | "outputs": [], 1987 | "source": [ 1988 | "#" 1989 | ] 1990 | } 1991 | ], 1992 | "metadata": { 1993 | "kernelspec": { 1994 | "display_name": "Python 3", 1995 | "language": "python", 1996 | "name": "python3" 1997 | }, 1998 | "language_info": { 1999 | "codemirror_mode": { 2000 | "name": "ipython", 2001 | "version": 3 2002 | }, 2003 | "file_extension": ".py", 2004 | "mimetype": "text/x-python", 2005 | "name": "python", 2006 | "nbconvert_exporter": "python", 2007 | "pygments_lexer": "ipython3", 2008 | "version": "3.9.4" 2009 | } 2010 | }, 2011 | "nbformat": 4, 2012 | "nbformat_minor": 2 2013 | } 2014 | -------------------------------------------------------------------------------- /archive/myfile.txt: -------------------------------------------------------------------------------- 1 | Hello, 2 | 3 | I'm content of a file 4 | I added a line!! Wow. -------------------------------------------------------------------------------- /archive/yetanotherfile.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenSourceEconomics/ose-course-primer/9ce7d6c2a5452dee11330c5a355cf8bb927fce5c/archive/yetanotherfile.txt -------------------------------------------------------------------------------- /data/bikes.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenSourceEconomics/ose-course-primer/9ce7d6c2a5452dee11330c5a355cf8bb927fce5c/data/bikes.csv -------------------------------------------------------------------------------- /lecture1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Lecture 1: Introduction" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Contents\n", 15 | "\n", 16 | "- [About Python](#What’s-Python?) \n", 17 | "- [Basic Basics](#Basic-Basics)\n", 18 | " - `\"hello wörld\"`\n", 19 | " - arithmetic\n", 20 | " - variables\n", 21 | " - strings\n", 22 | " - conditionals\n", 23 | " - lists\n", 24 | "- how to get help" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "**Note:** part of this overview is stolen from [QuantEcon](https://quantecon.org/). Thanks!" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "## What’s Python?\n", 39 | "\n", 40 | "[Python](https://www.python.org) is a general-purpose programming language conceived in 1989 by Dutch programmer [Guido van Rossum](https://en.wikipedia.org/wiki/Guido_van_Rossum).\n", 41 | "\n", 42 | "Python is free and open source, with development coordinated through the [Python Software Foundation](https://www.python.org/psf/).\n", 43 | "\n", 44 | "Python has experienced rapid adoption in the last decade and is now one of the most popular programming languages." 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "> “Python has gotten sufficiently weapons grade that we don’t descend into R\n", 52 | "> anymore. Sorry, R people. I used to be one of you but we no longer descend\n", 53 | "> into R.” – Chris Wiggins" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "### Common Uses\n", 61 | "\n", 62 | "Python is a general-purpose language used in almost all application domains such as\n", 63 | "\n", 64 | "- communications \n", 65 | "- web development \n", 66 | "- CGI and graphical user interfaces \n", 67 | "- game development \n", 68 | "- multimedia, data processing, security, etc., etc., etc. \n", 69 | "\n", 70 | "\n", 71 | "Used extensively by Internet services and high tech companies including\n", 72 | "\n", 73 | "- [Google](https://www.google.com/) \n", 74 | "- [Dropbox](https://www.dropbox.com/) \n", 75 | "- [Reddit](https://www.reddit.com/) \n", 76 | "- [YouTube](https://www.youtube.com/) \n", 77 | "- [Walt Disney Animation](https://pydanny-event-notes.readthedocs.org/en/latest/socalpiggies/20110526-wda.html)\n", 78 | "\n", 79 | "\n", 80 | "Python is very beginner-friendly and is often used to [teach computer science and programming](http://cacm.acm.org/blogs/blog-cacm/176450-python-is-now-the-most-popular-introductory-teaching-language-at-top-us-universities/fulltext).\n", 81 | "\n", 82 | "For reasons we will discuss, Python is particularly popular within the scientific community with users including NASA, CERN and practically all branches of academia.\n", 83 | "\n", 84 | "It is also [replacing familiar tools like Excel](https://news.efinancialcareers.com/us-en/3002556/python-replaced-excel-banking) in the fields of finance and banking." 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "### Relative Popularity\n", 92 | "\n", 93 | "The following chart, produced using Stack Overflow Trends, shows one measure of the relative popularity of Python\n", 94 | "\n", 95 | "\n", 96 | "\n", 97 | "The figure indicates not only that Python is widely used but also that adoption of Python has accelerated significantly since 2012.\n", 98 | "\n", 99 | "We suspect this is driven at least in part by uptake in the scientific\n", 100 | "domain, particularly in rapidly growing fields like data science." 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "For example, the popularity of [pandas](http://pandas.pydata.org/), a library for data analysis with Python has exploded, as seen here.\n", 108 | "\n", 109 | "(The corresponding time path for MATLAB is shown for comparison)\n", 110 | "\n", 111 | "" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "Note that pandas takes off in 2012, which is the same year that we see\n", 119 | "Python’s popularity begin to spike in the first figure.\n", 120 | "\n", 121 | "Overall, it’s clear that\n", 122 | "\n", 123 | "- Python is [one of the most popular programming languages worldwide](https://spectrum.ieee.org/computing/software/the-top-programming-languages-2019). \n", 124 | "- Python is a major tool for scientific computing, accounting for a rapidly rising share of scientific work around the globe. " 125 | ] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "metadata": {}, 130 | "source": [ 131 | "### Features\n", 132 | "\n", 133 | "Python is a [high-level language](https://en.wikipedia.org/wiki/High-level_programming_language) suitable for rapid development.\n", 134 | "\n", 135 | "It has a relatively small core language supported by many libraries.\n", 136 | "\n", 137 | "Other features of Python:\n", 138 | "\n", 139 | "- multiple programming styles are supported (procedural, object-oriented, functional, etc.) \n", 140 | "- it is interpreted rather than compiled. " 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "### Syntax and Design\n", 148 | "\n", 149 | "\n", 150 | "\n", 151 | "One nice feature of Python is its elegant syntax — we’ll see many examples later on.\n", 152 | "\n", 153 | "Elegant code might sound superfluous but in fact it’s highly beneficial because it makes the syntax easy to read and easy to remember.\n", 154 | "\n", 155 | "Remembering how to read from files, sort dictionaries and other such routine tasks means that you don’t need to break your flow in order to hunt down correct syntax.\n", 156 | "\n", 157 | "Closely related to elegant syntax is an elegant design.\n", 158 | "\n", 159 | "Features like iterators, generators, decorators and list comprehensions make Python highly expressive, allowing you to get more done with less code.\n", 160 | "\n", 161 | "[Namespaces](https://en.wikipedia.org/wiki/Namespace) improve productivity by cutting down on bugs and syntax errors." 162 | ] 163 | }, 164 | { 165 | "cell_type": "markdown", 166 | "metadata": {}, 167 | "source": [ 168 | "### Scientific Programming\n", 169 | "\n", 170 | "\n", 171 | "\n", 172 | "Python has become one of the core languages of scientific computing.\n", 173 | "\n", 174 | "It’s either the dominant player or a major player in\n", 175 | "\n", 176 | "- [machine learning and data science](http://scikit-learn.org/stable/) \n", 177 | "- [astronomy](http://www.astropy.org/) \n", 178 | "- [artificial intelligence](https://wiki.python.org/moin/PythonForArtificialIntelligence) \n", 179 | "- [chemistry](http://chemlab.github.io/chemlab/) \n", 180 | "- [computational biology](http://biopython.org/wiki/Main_Page) \n", 181 | "- [meteorology](https://pypi.org/project/meteorology/) \n", 182 | "\n", 183 | "\n", 184 | "Its popularity in economics is also rising." 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "## Basic Basics\n", 192 | "\n", 193 | "For most part of the course we will be working with Python in your browser using iPython Notebook. Here is an example block of code:" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": null, 199 | "metadata": {}, 200 | "outputs": [], 201 | "source": [ 202 | "print('Hello wörld')" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": {}, 208 | "source": [ 209 | "To run a block of code like the one above, click on it to select it and then you can either click the run button in the menu above:\n", 210 | "\n", 211 | "\n", 212 | "\n", 213 | "or type shift-enter. The output of the block is shown below the block.\n", 214 | "\n", 215 | "All of the code blocks on this page are interactive. Please make sure you run them all at least once. Feel free the change the code and see what the affect is." 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": {}, 222 | "outputs": [], 223 | "source": [] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "### Arithmetic\n", 237 | "\n", 238 | "Like every programming language, Python is a good calculator. Run the block of code below to make sure the answer is right!" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": {}, 245 | "outputs": [], 246 | "source": [ 247 | "1 + 1" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "Just wow. \n", 255 | "\n", 256 | "Now lets say you won the lottery. You are about to collect your millions, but first you have to answer this skill testing question:\n", 257 | "\n", 258 | "$$8+6*2*3-(15-13)$$\n", 259 | "\n", 260 | "Tricky one. Fortuntely Python can help. The order of operations you learned in school applies, BEDMAS (brackets, exponents, division, multiplication, addition, subtraction)" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": null, 266 | "metadata": {}, 267 | "outputs": [], 268 | "source": [] 269 | }, 270 | { 271 | "cell_type": "markdown", 272 | "metadata": {}, 273 | "source": [ 274 | "Numbers are valid Python code as are the common operators, +, /, * and -. You can write different types of numbers including integers, real numbers (floating point) and negative integers." 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "metadata": {}, 287 | "source": [ 288 | "**Modulus tells us if a given number is divisible by another number!**\n", 289 | "\n", 290 | "If the result is 0, we know the answer is yes, the number on the left is divisible by the number on the right. \n", 291 | "\n", 292 | "If the result is anything but 0, we know the number on the left is not divisible by the number on the right. \n", 293 | "\n", 294 | "Modulus is very useful and is widely used even by advanced programmers, and often in context that have nothing to do with mathematics. Soon you will learn more about this." 295 | ] 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "metadata": {}, 300 | "source": [ 301 | "Since 42 is literally 42, we call these numbers *literals*. You are literally writing number in your Python code." 302 | ] 303 | }, 304 | { 305 | "cell_type": "markdown", 306 | "metadata": {}, 307 | "source": [ 308 | "## Variables\n", 309 | "\n", 310 | "So you just had a big meal to celebrate, and now you need to calculate the tip." 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": null, 316 | "metadata": {}, 317 | "outputs": [], 318 | "source": [ 319 | "meal = 200.0\n", 320 | "tip_percent = 0.1\n", 321 | "\n", 322 | "meal * tip_percent" 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": {}, 328 | "source": [ 329 | "If you want to make it more user friendly you could do the following." 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": null, 335 | "metadata": {}, 336 | "outputs": [], 337 | "source": [] 338 | }, 339 | { 340 | "cell_type": "markdown", 341 | "metadata": {}, 342 | "source": [ 343 | "Because of BEDMAS we don't need brackets, but `meal * (tip_percent / 100)` would work too." 344 | ] 345 | }, 346 | { 347 | "cell_type": "markdown", 348 | "metadata": {}, 349 | "source": [ 350 | "`meal` and `tip_percent` aren't literal numbers, they are variables.\n", 351 | "\n", 352 | "In Python variables are like buckets (dump trucks?). You can put anything you want in them. Just give them a name and you can use them in place of the literal value.\n", 353 | "\n", 354 | "Above, `meal` was 200.00 but we could also set meal to the text `'Hello, World'`" 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": null, 360 | "metadata": {}, 361 | "outputs": [], 362 | "source": [ 363 | "meal = 'Hello, World'" 364 | ] 365 | }, 366 | { 367 | "cell_type": "code", 368 | "execution_count": null, 369 | "metadata": {}, 370 | "outputs": [], 371 | "source": [] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": {}, 376 | "source": [ 377 | "The value a variable has only depends on what it was last assigned.\n", 378 | "\n", 379 | "It is like a spreadsheet except you choose the names for the cells yourself." 380 | ] 381 | }, 382 | { 383 | "cell_type": "markdown", 384 | "metadata": {}, 385 | "source": [ 386 | "## Strings\n", 387 | "\n", 388 | "Numbers are great... but most of our day to day computing needs involves text, from emails to tweets to documents.\n", 389 | "\n", 390 | "We have already seen a text literal in Python, \"Hello, World!\"" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": null, 396 | "metadata": {}, 397 | "outputs": [], 398 | "source": [ 399 | "meal = 'Hello, World'" 400 | ] 401 | }, 402 | { 403 | "cell_type": "code", 404 | "execution_count": null, 405 | "metadata": {}, 406 | "outputs": [], 407 | "source": [] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "Text literals are surrounded by quotes. Without the quotes Hello by itself would be viewed as a variable name.\n", 414 | "\n", 415 | "You can use either double quotes (\") or single quotes (') for text literals.\n", 416 | "\n", 417 | "As we saw before we can also save text literals in variables.\n", 418 | "\n", 419 | "### What's a String?\n", 420 | "\n", 421 | "Programmers call text literals *strings* because we are weird like that. From now on we will only refer to strings, but we just mean pieces of text inside our code.\n", 422 | "\n", 423 | "Let's use strings with variables!" 424 | ] 425 | }, 426 | { 427 | "cell_type": "code", 428 | "execution_count": null, 429 | "metadata": {}, 430 | "outputs": [], 431 | "source": [ 432 | "weird_variable = \"green blobb\"\n", 433 | "your_name = weird_variable" 434 | ] 435 | }, 436 | { 437 | "cell_type": "code", 438 | "execution_count": null, 439 | "metadata": {}, 440 | "outputs": [], 441 | "source": [] 442 | }, 443 | { 444 | "cell_type": "markdown", 445 | "metadata": {}, 446 | "source": [ 447 | "Let's say you are really happy, and you want to make sure everyone knows it, you can use upper. \"upper\" is short for uppercase and you will see what it does by running the code block below." 448 | ] 449 | }, 450 | { 451 | "cell_type": "code", 452 | "execution_count": null, 453 | "metadata": {}, 454 | "outputs": [], 455 | "source": [ 456 | "string = \"Hello, World\"" 457 | ] 458 | }, 459 | { 460 | "cell_type": "code", 461 | "execution_count": null, 462 | "metadata": {}, 463 | "outputs": [], 464 | "source": [] 465 | }, 466 | { 467 | "cell_type": "markdown", 468 | "metadata": {}, 469 | "source": [ 470 | "Maybe you are feeling a bit sad and you want to be quiet, you can then use lower." 471 | ] 472 | }, 473 | { 474 | "cell_type": "code", 475 | "execution_count": null, 476 | "metadata": {}, 477 | "outputs": [], 478 | "source": [] 479 | }, 480 | { 481 | "cell_type": "markdown", 482 | "metadata": {}, 483 | "source": [ 484 | "We use the dot (\".\") operator to call these operations on the string. What lower and upper operate on comes before the dot and needs to be a string variable or literal." 485 | ] 486 | }, 487 | { 488 | "cell_type": "markdown", 489 | "metadata": {}, 490 | "source": [ 491 | "Formating\n", 492 | "---------\n", 493 | "\n", 494 | "Sometimes you want to create a string out of a few other strings. Above we printed\n", 495 | "\n", 496 | " Hello,\n", 497 | " Your Name\n", 498 | "\n", 499 | "by using two print statements, but it would be nice to output \"Hello, Your Name!\" instead. (Where Your Name is actually your name... oh variables)\n", 500 | "\n", 501 | "We can do this with the string operation called format. Format is different from lower and upper because it can take other arguments. An *agrument* is what coders call the value passed to an operation or function, it doesn't mean we are fighting." 502 | ] 503 | }, 504 | { 505 | "cell_type": "code", 506 | "execution_count": null, 507 | "metadata": {}, 508 | "outputs": [], 509 | "source": [ 510 | "your_name = \"Gregor\"" 511 | ] 512 | }, 513 | { 514 | "cell_type": "code", 515 | "execution_count": null, 516 | "metadata": {}, 517 | "outputs": [], 518 | "source": [] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": null, 523 | "metadata": {}, 524 | "outputs": [], 525 | "source": [ 526 | "string = \"hello %s\"" 527 | ] 528 | }, 529 | { 530 | "cell_type": "code", 531 | "execution_count": null, 532 | "metadata": {}, 533 | "outputs": [], 534 | "source": [] 535 | }, 536 | { 537 | "cell_type": "code", 538 | "execution_count": null, 539 | "metadata": {}, 540 | "outputs": [], 541 | "source": [ 542 | "cnumber = 1\n", 543 | "print('my favorite number %s and %s' %(cnumber,2))" 544 | ] 545 | }, 546 | { 547 | "cell_type": "markdown", 548 | "metadata": {}, 549 | "source": [ 550 | "## Conditions\n", 551 | "\n", 552 | "Has an application ever ask you a question? Maybe it asks you if you really want to quit because unsaved changed might lost, or if you want to leave a webpage. If you answer OK one thing happen, like your application closing, but if you answer No or Cancel something else happens. In all those cases there is a special piece of code that is being run somewhere, it is an *if* condition.\n", 553 | "\n", 554 | "Like all languages, Python allows us to conditionally run code.\n", 555 | "\n", 556 | "To have an if condition we need the idea of something being true and something being false. Remember, we call numbers \"integers\" and \"floating point\", and text \"strings\". We call true or false \"boolean\" values. True would represent OK where as false would represent No or Cancel in the example above.\n", 557 | "\n", 558 | "The literal values in Python for true and false are \"True\" and \"False\"\n" 559 | ] 560 | }, 561 | { 562 | "cell_type": "markdown", 563 | "metadata": {}, 564 | "source": [ 565 | "Sometimes you hear the word 'binary' related with computers. Binary just means that there are two options, 0 and 1. For example we may have a case where the statement \"it's raining\", is True or False.\n", 566 | "\n", 567 | "This has to do with the way computers work; the processing unit (CPU) of the computer is made of billions of tiny gates. These tiny gates can only peform one action, they can open or close. Related with this, there is a system of mathematics called boolean logic. Boolean means the same thing as binary, that there are only two possible states. Instead of talking about gates or 0 and 1, in Boolean logic we talk about True and False. Either something is true, or it's false. When you hear about Boolean Logic for the first time, it sounds confusing, but actually it is really as simple as that. \n", 568 | "\n", 569 | "Understanding this clearly, you take a giant leap towards understanding computers. Boolean logic, and the statements we use to instruct the computer based on that type of simplistic logic, is the language of computers. Python gives us humans an easy to learn and understand way to use boolean logic to tell computers what we want them to do. Let's see a couple of examples." 570 | ] 571 | }, 572 | { 573 | "cell_type": "code", 574 | "execution_count": null, 575 | "metadata": {}, 576 | "outputs": [], 577 | "source": [] 578 | }, 579 | { 580 | "cell_type": "markdown", 581 | "metadata": {}, 582 | "source": [ 583 | "The basic principle is that simple. Boolean logic also leverage 'and' and 'or' statements. " 584 | ] 585 | }, 586 | { 587 | "cell_type": "code", 588 | "execution_count": null, 589 | "metadata": {}, 590 | "outputs": [], 591 | "source": [] 592 | }, 593 | { 594 | "cell_type": "markdown", 595 | "metadata": {}, 596 | "source": [ 597 | "With or statement we are saying that one of the options is true, and with and statement we are saying that both are true. We can also do the reverse and say that something is not. In other words, we have two options, statements that are saying something is true, and if it is true in fact, we get the respone True, and statements that are saying something is not true, and if it is not true, we get the response True (and if it's true, we get False)." 598 | ] 599 | }, 600 | { 601 | "cell_type": "code", 602 | "execution_count": null, 603 | "metadata": {}, 604 | "outputs": [], 605 | "source": [] 606 | }, 607 | { 608 | "cell_type": "markdown", 609 | "metadata": {}, 610 | "source": [ 611 | "Actually, we can join together as many such statements as we like using and and or operators.\n", 612 | "\n", 613 | "So, I somehow suspect that `5` is a prime number. So let us see if we can confirm this..." 614 | ] 615 | }, 616 | { 617 | "cell_type": "code", 618 | "execution_count": null, 619 | "metadata": {}, 620 | "outputs": [], 621 | "source": [] 622 | }, 623 | { 624 | "cell_type": "markdown", 625 | "metadata": {}, 626 | "source": [ 627 | "To clarify, we confirm that number 5 is not divisible by any other number than 1 and itself. Actually all numbers are divisible by 1 and itself, so this is to say it's not divisible. Also numbers can't be divisible by numbers that are larger than the number itself, so it's enough to check all the numbers between 1 and the number itself to get the answer if a given number is prime or not. This sounds fine as long as we deal with small numbers, but how about when we want to answer the same question for a very large number?\n", 628 | "\n", 629 | "Because it's so easy to say if small numbers are prime or not, mathematicians are generally only interested in finding really big primes. In the next section we'll learn just how big, and then come back to learn how big numbers can be verified using the techniques we've learn already." 630 | ] 631 | }, 632 | { 633 | "cell_type": "markdown", 634 | "metadata": {}, 635 | "source": [ 636 | "We can write expressions with operations too." 637 | ] 638 | }, 639 | { 640 | "cell_type": "code", 641 | "execution_count": null, 642 | "metadata": {}, 643 | "outputs": [], 644 | "source": [] 645 | }, 646 | { 647 | "cell_type": "markdown", 648 | "metadata": {}, 649 | "source": [ 650 | "In order to write an \"if\" statement we need code that spans multiple lines\n", 651 | "\n", 652 | " if condition:\n", 653 | " print(\"Condition is True\")\n", 654 | " else:\n", 655 | " print(\"Condition is False\")\n", 656 | "\n", 657 | "Some things to notice. The if condition ends in a colon (\":\"). In Python blocks of code are indicated with a colon (\":\") and are grouped by white space. Notice the else also ends with a colon (\":\"), \"else:\". Let's try changing the condition and see what happens." 658 | ] 659 | }, 660 | { 661 | "cell_type": "code", 662 | "execution_count": null, 663 | "metadata": {}, 664 | "outputs": [], 665 | "source": [] 666 | }, 667 | { 668 | "cell_type": "markdown", 669 | "metadata": {}, 670 | "source": [ 671 | "About that white space, consider the following code:\n", 672 | "\n", 673 | " if condition:\n", 674 | " print(\"Condition is True\")\n", 675 | " else:\n", 676 | " print(\"Condition is False\")\n", 677 | " print(\"Condition is True or False, either way this is outputted\")\n", 678 | "\n", 679 | "Since the last print statement isn't indented it gets run after the if block or the else block.\n", 680 | "\n", 681 | "You can play with this. Try indenting the last print statement below and see what happens." 682 | ] 683 | }, 684 | { 685 | "cell_type": "code", 686 | "execution_count": null, 687 | "metadata": {}, 688 | "outputs": [], 689 | "source": [] 690 | }, 691 | { 692 | "cell_type": "markdown", 693 | "metadata": {}, 694 | "source": [ 695 | "Exercise\n", 696 | "---------\n", 697 | "\n", 698 | "You can also use \"and\" and \"or\" to combine conditions. Let's look at and.\n", 699 | "\n", 700 | " True and True is True\n", 701 | " True and False is False\n", 702 | " False and True is False\n", 703 | " False and False is False\n", 704 | "\n", 705 | "With \"and\" both conditions have to be True to be True. \n", 706 | "\n", 707 | "Below change the values of the three variables to make the entire \"if condition\" true." 708 | ] 709 | }, 710 | { 711 | "cell_type": "code", 712 | "execution_count": null, 713 | "metadata": {}, 714 | "outputs": [], 715 | "source": [ 716 | "# Edit the values of these 3 variables\n", 717 | "boolean_literal = False\n", 718 | "number = 8\n", 719 | "string_literal = \"I like to count sheep before bed.\"\n", 720 | "\n", 721 | "# Leave this code the same please\n", 722 | "if number > 10 and boolean_literal and \"cows\" in string_literal:\n", 723 | " print(\"Success!\")\n", 724 | "else:\n", 725 | " print(\"Try again!\")" 726 | ] 727 | }, 728 | { 729 | "cell_type": "markdown", 730 | "metadata": {}, 731 | "source": [ 732 | "### Lists" 733 | ] 734 | }, 735 | { 736 | "cell_type": "markdown", 737 | "metadata": {}, 738 | "source": [ 739 | "Python knows a number of _compound_ data types, which are used to group together other values. The most versatile is the [*list*](https://docs.python.org/3.5/library/stdtypes.html#typesseq-list), which can be written as a sequence of comma-separated values (items) between square brackets. Lists might contain items of different types, but usually the items all have the same type." 740 | ] 741 | }, 742 | { 743 | "cell_type": "code", 744 | "execution_count": null, 745 | "metadata": {}, 746 | "outputs": [], 747 | "source": [ 748 | "squares = [1, 4, 9, 16, 25]" 749 | ] 750 | }, 751 | { 752 | "cell_type": "code", 753 | "execution_count": null, 754 | "metadata": {}, 755 | "outputs": [], 756 | "source": [] 757 | }, 758 | { 759 | "cell_type": "markdown", 760 | "metadata": {}, 761 | "source": [ 762 | "Like strings (and all other built-in [sequence](https://docs.python.org/3.5/glossary.html#term-sequence) types), lists can be indexed and sliced:" 763 | ] 764 | }, 765 | { 766 | "cell_type": "code", 767 | "execution_count": null, 768 | "metadata": {}, 769 | "outputs": [], 770 | "source": [] 771 | }, 772 | { 773 | "cell_type": "markdown", 774 | "metadata": {}, 775 | "source": [ 776 | "Lists also support concatenation with the `+` operator:" 777 | ] 778 | }, 779 | { 780 | "cell_type": "code", 781 | "execution_count": null, 782 | "metadata": {}, 783 | "outputs": [], 784 | "source": [] 785 | }, 786 | { 787 | "cell_type": "markdown", 788 | "metadata": {}, 789 | "source": [ 790 | "Unlike strings, which are [immutable](https://docs.python.org/3.5/glossary.html#term-immutable), lists are a [mutable](https://docs.python.org/3.5/glossary.html#term-mutable) type, which means you can change any value in the list:" 791 | ] 792 | }, 793 | { 794 | "cell_type": "code", 795 | "execution_count": null, 796 | "metadata": {}, 797 | "outputs": [], 798 | "source": [ 799 | "cubes = [1, 8, 27, 65, 125] # Something's wrong here ..." 800 | ] 801 | }, 802 | { 803 | "cell_type": "code", 804 | "execution_count": null, 805 | "metadata": {}, 806 | "outputs": [], 807 | "source": [] 808 | }, 809 | { 810 | "cell_type": "markdown", 811 | "metadata": {}, 812 | "source": [ 813 | "Use the list's `append()` method to add new items to the end of the list:" 814 | ] 815 | }, 816 | { 817 | "cell_type": "code", 818 | "execution_count": null, 819 | "metadata": {}, 820 | "outputs": [], 821 | "source": [ 822 | "cubes.append(216)" 823 | ] 824 | }, 825 | { 826 | "cell_type": "code", 827 | "execution_count": null, 828 | "metadata": {}, 829 | "outputs": [], 830 | "source": [] 831 | }, 832 | { 833 | "cell_type": "markdown", 834 | "metadata": {}, 835 | "source": [ 836 | "You can even assign to slices, which can change the size of the list or clear it entirely:" 837 | ] 838 | }, 839 | { 840 | "cell_type": "code", 841 | "execution_count": null, 842 | "metadata": {}, 843 | "outputs": [], 844 | "source": [ 845 | "letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']" 846 | ] 847 | }, 848 | { 849 | "cell_type": "code", 850 | "execution_count": null, 851 | "metadata": {}, 852 | "outputs": [], 853 | "source": [] 854 | }, 855 | { 856 | "cell_type": "markdown", 857 | "metadata": {}, 858 | "source": [ 859 | "The built-in [`len()`](https://docs.python.org/3.5/library/functions.html#len) function also applies to lists:" 860 | ] 861 | }, 862 | { 863 | "cell_type": "code", 864 | "execution_count": null, 865 | "metadata": {}, 866 | "outputs": [], 867 | "source": [ 868 | "letters = ['a','b','c']" 869 | ] 870 | }, 871 | { 872 | "cell_type": "code", 873 | "execution_count": null, 874 | "metadata": {}, 875 | "outputs": [], 876 | "source": [] 877 | }, 878 | { 879 | "cell_type": "markdown", 880 | "metadata": {}, 881 | "source": [ 882 | "You can nest lists, which means to create lists that contain other lists. For example:" 883 | ] 884 | }, 885 | { 886 | "cell_type": "code", 887 | "execution_count": null, 888 | "metadata": {}, 889 | "outputs": [], 890 | "source": [ 891 | "n = [1,2,3]\n", 892 | "x = [n, letters]" 893 | ] 894 | }, 895 | { 896 | "cell_type": "code", 897 | "execution_count": null, 898 | "metadata": {}, 899 | "outputs": [], 900 | "source": [] 901 | }, 902 | { 903 | "cell_type": "markdown", 904 | "metadata": {}, 905 | "source": [ 906 | "List literals are all about square brackets (\"[ ]\") and commas (\",\"). You can create a list of literals by wrapping them in square brackets and separating them with commas.\n", 907 | "\n", 908 | "You can even mix different types of things into the same list; numbers, strings, booleans." 909 | ] 910 | }, 911 | { 912 | "cell_type": "code", 913 | "execution_count": null, 914 | "metadata": {}, 915 | "outputs": [], 916 | "source": [ 917 | "[True, \"Awesome\", 0]" 918 | ] 919 | }, 920 | { 921 | "cell_type": "markdown", 922 | "metadata": {}, 923 | "source": [ 924 | "We can put variables into a list and set a variable to a list." 925 | ] 926 | }, 927 | { 928 | "cell_type": "code", 929 | "execution_count": null, 930 | "metadata": {}, 931 | "outputs": [], 932 | "source": [ 933 | "#" 934 | ] 935 | }, 936 | { 937 | "cell_type": "markdown", 938 | "metadata": {}, 939 | "source": [ 940 | "Let us also review some operations and methods on lists..." 941 | ] 942 | }, 943 | { 944 | "cell_type": "code", 945 | "execution_count": null, 946 | "metadata": {}, 947 | "outputs": [], 948 | "source": [] 949 | }, 950 | { 951 | "cell_type": "markdown", 952 | "metadata": {}, 953 | "source": [ 954 | "Most of these concepts also apply to strings! " 955 | ] 956 | }, 957 | { 958 | "cell_type": "code", 959 | "execution_count": null, 960 | "metadata": {}, 961 | "outputs": [], 962 | "source": [] 963 | }, 964 | { 965 | "cell_type": "markdown", 966 | "metadata": {}, 967 | "source": [ 968 | "Sweet. Let's stop learning the basic concepts here and put it in to practice with something interesting in the next episode. But first, let's summarize the learnings of this introductory section." 969 | ] 970 | }, 971 | { 972 | "cell_type": "markdown", 973 | "metadata": {}, 974 | "source": [ 975 | "### Exceptional Python and getting help\n", 976 | "\n", 977 | "Python only understands certain code. When you write something Python doesn't understand it throws an exception and tries to explain what went wrong, but it can only speak in a broken Pythonesque english. Let's see some examples by running these code blocks" 978 | ] 979 | }, 980 | { 981 | "cell_type": "code", 982 | "execution_count": null, 983 | "metadata": {}, 984 | "outputs": [], 985 | "source": [ 986 | "gibberish" 987 | ] 988 | }, 989 | { 990 | "cell_type": "code", 991 | "execution_count": null, 992 | "metadata": {}, 993 | "outputs": [], 994 | "source": [ 995 | "print('Hello' # EOF = End Of File" 996 | ] 997 | }, 998 | { 999 | "cell_type": "code", 1000 | "execution_count": null, 1001 | "metadata": {}, 1002 | "outputs": [], 1003 | "source": [ 1004 | "print('Hello)" 1005 | ] 1006 | }, 1007 | { 1008 | "cell_type": "code", 1009 | "execution_count": null, 1010 | "metadata": {}, 1011 | "outputs": [], 1012 | "source": [ 1013 | "200 / 0" 1014 | ] 1015 | }, 1016 | { 1017 | "cell_type": "markdown", 1018 | "metadata": {}, 1019 | "source": [ 1020 | "Python tries to tell you where it stopped understanding, but in the above examples, each program is only 1 line long. \n", 1021 | "\n", 1022 | "Finally it tells you the type of thing that went wrong, (NameError, SyntaxError, ZeroDivisionError) and a bit more information like \"name 'gibberish' is not defined\" or \"unexpected EOF while parsing\".\n", 1023 | "\n", 1024 | "Unfortunately you might not find \"unexpected EOF while parsing\" too helpful. EOF stands for End of File, but what file? What is parsing? Python does it's best, but it does take a bit of time to develop a knack for what these messages mean. If you run into an error you don't understand please ask a tutor.\n", 1025 | "\n", 1026 | "Exercises\n", 1027 | "---------\n", 1028 | "\n", 1029 | "Try to fix the two blocks of code so that they run successfully" 1030 | ] 1031 | }, 1032 | { 1033 | "cell_type": "code", 1034 | "execution_count": null, 1035 | "metadata": {}, 1036 | "outputs": [], 1037 | "source": [ 1038 | "print(Hello, World!')" 1039 | ] 1040 | }, 1041 | { 1042 | "cell_type": "code", 1043 | "execution_count": null, 1044 | "metadata": {}, 1045 | "outputs": [], 1046 | "source": [ 1047 | "answer = 3 * 8\n", 1048 | "print(anwer)" 1049 | ] 1050 | }, 1051 | { 1052 | "cell_type": "markdown", 1053 | "metadata": {}, 1054 | "source": [ 1055 | "### Getting help\n", 1056 | "\n", 1057 | "We are happy to help you! But... sometimes it is hard:\n", 1058 | "\n", 1059 | "> \"Geht irgendwie nicht\" (\"it doesn't work\")\n", 1060 | "\n", 1061 | "=> ***Context matters!*** <=\n", 1062 | "\n", 1063 | "Writing a *good* bug report is an art\n", 1064 | "\n", 1065 | "- https://github.com/stevemao/github-issue-templates/blob/master/bugs-only/ISSUE_TEMPLATE.md\n", 1066 | "- https://developer.mozilla.org/en-US/docs/Mozilla/QA/Bug_writing_guidelines\n", 1067 | "- https://www.chiark.greenend.org.uk/~sgtatham/bugs.html" 1068 | ] 1069 | }, 1070 | { 1071 | "cell_type": "markdown", 1072 | "metadata": {}, 1073 | "source": [ 1074 | "> \"So I loaded the disk on to my Windows . . .\"\n", 1075 | "\n", 1076 | "Writing clearly is essential in an error bug report. \n", 1077 | "\n", 1078 | "* **Be specific.** If you can do the same thing two different ways, state which one you used. \"I selected Load\" might mean \"I clicked on Load\" or \"I pressed Alt-L\". Say which you did. Sometimes it matters.\n", 1079 | "* **Be complete.** Tell everything you did. \"I wanted X. You told me to do Y, but X still does not work.\" (...but actually, Y did not work)\n", 1080 | "* **Provide context.** Report the background, such as e.g. the operating system. If you try to do something on Windows 98 and you don't have admin rights, that is definitely an important background.\n", 1081 | "* **Be verbose.** Give more information rather than less. If you say too much, the programmer can ignore some of it. If you say too little, they have to come back and ask more questions. One bug report I received was a single sentence; every time I asked for more information, the reporter would reply with another single sentence. It took me several weeks to get a useful amount of information, because it turned up one short sentence at a time.\n", 1082 | "* **Be careful of pronouns.** Don't use words like \"it\", or references like \"the window\", when it's unclear what they mean. Consider this: \"I started FooApp. It put up a warning window. I tried to close it and it crashed.\" It isn't clear what the user tried to close. Did they try to close the warning window, or the whole of FooApp? It makes a difference. Instead, you could say \"I started FooApp, which put up a warning window. I tried to close the warning window, and FooApp crashed.\" This is longer and more repetitive, but also clearer and less easy to misunderstand.\n", 1083 | "* **Read what you wrote.** Read the report back to yourself, and see if you think it's clear. If you have listed a sequence of actions which should produce the failure, try following them yourself, to see if you missed a step.\n", 1084 | "\n", 1085 | "When you ask for help, make sure that you provide all the information that is potentially necessary." 1086 | ] 1087 | } 1088 | ], 1089 | "metadata": { 1090 | "kernelspec": { 1091 | "display_name": "Python 3", 1092 | "language": "python", 1093 | "name": "python3" 1094 | }, 1095 | "language_info": { 1096 | "codemirror_mode": { 1097 | "name": "ipython", 1098 | "version": 3 1099 | }, 1100 | "file_extension": ".py", 1101 | "mimetype": "text/x-python", 1102 | "name": "python", 1103 | "nbconvert_exporter": "python", 1104 | "pygments_lexer": "ipython3", 1105 | "version": "3.9.3" 1106 | } 1107 | }, 1108 | "nbformat": 4, 1109 | "nbformat_minor": 2 1110 | } 1111 | -------------------------------------------------------------------------------- /lecture2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Lecture 2: Loops and functions" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Contents\n", 15 | "\n", 16 | "* Summary of lecture 1\n", 17 | "* Collections \n", 18 | "* Mutabillity/shallow & deep copy\n", 19 | "* Loops\n", 20 | "* Lunctions" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Summary of Lecture 1\n", 28 | "\n", 29 | "Last time: \n", 30 | " - `\"hello wörld\"`\n", 31 | " - arithmetic\n", 32 | " - variables\n", 33 | " - strings\n", 34 | " - conditionals\n", 35 | " - lists" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "#" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": { 50 | "slideshow": { 51 | "slide_type": "slide" 52 | }, 53 | "toc-hr-collapsed": false 54 | }, 55 | "source": [ 56 | "## Collections\n", 57 | "\n", 58 | "- Lists are an example of a *collection*.\n", 59 | "\n", 60 | "- A collection is a type of value that can contain other values.\n", 61 | "\n", 62 | "- There are other collection types in Python:\n", 63 | "\n", 64 | " - `tuple`\n", 65 | " - `dict`\n", 66 | " - `set` (not treated here)" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": { 72 | "slideshow": { 73 | "slide_type": "slide" 74 | } 75 | }, 76 | "source": [ 77 | "### Tuples\n", 78 | "\n", 79 | "- Tuples are another way to combine different values.\n", 80 | "\n", 81 | "- The combined values can be of different types.\n", 82 | "\n", 83 | "- Like lists, they have a well-defined ordering and can be indexed.\n", 84 | "\n", 85 | "- To create a tuple in Python, use round brackets instead of square brackets" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": null, 91 | "metadata": {}, 92 | "outputs": [], 93 | "source": [ 94 | "tuple1 = (50, 'hello')" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "#" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": { 109 | "slideshow": { 110 | "slide_type": "slide" 111 | } 112 | }, 113 | "source": [ 114 | "#### Tuples are immutable\n", 115 | "\n", 116 | "- Unlike lists, tuples are *immutable*. Once we have created a tuple we cannot add values to it.\n", 117 | "\n" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": null, 123 | "metadata": {}, 124 | "outputs": [], 125 | "source": [ 126 | "#" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "...but... why #(*&_% do we need both, `tuples` and `lists`?\n", 134 | "\n", 135 | "Answer 1: `¯\\_(ツ)_/¯`\n", 136 | "\n", 137 | "Answer 2: a matter of taste\n", 138 | "\n", 139 | "(Real) Answer 3:" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "%timeit [\"fee\", \"fie\", \"fo\", \"fum\"] # Zzz..." 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": null, 154 | "metadata": {}, 155 | "outputs": [], 156 | "source": [ 157 | "%timeit (\"fee\", \"fie\", \"fo\", \"fum\") # woaaaah..!" 158 | ] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": {}, 163 | "source": [ 164 | "(Real) Answer 4a: sometimes you want to be very concrete" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "(Real) Answer 4b: tuples are easier to debug" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "(Real) Answer 4c: https://www.afternerd.com/blog/difference-between-list-tuple" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "(Not an) Answer 5:" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": 1, 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "huple = ('hurz','hunk','hulk')" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": 2, 200 | "metadata": {}, 201 | "outputs": [ 202 | { 203 | "data": { 204 | "text/plain": [ 205 | "tuple" 206 | ] 207 | }, 208 | "execution_count": 2, 209 | "metadata": {}, 210 | "output_type": "execute_result" 211 | } 212 | ], 213 | "source": [ 214 | "type(huple)" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 3, 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [ 223 | "hist = list(huple)" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": 4, 229 | "metadata": {}, 230 | "outputs": [ 231 | { 232 | "data": { 233 | "text/plain": [ 234 | "list" 235 | ] 236 | }, 237 | "execution_count": 4, 238 | "metadata": {}, 239 | "output_type": "execute_result" 240 | } 241 | ], 242 | "source": [ 243 | "type(hist)" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": null, 249 | "metadata": {}, 250 | "outputs": [], 251 | "source": [ 252 | "hist" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": { 258 | "slideshow": { 259 | "slide_type": "slide" 260 | } 261 | }, 262 | "source": [ 263 | "### Dictionaries\n", 264 | "\n", 265 | "- A dictionary contains a mapping between *keys*, and corresponding *values*.\n", 266 | " \n", 267 | " - Mathematically it is a one-to-one function with a finite domain and range.\n", 268 | " \n", 269 | "- Given a key, we can very quickly look up the corresponding value.\n", 270 | "\n", 271 | "- The values can be any type (and need not all be of the same type).\n", 272 | "\n", 273 | "- Keys can be any immutable (hashable) type.\n", 274 | "\n", 275 | "- They are abbreviated by the keyword `dict`.\n", 276 | "\n", 277 | "- In other programming languages they are sometimes called *associative arrays*." 278 | ] 279 | }, 280 | { 281 | "cell_type": "markdown", 282 | "metadata": { 283 | "slideshow": { 284 | "slide_type": "slide" 285 | } 286 | }, 287 | "source": [ 288 | "#### Creating a dictionary\n" 289 | ] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "metadata": { 294 | "slideshow": { 295 | "slide_type": "slide" 296 | } 297 | }, 298 | "source": [ 299 | "- We can use any immutable type for the keys of a dictionary\n", 300 | "\n", 301 | "- For example, we can map names onto integers:" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": 5, 307 | "metadata": {}, 308 | "outputs": [], 309 | "source": [ 310 | "#" 311 | ] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "metadata": {}, 316 | "source": [ 317 | "- A dictionary can also contain any set of key-value pairs.\n", 318 | "\n", 319 | "- Create a dictionary:" 320 | ] 321 | }, 322 | { 323 | "cell_type": "code", 324 | "execution_count": null, 325 | "metadata": {}, 326 | "outputs": [], 327 | "source": [ 328 | "#" 329 | ] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "metadata": {}, 334 | "source": [ 335 | "- The above initialises the dictionary students so that it contains three key-value pairs.\n", 336 | "\n", 337 | "- The keys are the student id numbers (integers).\n", 338 | "\n", 339 | "- The values are the names of the students (strings)." 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": null, 345 | "metadata": {}, 346 | "outputs": [], 347 | "source": [ 348 | "type(students)" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": { 354 | "slideshow": { 355 | "slide_type": "slide" 356 | } 357 | }, 358 | "source": [ 359 | "#### Accessing the values in a dictionary\n", 360 | "\n", 361 | "- We can access the value corresponding to a given key using the same syntax to access particular elements of a list: " 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": 6, 367 | "metadata": {}, 368 | "outputs": [], 369 | "source": [ 370 | "#" 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": {}, 376 | "source": [ 377 | "- Accessing a non-existent key will generate a `KeyError`:" 378 | ] 379 | }, 380 | { 381 | "cell_type": "code", 382 | "execution_count": 7, 383 | "metadata": {}, 384 | "outputs": [], 385 | "source": [ 386 | "#" 387 | ] 388 | }, 389 | { 390 | "cell_type": "markdown", 391 | "metadata": { 392 | "slideshow": { 393 | "slide_type": "slide" 394 | } 395 | }, 396 | "source": [ 397 | "#### Updating dictionary entries\n", 398 | "\n", 399 | "- Dictionaries are mutable, so we can update the mapping:" 400 | ] 401 | }, 402 | { 403 | "cell_type": "code", 404 | "execution_count": null, 405 | "metadata": {}, 406 | "outputs": [], 407 | "source": [ 408 | "#" 409 | ] 410 | }, 411 | { 412 | "cell_type": "markdown", 413 | "metadata": {}, 414 | "source": [ 415 | "- We can also grow the dictionary by adding new keys:" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": null, 421 | "metadata": {}, 422 | "outputs": [], 423 | "source": [ 424 | "#" 425 | ] 426 | }, 427 | { 428 | "cell_type": "markdown", 429 | "metadata": { 430 | "slideshow": { 431 | "slide_type": "slide" 432 | } 433 | }, 434 | "source": [ 435 | "#### Creating an empty dictionary\n", 436 | "\n", 437 | "- We often want to initialise a dictionary with no keys or values.\n", 438 | "\n", 439 | "- To do this call the function `dict()` or just `{}`:" 440 | ] 441 | }, 442 | { 443 | "cell_type": "code", 444 | "execution_count": null, 445 | "metadata": {}, 446 | "outputs": [], 447 | "source": [ 448 | "#" 449 | ] 450 | }, 451 | { 452 | "cell_type": "markdown", 453 | "metadata": { 454 | "slideshow": { 455 | "slide_type": "-" 456 | } 457 | }, 458 | "source": [ 459 | "- We can then progressively add entries to the dictionary:" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": null, 465 | "metadata": {}, 466 | "outputs": [], 467 | "source": [ 468 | "#" 469 | ] 470 | }, 471 | { 472 | "cell_type": "markdown", 473 | "metadata": {}, 474 | "source": [ 475 | "### The size of a collection\n", 476 | "\n", 477 | "- We can count the number of values in a collection using the `len` (length) function.\n", 478 | "\n", 479 | "- This can be used with any type of collection (list, dict, tuple, set etc.).\n" 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "execution_count": null, 485 | "metadata": {}, 486 | "outputs": [], 487 | "source": [ 488 | "#" 489 | ] 490 | }, 491 | { 492 | "cell_type": "markdown", 493 | "metadata": {}, 494 | "source": [ 495 | "#### Empty collections" 496 | ] 497 | }, 498 | { 499 | "cell_type": "markdown", 500 | "metadata": {}, 501 | "source": [ 502 | "- Empty collections have a size of zero:" 503 | ] 504 | }, 505 | { 506 | "cell_type": "code", 507 | "execution_count": null, 508 | "metadata": {}, 509 | "outputs": [], 510 | "source": [ 511 | "#" 512 | ] 513 | }, 514 | { 515 | "cell_type": "markdown", 516 | "metadata": {}, 517 | "source": [ 518 | "" 519 | ] 520 | }, 521 | { 522 | "cell_type": "markdown", 523 | "metadata": {}, 524 | "source": [ 525 | "## Loops" 526 | ] 527 | }, 528 | { 529 | "cell_type": "markdown", 530 | "metadata": {}, 531 | "source": [ 532 | "### The `for`-Loop" 533 | ] 534 | }, 535 | { 536 | "cell_type": "markdown", 537 | "metadata": {}, 538 | "source": [ 539 | "We have seen lists. Indexes are useful, but lists really shine when you start looping.\n", 540 | "\n", 541 | "Loops let you do something for each item in a list. They are kind of like if statements because they have an indented block.\n", 542 | "\n", 543 | "They look like this:\n", 544 | "\n", 545 | " for item in list:\n", 546 | " print(item) # Do any action per item in the list\n", 547 | "\n", 548 | "\"for\" and \"in\" are required. \"list\" can be any variable or literal which is like a list. \"item\" is the name you want to give each item of the list in the indented block as you iterate through. We call each step where item has a new value an iteration.\n", 549 | "\n", 550 | "Let's see it in action with our list" 551 | ] 552 | }, 553 | { 554 | "cell_type": "code", 555 | "execution_count": null, 556 | "metadata": {}, 557 | "outputs": [], 558 | "source": [ 559 | "#" 560 | ] 561 | }, 562 | { 563 | "cell_type": "markdown", 564 | "metadata": {}, 565 | "source": [ 566 | "Before continuing with loops let's become familiar with the idea and have some number generation fun.\n", 567 | "\n", 568 | "Number generation will become handy soon, so we don't have to key in the many numbers we want to check in terms of if they are prime or not. To do this, we will use a for statement. But let's first learn about range, a nifty little function that comes with python." 569 | ] 570 | }, 571 | { 572 | "cell_type": "markdown", 573 | "metadata": {}, 574 | "source": [ 575 | "At the simplest, range takes a number and creates a sequence of numbers from 0 to the input number. In this case, even though we can't see the numbers yet, we've created a sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.\n", 576 | "\n", 577 | "You might wonder why we don't get a 10 but stop at 9 even though we input 10. In Python and most other programming languages counting always starts from 0. Now, let's access the numbers we're generating." 578 | ] 579 | }, 580 | { 581 | "cell_type": "code", 582 | "execution_count": 8, 583 | "metadata": {}, 584 | "outputs": [ 585 | { 586 | "data": { 587 | "text/plain": [ 588 | "range(0, 10)" 589 | ] 590 | }, 591 | "execution_count": 8, 592 | "metadata": {}, 593 | "output_type": "execute_result" 594 | } 595 | ], 596 | "source": [ 597 | "range(10)" 598 | ] 599 | }, 600 | { 601 | "cell_type": "code", 602 | "execution_count": null, 603 | "metadata": {}, 604 | "outputs": [], 605 | "source": [ 606 | "#" 607 | ] 608 | }, 609 | { 610 | "cell_type": "markdown", 611 | "metadata": {}, 612 | "source": [ 613 | "Let's see what we did here. First with for we basically say that we want to do something for a number of items. Then with i we say that each time an item is picked, i will represent it. In other words, we can use i to access it inside the loop. With range(10) we create a sequence of numbers from 0 through 9. As you can see, the print(i) has leading spaces to it, which means that it's handled inside the loop. Note that i can be called anything you like." 614 | ] 615 | }, 616 | { 617 | "cell_type": "code", 618 | "execution_count": null, 619 | "metadata": {}, 620 | "outputs": [], 621 | "source": [ 622 | "#" 623 | ] 624 | }, 625 | { 626 | "cell_type": "markdown", 627 | "metadata": {}, 628 | "source": [ 629 | "range can be used to create any sequence of integers by defining the starting and ending positions of the sequence." 630 | ] 631 | }, 632 | { 633 | "cell_type": "code", 634 | "execution_count": null, 635 | "metadata": {}, 636 | "outputs": [], 637 | "source": [ 638 | "#" 639 | ] 640 | }, 641 | { 642 | "cell_type": "markdown", 643 | "metadata": {}, 644 | "source": [ 645 | "We can also add a 'step' argument, which gives us even more control over the range of numbers we want to create. For example with step argument 2, we will get every other number in a range:" 646 | ] 647 | }, 648 | { 649 | "cell_type": "code", 650 | "execution_count": null, 651 | "metadata": {}, 652 | "outputs": [], 653 | "source": [ 654 | "#" 655 | ] 656 | }, 657 | { 658 | "cell_type": "markdown", 659 | "metadata": {}, 660 | "source": [ 661 | "This way we only get the even numbers between 2 and 2. Let's try the same for odd numbers." 662 | ] 663 | }, 664 | { 665 | "cell_type": "code", 666 | "execution_count": null, 667 | "metadata": {}, 668 | "outputs": [], 669 | "source": [ 670 | "#" 671 | ] 672 | }, 673 | { 674 | "cell_type": "markdown", 675 | "metadata": {}, 676 | "source": [ 677 | "You've now learned a very useful and often applicable process automation; number generation. We've learn how to write any sequence of numbers, including just even or odd numbers.\n", 678 | "\n", 679 | "There are many other ways you can use to create numbers, including random numbers, but this will be more than enough for what we want to do. Let's move on to the next section and learn about loops." 680 | ] 681 | }, 682 | { 683 | "cell_type": "markdown", 684 | "metadata": {}, 685 | "source": [ 686 | "### Exercise: `for`-loops\n", 687 | "a) create a loop that returns the sequence \n", 688 | "$$x_n = n^2 + 1$$\n", 689 | "for $n=0,1,2,...,20$" 690 | ] 691 | }, 692 | { 693 | "cell_type": "code", 694 | "execution_count": 3, 695 | "metadata": {}, 696 | "outputs": [], 697 | "source": [ 698 | "#" 699 | ] 700 | }, 701 | { 702 | "cell_type": "markdown", 703 | "metadata": {}, 704 | "source": [ 705 | "b) create a loop that retuns the sequence\n", 706 | "$$x_n = 2x_{n-1} + 1$$\n", 707 | "for n = 0,1,2,...,20 and given $x_0 = 0$." 708 | ] 709 | }, 710 | { 711 | "cell_type": "code", 712 | "execution_count": 4, 713 | "metadata": {}, 714 | "outputs": [], 715 | "source": [ 716 | "#" 717 | ] 718 | }, 719 | { 720 | "cell_type": "markdown", 721 | "metadata": {}, 722 | "source": [ 723 | "c) repeat b), but store the result in a list (remember that you can add item `x` to list `list_of_x` via `list_of_x.append(x)`)" 724 | ] 725 | }, 726 | { 727 | "cell_type": "code", 728 | "execution_count": 2, 729 | "metadata": {}, 730 | "outputs": [], 731 | "source": [ 732 | "#" 733 | ] 734 | }, 735 | { 736 | "cell_type": "markdown", 737 | "metadata": {}, 738 | "source": [ 739 | "### Exercise: `lists`\n", 740 | "\n", 741 | "For the following exercises, take this list as an example:" 742 | ] 743 | }, 744 | { 745 | "cell_type": "code", 746 | "execution_count": 9, 747 | "metadata": {}, 748 | "outputs": [], 749 | "source": [ 750 | "elist = [1,5,1,6,5]" 751 | ] 752 | }, 753 | { 754 | "cell_type": "markdown", 755 | "metadata": {}, 756 | "source": [ 757 | " a) Write a Python program to sum all the items in the list. " 758 | ] 759 | }, 760 | { 761 | "cell_type": "code", 762 | "execution_count": 5, 763 | "metadata": {}, 764 | "outputs": [], 765 | "source": [ 766 | "#" 767 | ] 768 | }, 769 | { 770 | "cell_type": "markdown", 771 | "metadata": {}, 772 | "source": [ 773 | " b) Write a Python program to get the largest number from the list." 774 | ] 775 | }, 776 | { 777 | "cell_type": "code", 778 | "execution_count": 6, 779 | "metadata": {}, 780 | "outputs": [], 781 | "source": [ 782 | "#" 783 | ] 784 | }, 785 | { 786 | "cell_type": "markdown", 787 | "metadata": {}, 788 | "source": [ 789 | " c) Write a Python program to remove duplicates from the list (remember the `.append()` command)." 790 | ] 791 | }, 792 | { 793 | "cell_type": "code", 794 | "execution_count": 8, 795 | "metadata": {}, 796 | "outputs": [], 797 | "source": [ 798 | "#" 799 | ] 800 | }, 801 | { 802 | "cell_type": "markdown", 803 | "metadata": {}, 804 | "source": [ 805 | " d) write a Python program to sort a list." 806 | ] 807 | }, 808 | { 809 | "cell_type": "code", 810 | "execution_count": null, 811 | "metadata": {}, 812 | "outputs": [], 813 | "source": [ 814 | "#" 815 | ] 816 | }, 817 | { 818 | "cell_type": "markdown", 819 | "metadata": {}, 820 | "source": [ 821 | "### The `while`-Loop" 822 | ] 823 | }, 824 | { 825 | "cell_type": "markdown", 826 | "metadata": {}, 827 | "source": [ 828 | "Python, being used by professional programmers and scientists, among others, is capable of far more complicated tasks than adding numbers, playing with strings, and manipulating lists. For instance, we can write an initial sub-sequence of the Fibonacci series as follows:" 829 | ] 830 | }, 831 | { 832 | "cell_type": "code", 833 | "execution_count": 3, 834 | "metadata": { 835 | "scrolled": true 836 | }, 837 | "outputs": [ 838 | { 839 | "name": "stdout", 840 | "output_type": "stream", 841 | "text": [ 842 | "1\n", 843 | "2\n", 844 | "3\n", 845 | "5\n", 846 | "8\n", 847 | "13\n" 848 | ] 849 | } 850 | ], 851 | "source": [ 852 | "# Fibonacci series:\n", 853 | "# the sum of two elements defines the next.\n", 854 | "a, b = 0, 1\n", 855 | "\n", 856 | "while b < 10: \n", 857 | " c = a + b\n", 858 | " a = b\n", 859 | " b = c \n", 860 | " print(c)" 861 | ] 862 | }, 863 | { 864 | "cell_type": "markdown", 865 | "metadata": {}, 866 | "source": [ 867 | "This example introduces several new features of the Python language:\n", 868 | "\n", 869 | "- The first line contains a *multiple assignment*: the variables `a` and `b` simultaneously get the new values 0 and 1. On the last line this assignment is used again, demonstrating that the expressions on the right-hand side are all evaluated first before any of the assignments take place. The right-hand side expressions are evaluated from the left to the right.\n", 870 | "\n", 871 | "- The [`while`](https://docs.python.org/3.5/reference/compound_stmts.html#while) loop executes as long as the condition (here: `b < 10`) remains true. In Python, as in C, any non-zero integer value is true; zero is false. The condition may also be a string or list value, in fact any sequence; anything with a non-zero length is true, empty sequences are false. The test used in the example is a simple comparison. The standard comparison operators are written the same as in C: `<` (less than), `>` (greater than), `==` (equal to), `<=` (less than or equal to), `>=` (greater than or equal to) and `!=` (not equal to).\n", 872 | "\n", 873 | "- Every line in the *body* of the loop is indented: indentation is Python's way of grouping statements. At the interactive prompt, you have to type a tab or space(s) for each indented line. In practice, you typically write Python code in an editor, including a Jupyter notebook, that provides automatic indentation.\n" 874 | ] 875 | }, 876 | { 877 | "cell_type": "code", 878 | "execution_count": null, 879 | "metadata": {}, 880 | "outputs": [], 881 | "source": [ 882 | "#" 883 | ] 884 | }, 885 | { 886 | "cell_type": "markdown", 887 | "metadata": { 888 | "slideshow": { 889 | "slide_type": "slide" 890 | } 891 | }, 892 | "source": [ 893 | "#### Creating an empty dictionary (as above)\n", 894 | "\n", 895 | "- We often want to initialise a dictionary with no keys or values." 896 | ] 897 | }, 898 | { 899 | "cell_type": "code", 900 | "execution_count": null, 901 | "metadata": {}, 902 | "outputs": [], 903 | "source": [ 904 | "#" 905 | ] 906 | }, 907 | { 908 | "cell_type": "markdown", 909 | "metadata": { 910 | "slideshow": { 911 | "slide_type": "-" 912 | } 913 | }, 914 | "source": [ 915 | "- We can then progressively add entries to the dictionary, e.g. using iteration:" 916 | ] 917 | }, 918 | { 919 | "cell_type": "code", 920 | "execution_count": null, 921 | "metadata": {}, 922 | "outputs": [], 923 | "source": [ 924 | "#" 925 | ] 926 | }, 927 | { 928 | "cell_type": "markdown", 929 | "metadata": { 930 | "slideshow": { 931 | "slide_type": "slide" 932 | } 933 | }, 934 | "source": [ 935 | "#### Iterating over a dictionary\n", 936 | "\n", 937 | "- We can use a for loop with dictionaries, just as we can with other collections such as sets.\n", 938 | "- When we iterate over a dictionary, we iterate over the *keys*.\n", 939 | "- We can then perform some computation on each key inside the loop.\n", 940 | "- Typically we will also access the corresponding value." 941 | ] 942 | }, 943 | { 944 | "cell_type": "code", 945 | "execution_count": 6, 946 | "metadata": {}, 947 | "outputs": [], 948 | "source": [ 949 | "#" 950 | ] 951 | }, 952 | { 953 | "cell_type": "markdown", 954 | "metadata": {}, 955 | "source": [ 956 | "### Exercise: `while`-loops\n", 957 | "Repeat the exercises for the `for`-loop with a while loop:" 958 | ] 959 | }, 960 | { 961 | "cell_type": "markdown", 962 | "metadata": {}, 963 | "source": [ 964 | "a) create a loop that prints the sequence \n", 965 | "$$x_i = 2x_{i-1} + 1$$\n", 966 | "for $x_0 = 1$ as long as $x_i < 20$." 967 | ] 968 | }, 969 | { 970 | "cell_type": "code", 971 | "execution_count": 3, 972 | "metadata": {}, 973 | "outputs": [], 974 | "source": [ 975 | "#" 976 | ] 977 | }, 978 | { 979 | "cell_type": "markdown", 980 | "metadata": {}, 981 | "source": [ 982 | "b) create a loop that retuns the sequence\n", 983 | "$$x_n = x_{n-1}**2 + 1$$\n", 984 | "for n = 0,1,2,...,20 and given $x_0 = 0$." 985 | ] 986 | }, 987 | { 988 | "cell_type": "code", 989 | "execution_count": 4, 990 | "metadata": {}, 991 | "outputs": [], 992 | "source": [ 993 | "#" 994 | ] 995 | }, 996 | { 997 | "cell_type": "markdown", 998 | "metadata": {}, 999 | "source": [ 1000 | "c) repeat b), but store the result in a list (remember that you can add item `x` to list `list_of_x` via `list_of_x.append(x)`)" 1001 | ] 1002 | }, 1003 | { 1004 | "cell_type": "code", 1005 | "execution_count": 5, 1006 | "metadata": {}, 1007 | "outputs": [], 1008 | "source": [ 1009 | "#" 1010 | ] 1011 | }, 1012 | { 1013 | "cell_type": "markdown", 1014 | "metadata": {}, 1015 | "source": [ 1016 | "## Functions" 1017 | ] 1018 | }, 1019 | { 1020 | "cell_type": "markdown", 1021 | "metadata": {}, 1022 | "source": [ 1023 | "The last concept we're going to learn today is called a 'function'. Just like its name suggest, it is a utility that performs a function. For example, there is a function that allows us to identify the type of data (the same type we just went through in the previous examples). Actually we already used a function...the print() function for doing our \"hello world\" example in the beginning." 1024 | ] 1025 | }, 1026 | { 1027 | "cell_type": "code", 1028 | "execution_count": null, 1029 | "metadata": {}, 1030 | "outputs": [], 1031 | "source": [ 1032 | "#" 1033 | ] 1034 | }, 1035 | { 1036 | "cell_type": "markdown", 1037 | "metadata": {}, 1038 | "source": [ 1039 | "Calling functions is as easy as that, and there are a lot of them. This means that you can do a lot of different exciting and useful things very simply just by calling a function you want to use in a way we had just done. You can even make your own functions! " 1040 | ] 1041 | }, 1042 | { 1043 | "cell_type": "code", 1044 | "execution_count": null, 1045 | "metadata": {}, 1046 | "outputs": [], 1047 | "source": [ 1048 | "#" 1049 | ] 1050 | }, 1051 | { 1052 | "cell_type": "markdown", 1053 | "metadata": {}, 1054 | "source": [ 1055 | "Before trying it out, let's briefly overview what's happening here. First we declare our own function with def which just means we're going to define a function next. Then we have the name of our function my_first_function following it, and parenthesis with semicolon following it. That's it! Now let's see how to use our function." 1056 | ] 1057 | }, 1058 | { 1059 | "cell_type": "code", 1060 | "execution_count": null, 1061 | "metadata": {}, 1062 | "outputs": [], 1063 | "source": [ 1064 | "#" 1065 | ] 1066 | }, 1067 | { 1068 | "cell_type": "markdown", 1069 | "metadata": {}, 1070 | "source": [ 1071 | "As you might have guessed it, we use it just like we use print() and type() functions in the above examples. Also you might have found one difference, we are not making any input inside the parenthesis. This leads us to another basic building block of understanding computer programming; there are functions, and inputs to those functions. \n", 1072 | "\n", 1073 | "The function is what happens, a process of some sort, and the input is what the process happens to. Let's modify our function slightly to learn more about this." 1074 | ] 1075 | }, 1076 | { 1077 | "cell_type": "code", 1078 | "execution_count": null, 1079 | "metadata": {}, 1080 | "outputs": [], 1081 | "source": [ 1082 | "#" 1083 | ] 1084 | }, 1085 | { 1086 | "cell_type": "markdown", 1087 | "metadata": {}, 1088 | "source": [ 1089 | "As you can see, we have slightly changed the way the function is defined. Now instead of having empty parenthesis following the name of the function, we are declaring data in there. This way data becomes a 'parameter' also called 'argument', which is really just a fancy word for somethign we input to the function, so the function can process it. Let's try it first..." 1090 | ] 1091 | }, 1092 | { 1093 | "cell_type": "code", 1094 | "execution_count": null, 1095 | "metadata": {}, 1096 | "outputs": [], 1097 | "source": [ 1098 | "#" 1099 | ] 1100 | }, 1101 | { 1102 | "cell_type": "markdown", 1103 | "metadata": {}, 1104 | "source": [ 1105 | "Ah, our first error message. When something is wrong, Python is going to tell us exactly what is wrong. In this case, the error is telling us that even though our function is expecting to receive one argument (data), it is not getting it. Let's give our function an input and see what happens." 1106 | ] 1107 | }, 1108 | { 1109 | "cell_type": "code", 1110 | "execution_count": null, 1111 | "metadata": {}, 1112 | "outputs": [], 1113 | "source": [ 1114 | "#" 1115 | ] 1116 | }, 1117 | { 1118 | "cell_type": "markdown", 1119 | "metadata": {}, 1120 | "source": [ 1121 | "That's better. This makes the function quite a bit more powerful than the first version that just printed one thing every time. In fact, now we can print anything we like through this same function." 1122 | ] 1123 | }, 1124 | { 1125 | "cell_type": "code", 1126 | "execution_count": null, 1127 | "metadata": {}, 1128 | "outputs": [], 1129 | "source": [ 1130 | "#" 1131 | ] 1132 | }, 1133 | { 1134 | "cell_type": "markdown", 1135 | "metadata": {}, 1136 | "source": [ 1137 | "In a factory there is something that comes in (for example recycled newspapers), there is a process of some sort in between (for example turning newspaper in to pulp and then in to paper), and something that comes out (for example toilet paper). Algoritms are the part in the middle, where some process takes place in order to transform what comes in to what goes out.\n", 1138 | "\n", 1139 | "As the last thing, a function can have a `return` statement. This is what the function returns when executed:" 1140 | ] 1141 | }, 1142 | { 1143 | "cell_type": "code", 1144 | "execution_count": 1, 1145 | "metadata": {}, 1146 | "outputs": [], 1147 | "source": [ 1148 | "#" 1149 | ] 1150 | }, 1151 | { 1152 | "cell_type": "markdown", 1153 | "metadata": {}, 1154 | "source": [ 1155 | "### Functions: exercises\n", 1156 | "\n", 1157 | "a) create a function that takes $x$ and $y$ as an argument and prints $x+y$" 1158 | ] 1159 | }, 1160 | { 1161 | "cell_type": "code", 1162 | "execution_count": 1, 1163 | "metadata": {}, 1164 | "outputs": [], 1165 | "source": [ 1166 | "#" 1167 | ] 1168 | }, 1169 | { 1170 | "cell_type": "markdown", 1171 | "metadata": {}, 1172 | "source": [ 1173 | "b) make such function *return* $x+y$" 1174 | ] 1175 | }, 1176 | { 1177 | "cell_type": "code", 1178 | "execution_count": 2, 1179 | "metadata": {}, 1180 | "outputs": [], 1181 | "source": [ 1182 | "#" 1183 | ] 1184 | }, 1185 | { 1186 | "cell_type": "markdown", 1187 | "metadata": {}, 1188 | "source": [ 1189 | "c) create a function $y=f(x)$ that, for a given $x$, evaluates\n", 1190 | "$$ y = 5x^2 + 3x +2.$$\n", 1191 | "Evaluate $f(x)$ for $x=2$." 1192 | ] 1193 | }, 1194 | { 1195 | "cell_type": "code", 1196 | "execution_count": 1, 1197 | "metadata": {}, 1198 | "outputs": [], 1199 | "source": [ 1200 | "#" 1201 | ] 1202 | }, 1203 | { 1204 | "cell_type": "markdown", 1205 | "metadata": {}, 1206 | "source": [ 1207 | "d) extend the function $f$ from c) such that it also prints \"for x={your value of x}, y is {the result}\"" 1208 | ] 1209 | }, 1210 | { 1211 | "cell_type": "code", 1212 | "execution_count": 2, 1213 | "metadata": {}, 1214 | "outputs": [], 1215 | "source": [ 1216 | "#" 1217 | ] 1218 | }, 1219 | { 1220 | "cell_type": "markdown", 1221 | "metadata": {}, 1222 | "source": [ 1223 | "e) write a function that returns the `max` of two numbers" 1224 | ] 1225 | }, 1226 | { 1227 | "cell_type": "code", 1228 | "execution_count": 7, 1229 | "metadata": {}, 1230 | "outputs": [], 1231 | "source": [ 1232 | "#" 1233 | ] 1234 | }, 1235 | { 1236 | "cell_type": "markdown", 1237 | "metadata": {}, 1238 | "source": [ 1239 | "### A Life of an Algorithm" 1240 | ] 1241 | }, 1242 | { 1243 | "cell_type": "markdown", 1244 | "metadata": {}, 1245 | "source": [ 1246 | "Using what we have already learn, let's create a very simple algoritm. One that takes in two numbers, finds out if the first number (left number) we input is divisible by the second number (right number) we input. Algorithms are sometimes called 'algos' and we will be using that shorthand from now on." 1247 | ] 1248 | }, 1249 | { 1250 | "cell_type": "code", 1251 | "execution_count": null, 1252 | "metadata": {}, 1253 | "outputs": [], 1254 | "source": [ 1255 | "#" 1256 | ] 1257 | }, 1258 | { 1259 | "cell_type": "markdown", 1260 | "metadata": {}, 1261 | "source": [ 1262 | "Now that we have created our function, which contains an algoritm that finds out if the left number is divisible by the right, you might remember that we have to call it to get the output." 1263 | ] 1264 | }, 1265 | { 1266 | "cell_type": "code", 1267 | "execution_count": null, 1268 | "metadata": {}, 1269 | "outputs": [], 1270 | "source": [ 1271 | "#" 1272 | ] 1273 | }, 1274 | { 1275 | "cell_type": "markdown", 1276 | "metadata": {}, 1277 | "source": [ 1278 | "How come we did not get a result even we seemingly did everything right? Actually this is an expected behavior of the function, because we are not saying that we want to print something out. The computer has no way to know that we want to print something out. Instead, it silently performs the modulus operation. This is easy to fix by modifying our function slightly. " 1279 | ] 1280 | }, 1281 | { 1282 | "cell_type": "code", 1283 | "execution_count": null, 1284 | "metadata": {}, 1285 | "outputs": [], 1286 | "source": [ 1287 | "#" 1288 | ] 1289 | }, 1290 | { 1291 | "cell_type": "markdown", 1292 | "metadata": {}, 1293 | "source": [ 1294 | "Nice, now it works. Before we move on, let's look at a better way to achieve the same thing. Not always we want to print something, so it's better to use return at the end of the function. Return just means that there is some kind of thing we want to spit out of the function once its done its job. Unlike print which just prints something on the screen, return output can be used as an input for another function. Later you'll learn more about this." 1295 | ] 1296 | }, 1297 | { 1298 | "cell_type": "code", 1299 | "execution_count": null, 1300 | "metadata": {}, 1301 | "outputs": [], 1302 | "source": [ 1303 | "#" 1304 | ] 1305 | }, 1306 | { 1307 | "cell_type": "markdown", 1308 | "metadata": {}, 1309 | "source": [ 1310 | "As you see, this behaves exactly like we want it even though we don't use print anymore. Keep this in mind, it's one of the most commonly used features in Python programming. Let's run through a few examples of how we could use our function / and the algorithm inside it." 1311 | ] 1312 | }, 1313 | { 1314 | "cell_type": "code", 1315 | "execution_count": null, 1316 | "metadata": {}, 1317 | "outputs": [], 1318 | "source": [ 1319 | "#" 1320 | ] 1321 | }, 1322 | { 1323 | "cell_type": "markdown", 1324 | "metadata": {}, 1325 | "source": [ 1326 | "We could also input much larger numbers." 1327 | ] 1328 | }, 1329 | { 1330 | "cell_type": "code", 1331 | "execution_count": null, 1332 | "metadata": {}, 1333 | "outputs": [], 1334 | "source": [ 1335 | "#" 1336 | ] 1337 | }, 1338 | { 1339 | "cell_type": "markdown", 1340 | "metadata": {}, 1341 | "source": [ 1342 | "As you can see, regardless of what numbers we use as input, we always get exactly what is expected; the remant of the modulus. In other words, we always see what is remaining after we divide the left number with the right number. Let's apply some Boolean logic to the our algoritmh." 1343 | ] 1344 | }, 1345 | { 1346 | "cell_type": "code", 1347 | "execution_count": null, 1348 | "metadata": {}, 1349 | "outputs": [], 1350 | "source": [ 1351 | "#" 1352 | ] 1353 | }, 1354 | { 1355 | "cell_type": "markdown", 1356 | "metadata": {}, 1357 | "source": [ 1358 | "At this point, let's put some of the concepts we've learn together in to something just slightly more involving. " 1359 | ] 1360 | }, 1361 | { 1362 | "cell_type": "code", 1363 | "execution_count": 4, 1364 | "metadata": {}, 1365 | "outputs": [], 1366 | "source": [ 1367 | "#" 1368 | ] 1369 | }, 1370 | { 1371 | "cell_type": "markdown", 1372 | "metadata": {}, 1373 | "source": [ 1374 | "As you can see, we are now returning True when the remnant is 0 and False when it's not." 1375 | ] 1376 | }, 1377 | { 1378 | "cell_type": "code", 1379 | "execution_count": null, 1380 | "metadata": {}, 1381 | "outputs": [], 1382 | "source": [ 1383 | "#" 1384 | ] 1385 | }, 1386 | { 1387 | "cell_type": "markdown", 1388 | "metadata": {}, 1389 | "source": [ 1390 | "Before moving on the nex section, where we will cover generating numbers, let's consider a conditional statement with one more clause. " 1391 | ] 1392 | }, 1393 | { 1394 | "cell_type": "markdown", 1395 | "metadata": {}, 1396 | "source": [ 1397 | "Now we're going to add elif clause, which is just another way to say if between if and else. We will also introduce the idea of comments, where inside our function we use human language to explain what parts of code do. Anything that starts with # is consider a comment in Python. It means that part of the code will not be excecuted together with others. In other words, comments do not effect the workings or output of the function in anyway." 1398 | ] 1399 | }, 1400 | { 1401 | "cell_type": "code", 1402 | "execution_count": null, 1403 | "metadata": {}, 1404 | "outputs": [], 1405 | "source": [ 1406 | "#" 1407 | ] 1408 | }, 1409 | { 1410 | "cell_type": "markdown", 1411 | "metadata": {}, 1412 | "source": [ 1413 | "In the next section we will continue building on what we've learned here and you're going to build simple but far more powerful algoritms with your new skills." 1414 | ] 1415 | }, 1416 | { 1417 | "cell_type": "markdown", 1418 | "metadata": {}, 1419 | "source": [ 1420 | "### Putting it All Together: the holy quest for a prime number" 1421 | ] 1422 | }, 1423 | { 1424 | "cell_type": "markdown", 1425 | "metadata": {}, 1426 | "source": [ 1427 | "" 1428 | ] 1429 | }, 1430 | { 1431 | "cell_type": "markdown", 1432 | "metadata": {}, 1433 | "source": [ 1434 | "Let us imagine that we have the urge to **find out whether a number is a prime number**. We will persue this goal in this section.\n", 1435 | "\n", 1436 | "In this following section the length of our algoritm (function) is growing. But if you look carefully, you see that the changes we make are very small in fact. Moreover, we are only making changes that you've already learn so far. " 1437 | ] 1438 | }, 1439 | { 1440 | "cell_type": "code", 1441 | "execution_count": 5, 1442 | "metadata": {}, 1443 | "outputs": [], 1444 | "source": [ 1445 | "#" 1446 | ] 1447 | }, 1448 | { 1449 | "cell_type": "markdown", 1450 | "metadata": {}, 1451 | "source": [ 1452 | "So what we are doing now, is fixing the left number to be 20, and then checking it against every number in the range of 1 to 20 and see if it's divisible. This makes checking if a number is prime a whole lot simpler! Let's try an example where we know it's a prime nubmer, for example 13 (it's not divisisble by any other number than 1 and itself)." 1453 | ] 1454 | }, 1455 | { 1456 | "cell_type": "code", 1457 | "execution_count": null, 1458 | "metadata": {}, 1459 | "outputs": [], 1460 | "source": [ 1461 | "#" 1462 | ] 1463 | }, 1464 | { 1465 | "cell_type": "markdown", 1466 | "metadata": {}, 1467 | "source": [ 1468 | "Because we are starting our range from 1, one get one True in the beginning, so we have to start the range from 2 instead to get the right answer. As you can see, I changed the second line so that we scan until 12 which is the last number before 13. Let's put this inside a function as our fifth algo version and make the range start from 2 instead of 1." 1469 | ] 1470 | }, 1471 | { 1472 | "cell_type": "code", 1473 | "execution_count": null, 1474 | "metadata": {}, 1475 | "outputs": [], 1476 | "source": [ 1477 | "#" 1478 | ] 1479 | }, 1480 | { 1481 | "cell_type": "markdown", 1482 | "metadata": {}, 1483 | "source": [ 1484 | "Now things are starting to look good. We could now remove 'left' variable entirely as it comes as an argument from the function, and also instead of having to modify the function for the last number of the range, we also input that as an argument." 1485 | ] 1486 | }, 1487 | { 1488 | "cell_type": "code", 1489 | "execution_count": null, 1490 | "metadata": {}, 1491 | "outputs": [], 1492 | "source": [ 1493 | "#" 1494 | ] 1495 | }, 1496 | { 1497 | "cell_type": "markdown", 1498 | "metadata": {}, 1499 | "source": [ 1500 | "That's it, we're prime number checking now! :) Because the result is False for all, we know for sure that our input, in this case 7, is a prime. There is one more very small change we can do using the skill we've already learn to make a nice improvement to what we already have. Instead of requiring the user to input the end of the range, we can automatically compute it as it's always the last number before left. In other words, it's left - 1." 1501 | ] 1502 | }, 1503 | { 1504 | "cell_type": "code", 1505 | "execution_count": null, 1506 | "metadata": {}, 1507 | "outputs": [], 1508 | "source": [ 1509 | "#" 1510 | ] 1511 | }, 1512 | { 1513 | "cell_type": "markdown", 1514 | "metadata": {}, 1515 | "source": [ 1516 | "Things are working real nicely now. But clearly we will later have a problem with larger numbers with this current approach, as if we input 1,000, we will have 1,000 True or False values printed on the screen. To overcome this, we can make a small change to our latest version." 1517 | ] 1518 | }, 1519 | { 1520 | "cell_type": "code", 1521 | "execution_count": null, 1522 | "metadata": {}, 1523 | "outputs": [], 1524 | "source": [ 1525 | "#" 1526 | ] 1527 | }, 1528 | { 1529 | "cell_type": "markdown", 1530 | "metadata": {}, 1531 | "source": [ 1532 | "What we are doing, is first we declare a variable 'output' with starting value 0. Then instead of printing out True, we silently add 1 to output, and in case of False we add 0. Only in the end we print the value out, with the return statement that is outside of the for loop (note how it's indentation is equal to the for statement, meaning it will be processed only once the for loop has completed its job)." 1533 | ] 1534 | }, 1535 | { 1536 | "cell_type": "code", 1537 | "execution_count": null, 1538 | "metadata": {}, 1539 | "outputs": [], 1540 | "source": [ 1541 | "#" 1542 | ] 1543 | }, 1544 | { 1545 | "cell_type": "markdown", 1546 | "metadata": {}, 1547 | "source": [ 1548 | "Nice. Now we can key in much larger numbers, and just get one output." 1549 | ] 1550 | }, 1551 | { 1552 | "cell_type": "code", 1553 | "execution_count": null, 1554 | "metadata": {}, 1555 | "outputs": [], 1556 | "source": [ 1557 | "#" 1558 | ] 1559 | }, 1560 | { 1561 | "cell_type": "markdown", 1562 | "metadata": {}, 1563 | "source": [ 1564 | "Before wrapping up, let's simplify our code slightly and instead of outputting a number, output a True or False statement. True for 'it's a prime' and False for 'it's not a prime'." 1565 | ] 1566 | }, 1567 | { 1568 | "cell_type": "code", 1569 | "execution_count": null, 1570 | "metadata": {}, 1571 | "outputs": [], 1572 | "source": [ 1573 | "#" 1574 | ] 1575 | }, 1576 | { 1577 | "cell_type": "markdown", 1578 | "metadata": {}, 1579 | "source": [ 1580 | "Note how we removed the else statements entirely. Because we are doing nothing in the cases where the left number is not divisible by the right number. In other words, whenever the product of the modulus operation is not zero, we do nothing. Therefore it's enough to just have the if statement without the else. This is quite common. " 1581 | ] 1582 | }, 1583 | { 1584 | "cell_type": "markdown", 1585 | "metadata": {}, 1586 | "source": [ 1587 | "### Scope of functions" 1588 | ] 1589 | }, 1590 | { 1591 | "cell_type": "markdown", 1592 | "metadata": {}, 1593 | "source": [ 1594 | "Python follows the LEGB Rule (after https://www.amazon.com/dp/0596513984/):\n", 1595 | "\n", 1596 | "* L, Local: Names assigned in any way within a function (def or lambda)), and not declared global in that function.\n", 1597 | "* E, Enclosing function locals: Name in the local scope of any and all enclosing functions (def or lambda), from inner to outer.\n", 1598 | "* G, Global (module): Names assigned at the top-level of a module file, or declared global in a def within the file.\n", 1599 | "* B, Built-in (Python): Names preassigned in the built-in names module : open, range, SyntaxError,..." 1600 | ] 1601 | }, 1602 | { 1603 | "cell_type": "code", 1604 | "execution_count": null, 1605 | "metadata": {}, 1606 | "outputs": [], 1607 | "source": [ 1608 | "#" 1609 | ] 1610 | }, 1611 | { 1612 | "cell_type": "markdown", 1613 | "metadata": {}, 1614 | "source": [ 1615 | "See [scope_resolution_legb_rule.ipynb](scope_resolution_legb_rule.ipynb) for some additional readings on scope." 1616 | ] 1617 | }, 1618 | { 1619 | "cell_type": "markdown", 1620 | "metadata": {}, 1621 | "source": [ 1622 | "### Default arguments" 1623 | ] 1624 | }, 1625 | { 1626 | "cell_type": "code", 1627 | "execution_count": null, 1628 | "metadata": {}, 1629 | "outputs": [], 1630 | "source": [ 1631 | "#" 1632 | ] 1633 | } 1634 | ], 1635 | "metadata": { 1636 | "kernelspec": { 1637 | "display_name": "Python 3", 1638 | "language": "python", 1639 | "name": "python3" 1640 | }, 1641 | "language_info": { 1642 | "codemirror_mode": { 1643 | "name": "ipython", 1644 | "version": 3 1645 | }, 1646 | "file_extension": ".py", 1647 | "mimetype": "text/x-python", 1648 | "name": "python", 1649 | "nbconvert_exporter": "python", 1650 | "pygments_lexer": "ipython3", 1651 | "version": "3.9.4" 1652 | } 1653 | }, 1654 | "nbformat": 4, 1655 | "nbformat_minor": 2 1656 | } 1657 | -------------------------------------------------------------------------------- /lecture3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Lecture 3: Scientific programming" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Content\n", 15 | " \n", 16 | "* Summary of lecture 2\n", 17 | "* `numpy`: \n", 18 | " * the `array`\n", 19 | " * indexing\n", 20 | " * some standard operations/methods\n", 21 | " * linear algebra `<3`\n", 22 | "* plotting with `matplotlib`\n", 23 | "* `scipy`:\n", 24 | " * distributions\n", 25 | " * Nonlinear solvers\n", 26 | " * Nonlinear optimization" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## Summary of lecture 2\n", 34 | "\n", 35 | "* Collections: `tuple` & `dict`\n", 36 | "* Mutabillity\n", 37 | "* Loops: `for`\n", 38 | "& `while` loop\n", 39 | "* Functions" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 1, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "t = (2,3)" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 3, 54 | "metadata": {}, 55 | "outputs": [ 56 | { 57 | "data": { 58 | "text/plain": [ 59 | "(2, 3)" 60 | ] 61 | }, 62 | "execution_count": 3, 63 | "metadata": {}, 64 | "output_type": "execute_result" 65 | } 66 | ], 67 | "source": [ 68 | "t" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 5, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "data": { 78 | "text/plain": [ 79 | "tuple" 80 | ] 81 | }, 82 | "execution_count": 5, 83 | "metadata": {}, 84 | "output_type": "execute_result" 85 | } 86 | ], 87 | "source": [ 88 | "type(t)" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 7, 94 | "metadata": {}, 95 | "outputs": [ 96 | { 97 | "ename": "TypeError", 98 | "evalue": "'tuple' object does not support item assignment", 99 | "output_type": "error", 100 | "traceback": [ 101 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 102 | "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", 103 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 104 | "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" 105 | ] 106 | } 107 | ], 108 | "source": [ 109 | "t[0] = 1" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 8, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "l = list(t)" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 9, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "l[1] = 1" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": { 133 | "colab_type": "text", 134 | "id": "3cfrOV4dL9hW" 135 | }, 136 | "source": [ 137 | "## Numpy" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": { 143 | "colab_type": "text", 144 | "id": "fY12nHhyL9hX" 145 | }, 146 | "source": [ 147 | "Numpy is the core library for scientific computing in Python. It provides a high-performance multidimensional array object, and tools for working with these arrays. If you are already familiar with MATLAB, you might find this [tutorial](http://wiki.scipy.org/NumPy_for_Matlab_Users) useful to get started with Numpy." 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "The `numpy` package (module) is used in almost all numerical computation using Python. It is a package that provide high-performance vector, matrix and higher-dimensional data structures for Python. It is implemented in C and Fortran so when calculations are vectorized (formulated with vectors and matrices), performance is very good. \n", 155 | "\n", 156 | "To use `numpy` you need to import the module, using for example:" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 29, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "import numpy as np" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "In the `numpy` package the terminology used for vectors, matrices and higher-dimensional data sets is *array*. \n", 173 | "\n" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "## Creating `numpy` arrays" 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": {}, 186 | "source": [ 187 | "There are a number of ways to initialize new numpy arrays, for example from\n", 188 | "\n", 189 | "* a Python list or tuples\n", 190 | "* using functions that are dedicated to generating numpy arrays, such as `arange`, `linspace`, etc.\n", 191 | "* reading data from files" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "### From lists/tuples" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "For example, to create new vector and matrix arrays from Python lists we can use the `numpy.array` function." 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 1, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [ 214 | "#" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "metadata": {}, 220 | "source": [ 221 | "The `v` and `M` objects are both of the type `ndarray` that the `numpy` module provides." 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 5, 227 | "metadata": {}, 228 | "outputs": [ 229 | { 230 | "data": { 231 | "text/plain": [ 232 | "(numpy.ndarray, numpy.ndarray)" 233 | ] 234 | }, 235 | "execution_count": 5, 236 | "metadata": {}, 237 | "output_type": "execute_result" 238 | } 239 | ], 240 | "source": [ 241 | "#" 242 | ] 243 | }, 244 | { 245 | "cell_type": "markdown", 246 | "metadata": {}, 247 | "source": [ 248 | "The difference between the `v` and `M` arrays is only their shapes. We can get information about the shape of an array by using the `ndarray.shape` property." 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": 3, 254 | "metadata": {}, 255 | "outputs": [], 256 | "source": [ 257 | "#" 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "metadata": {}, 263 | "source": [ 264 | "Equivalently, we could use the function `numpy.shape`" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": 5, 270 | "metadata": {}, 271 | "outputs": [], 272 | "source": [ 273 | "#" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "So far the `numpy.ndarray` looks awefully much like a Python list (or nested list). Why not simply use Python lists for computations instead of creating a new array type? \n", 281 | "\n", 282 | "There are several reasons:\n", 283 | "\n", 284 | "* Python lists are very general. They can contain any kind of object. They are dynamically typed. They do not support mathematical functions such as matrix and dot multiplications, etc. Implementing such functions for Python lists would not be very efficient because of the dynamic typing.\n", 285 | "* Numpy arrays are **statically typed** and **homogeneous**. The type of the elements is determined when the array is created.\n", 286 | "* Numpy arrays are memory efficient.\n", 287 | "* Because of the static typing, fast implementation of mathematical functions such as multiplication and addition of `numpy` arrays can be implemented in a compiled language (C and Fortran is used).\n", 288 | "\n", 289 | "Using the `dtype` (data type) property of an `ndarray`, we can see what type the data of an array has:" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 6, 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [ 298 | "#" 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "metadata": {}, 304 | "source": [ 305 | "We get an error if we try to assign a value of the wrong type to an element in a numpy array:" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": 7, 311 | "metadata": {}, 312 | "outputs": [], 313 | "source": [ 314 | "#" 315 | ] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "metadata": {}, 320 | "source": [ 321 | "### Using array-generating functions" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "metadata": {}, 327 | "source": [ 328 | "For larger arrays it is inpractical to initialize the data manually, using explicit python lists. Instead we can use one of the many functions in `numpy` that generate arrays of different forms. Some of the more common are:" 329 | ] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "metadata": {}, 334 | "source": [ 335 | "#### `np.arange`" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": 8, 341 | "metadata": {}, 342 | "outputs": [], 343 | "source": [ 344 | "#" 345 | ] 346 | }, 347 | { 348 | "cell_type": "markdown", 349 | "metadata": {}, 350 | "source": [ 351 | "#### `np.linspace`" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 9, 357 | "metadata": {}, 358 | "outputs": [], 359 | "source": [ 360 | "#" 361 | ] 362 | }, 363 | { 364 | "cell_type": "markdown", 365 | "metadata": {}, 366 | "source": [ 367 | "#### random data" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": 10, 373 | "metadata": {}, 374 | "outputs": [], 375 | "source": [ 376 | "#" 377 | ] 378 | }, 379 | { 380 | "cell_type": "markdown", 381 | "metadata": {}, 382 | "source": [ 383 | "#### zeros and ones" 384 | ] 385 | }, 386 | { 387 | "cell_type": "code", 388 | "execution_count": 26, 389 | "metadata": {}, 390 | "outputs": [ 391 | { 392 | "data": { 393 | "text/plain": [ 394 | "array([[ 0., 0., 0.],\n", 395 | " [ 0., 0., 0.],\n", 396 | " [ 0., 0., 0.]])" 397 | ] 398 | }, 399 | "execution_count": 26, 400 | "metadata": {}, 401 | "output_type": "execute_result" 402 | } 403 | ], 404 | "source": [ 405 | "#" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "#### Creating arrays: Exercises" 413 | ] 414 | }, 415 | { 416 | "cell_type": "markdown", 417 | "metadata": {}, 418 | "source": [ 419 | "a) Create an array with only even numbers of lengh 10." 420 | ] 421 | }, 422 | { 423 | "cell_type": "code", 424 | "execution_count": 9, 425 | "metadata": {}, 426 | "outputs": [], 427 | "source": [ 428 | "#" 429 | ] 430 | }, 431 | { 432 | "cell_type": "markdown", 433 | "metadata": {}, 434 | "source": [ 435 | "b) Create an array of `[0,10,...,100]`." 436 | ] 437 | }, 438 | { 439 | "cell_type": "code", 440 | "execution_count": null, 441 | "metadata": {}, 442 | "outputs": [], 443 | "source": [ 444 | "#" 445 | ] 446 | }, 447 | { 448 | "cell_type": "markdown", 449 | "metadata": {}, 450 | "source": [ 451 | "## Manipulating arrays" 452 | ] 453 | }, 454 | { 455 | "cell_type": "markdown", 456 | "metadata": {}, 457 | "source": [ 458 | "### Indexing" 459 | ] 460 | }, 461 | { 462 | "cell_type": "markdown", 463 | "metadata": {}, 464 | "source": [ 465 | "We can index elements in an array using square brackets and indices:" 466 | ] 467 | }, 468 | { 469 | "cell_type": "code", 470 | "execution_count": 11, 471 | "metadata": {}, 472 | "outputs": [], 473 | "source": [ 474 | "#" 475 | ] 476 | }, 477 | { 478 | "cell_type": "markdown", 479 | "metadata": {}, 480 | "source": [ 481 | "If we omit an index of a multidimensional array it returns the whole row (or, in general, a N-1 dimensional array) " 482 | ] 483 | }, 484 | { 485 | "cell_type": "code", 486 | "execution_count": 12, 487 | "metadata": {}, 488 | "outputs": [], 489 | "source": [ 490 | "#" 491 | ] 492 | }, 493 | { 494 | "cell_type": "markdown", 495 | "metadata": {}, 496 | "source": [ 497 | "The same thing can be achieved with using `:` instead of an index: " 498 | ] 499 | }, 500 | { 501 | "cell_type": "code", 502 | "execution_count": 13, 503 | "metadata": {}, 504 | "outputs": [], 505 | "source": [ 506 | "#" 507 | ] 508 | }, 509 | { 510 | "cell_type": "markdown", 511 | "metadata": {}, 512 | "source": [ 513 | "We can assign new values to elements in an array using indexing:" 514 | ] 515 | }, 516 | { 517 | "cell_type": "code", 518 | "execution_count": 14, 519 | "metadata": {}, 520 | "outputs": [], 521 | "source": [ 522 | "#" 523 | ] 524 | }, 525 | { 526 | "cell_type": "markdown", 527 | "metadata": {}, 528 | "source": [ 529 | "### Index slicing" 530 | ] 531 | }, 532 | { 533 | "cell_type": "markdown", 534 | "metadata": {}, 535 | "source": [ 536 | "Index slicing is the technical name for the syntax `M[lower:upper:step]` to extract part of an array:" 537 | ] 538 | }, 539 | { 540 | "cell_type": "code", 541 | "execution_count": 15, 542 | "metadata": {}, 543 | "outputs": [], 544 | "source": [ 545 | "#" 546 | ] 547 | }, 548 | { 549 | "cell_type": "markdown", 550 | "metadata": {}, 551 | "source": [ 552 | "Array slices are *mutable*: if they are assigned a new value the original array from which the slice was extracted is modified:" 553 | ] 554 | }, 555 | { 556 | "cell_type": "code", 557 | "execution_count": 16, 558 | "metadata": {}, 559 | "outputs": [], 560 | "source": [ 561 | "#" 562 | ] 563 | }, 564 | { 565 | "cell_type": "markdown", 566 | "metadata": {}, 567 | "source": [ 568 | "We can omit any of the three parameters in `M[lower:upper:step]`:" 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "execution_count": 17, 574 | "metadata": {}, 575 | "outputs": [], 576 | "source": [ 577 | "#" 578 | ] 579 | }, 580 | { 581 | "cell_type": "markdown", 582 | "metadata": {}, 583 | "source": [ 584 | "Negative indices counts from the end of the array (positive index from the begining):" 585 | ] 586 | }, 587 | { 588 | "cell_type": "code", 589 | "execution_count": 18, 590 | "metadata": {}, 591 | "outputs": [], 592 | "source": [ 593 | "#" 594 | ] 595 | }, 596 | { 597 | "cell_type": "markdown", 598 | "metadata": {}, 599 | "source": [ 600 | "Index slicing works exactly the same way for multidimensional arrays:" 601 | ] 602 | }, 603 | { 604 | "cell_type": "code", 605 | "execution_count": 19, 606 | "metadata": {}, 607 | "outputs": [], 608 | "source": [ 609 | "#" 610 | ] 611 | }, 612 | { 613 | "cell_type": "markdown", 614 | "metadata": {}, 615 | "source": [ 616 | "### Fancy indexing" 617 | ] 618 | }, 619 | { 620 | "cell_type": "markdown", 621 | "metadata": {}, 622 | "source": [ 623 | "Fancy indexing is the name for when an array or list is used in-place of an index: " 624 | ] 625 | }, 626 | { 627 | "cell_type": "code", 628 | "execution_count": 20, 629 | "metadata": {}, 630 | "outputs": [], 631 | "source": [ 632 | "#" 633 | ] 634 | }, 635 | { 636 | "cell_type": "markdown", 637 | "metadata": {}, 638 | "source": [ 639 | "We can also use index masks: If the index mask is an Numpy array of data type `bool`, then an element is selected (True) or not (False) depending on the value of the index mask at the position of each element: " 640 | ] 641 | }, 642 | { 643 | "cell_type": "code", 644 | "execution_count": 21, 645 | "metadata": {}, 646 | "outputs": [], 647 | "source": [ 648 | "#" 649 | ] 650 | }, 651 | { 652 | "cell_type": "markdown", 653 | "metadata": {}, 654 | "source": [ 655 | "This feature is very useful to conditionally select elements from an array, using for example comparison operators:" 656 | ] 657 | }, 658 | { 659 | "cell_type": "code", 660 | "execution_count": 22, 661 | "metadata": {}, 662 | "outputs": [], 663 | "source": [ 664 | "#" 665 | ] 666 | }, 667 | { 668 | "cell_type": "markdown", 669 | "metadata": {}, 670 | "source": [ 671 | "#### Exercises: indexing\n", 672 | "a) create an array `a` from 0 to 9" 673 | ] 674 | }, 675 | { 676 | "cell_type": "code", 677 | "execution_count": 11, 678 | "metadata": {}, 679 | "outputs": [], 680 | "source": [ 681 | "#" 682 | ] 683 | }, 684 | { 685 | "cell_type": "markdown", 686 | "metadata": {}, 687 | "source": [ 688 | "b) get only the first 3 values of `a`" 689 | ] 690 | }, 691 | { 692 | "cell_type": "code", 693 | "execution_count": 12, 694 | "metadata": {}, 695 | "outputs": [], 696 | "source": [ 697 | "#" 698 | ] 699 | }, 700 | { 701 | "cell_type": "markdown", 702 | "metadata": {}, 703 | "source": [ 704 | "c) create a random array `b` of size 9 with $b_i \\sim N(0,1)$." 705 | ] 706 | }, 707 | { 708 | "cell_type": "code", 709 | "execution_count": null, 710 | "metadata": {}, 711 | "outputs": [], 712 | "source": [ 713 | "#" 714 | ] 715 | }, 716 | { 717 | "cell_type": "markdown", 718 | "metadata": {}, 719 | "source": [ 720 | "d) get all the values of `b` that are larger than one." 721 | ] 722 | }, 723 | { 724 | "cell_type": "code", 725 | "execution_count": 13, 726 | "metadata": {}, 727 | "outputs": [], 728 | "source": [ 729 | "#" 730 | ] 731 | }, 732 | { 733 | "cell_type": "markdown", 734 | "metadata": {}, 735 | "source": [ 736 | "## Some standard operations" 737 | ] 738 | }, 739 | { 740 | "cell_type": "markdown", 741 | "metadata": {}, 742 | "source": [ 743 | "Lets us create some very precious data that we want to learn more about." 744 | ] 745 | }, 746 | { 747 | "cell_type": "code", 748 | "execution_count": 23, 749 | "metadata": {}, 750 | "outputs": [], 751 | "source": [ 752 | "#" 753 | ] 754 | }, 755 | { 756 | "cell_type": "markdown", 757 | "metadata": {}, 758 | "source": [ 759 | "#### sum" 760 | ] 761 | }, 762 | { 763 | "cell_type": "code", 764 | "execution_count": 24, 765 | "metadata": {}, 766 | "outputs": [], 767 | "source": [ 768 | "#" 769 | ] 770 | }, 771 | { 772 | "cell_type": "markdown", 773 | "metadata": {}, 774 | "source": [ 775 | "#### mean" 776 | ] 777 | }, 778 | { 779 | "cell_type": "code", 780 | "execution_count": 25, 781 | "metadata": {}, 782 | "outputs": [], 783 | "source": [ 784 | "#" 785 | ] 786 | }, 787 | { 788 | "cell_type": "markdown", 789 | "metadata": {}, 790 | "source": [ 791 | "#### standard deviations and variance" 792 | ] 793 | }, 794 | { 795 | "cell_type": "code", 796 | "execution_count": 26, 797 | "metadata": {}, 798 | "outputs": [], 799 | "source": [ 800 | "#" 801 | ] 802 | }, 803 | { 804 | "cell_type": "markdown", 805 | "metadata": {}, 806 | "source": [ 807 | "#### min and max" 808 | ] 809 | }, 810 | { 811 | "cell_type": "code", 812 | "execution_count": 27, 813 | "metadata": {}, 814 | "outputs": [], 815 | "source": [ 816 | "#" 817 | ] 818 | }, 819 | { 820 | "cell_type": "markdown", 821 | "metadata": {}, 822 | "source": [ 823 | "Many other functions and methods in the `array` and `matrix` classes accept the same (optional) `axis` keyword argument." 824 | ] 825 | }, 826 | { 827 | "cell_type": "code", 828 | "execution_count": 28, 829 | "metadata": {}, 830 | "outputs": [], 831 | "source": [ 832 | "#" 833 | ] 834 | }, 835 | { 836 | "cell_type": "markdown", 837 | "metadata": {}, 838 | "source": [ 839 | "### Reshaping and stacking arrays" 840 | ] 841 | }, 842 | { 843 | "cell_type": "markdown", 844 | "metadata": {}, 845 | "source": [ 846 | "The shape of an Numpy array can be modified without copying the underlaying data, which makes it a fast operation even for large arrays. Let us create `A`." 847 | ] 848 | }, 849 | { 850 | "cell_type": "code", 851 | "execution_count": 30, 852 | "metadata": {}, 853 | "outputs": [], 854 | "source": [ 855 | "#" 856 | ] 857 | }, 858 | { 859 | "cell_type": "markdown", 860 | "metadata": {}, 861 | "source": [ 862 | "#### Standard operations: exercises\n", 863 | "a) create a random array `b` of size 9 with $b_i \\sim N(0,1)$." 864 | ] 865 | }, 866 | { 867 | "cell_type": "code", 868 | "execution_count": 14, 869 | "metadata": {}, 870 | "outputs": [], 871 | "source": [ 872 | "#" 873 | ] 874 | }, 875 | { 876 | "cell_type": "markdown", 877 | "metadata": {}, 878 | "source": [ 879 | "b) get the lowest and highest value of `b`." 880 | ] 881 | }, 882 | { 883 | "cell_type": "code", 884 | "execution_count": 15, 885 | "metadata": {}, 886 | "outputs": [], 887 | "source": [ 888 | "#" 889 | ] 890 | }, 891 | { 892 | "cell_type": "markdown", 893 | "metadata": {}, 894 | "source": [ 895 | "c) create an array `c` of size 9 and stack it horizontally on `b`. Call the result `d`." 896 | ] 897 | }, 898 | { 899 | "cell_type": "code", 900 | "execution_count": 17, 901 | "metadata": {}, 902 | "outputs": [], 903 | "source": [ 904 | "#" 905 | ] 906 | }, 907 | { 908 | "cell_type": "markdown", 909 | "metadata": {}, 910 | "source": [ 911 | "d) get the mean of `d`." 912 | ] 913 | }, 914 | { 915 | "cell_type": "code", 916 | "execution_count": 18, 917 | "metadata": {}, 918 | "outputs": [], 919 | "source": [ 920 | "#" 921 | ] 922 | }, 923 | { 924 | "cell_type": "markdown", 925 | "metadata": {}, 926 | "source": [ 927 | "## Copy and \"deep copy\"" 928 | ] 929 | }, 930 | { 931 | "cell_type": "markdown", 932 | "metadata": {}, 933 | "source": [ 934 | "To achieve high performance, assignments in Python usually do not copy the underlaying objects. This is important for example when objects are passed between functions, to avoid an excessive amount of memory copying when it is not necessary (technical term: pass by reference). " 935 | ] 936 | }, 937 | { 938 | "cell_type": "code", 939 | "execution_count": 31, 940 | "metadata": {}, 941 | "outputs": [], 942 | "source": [ 943 | "#" 944 | ] 945 | }, 946 | { 947 | "cell_type": "markdown", 948 | "metadata": {}, 949 | "source": [ 950 | "If we want to avoid this behavior, so that when we get a new completely independent object `B` copied from `A`, then we need to do a so-called \"deep copy\" using the function `copy`:" 951 | ] 952 | }, 953 | { 954 | "cell_type": "code", 955 | "execution_count": 32, 956 | "metadata": {}, 957 | "outputs": [], 958 | "source": [ 959 | "#" 960 | ] 961 | }, 962 | { 963 | "cell_type": "markdown", 964 | "metadata": {}, 965 | "source": [ 966 | "## Linear algebra" 967 | ] 968 | }, 969 | { 970 | "cell_type": "markdown", 971 | "metadata": {}, 972 | "source": [ 973 | "Vectorizing code is the key to writing efficient numerical calculation with Python/Numpy. That means that as much as possible of a program should be formulated in terms of matrix and vector operations, like matrix-matrix multiplication." 974 | ] 975 | }, 976 | { 977 | "cell_type": "markdown", 978 | "metadata": {}, 979 | "source": [ 980 | "### Scalar-array operations" 981 | ] 982 | }, 983 | { 984 | "cell_type": "markdown", 985 | "metadata": {}, 986 | "source": [ 987 | "We can use the usual arithmetic operators to multiply, add, subtract, and divide arrays with scalar numbers." 988 | ] 989 | }, 990 | { 991 | "cell_type": "code", 992 | "execution_count": 81, 993 | "metadata": {}, 994 | "outputs": [], 995 | "source": [ 996 | "#" 997 | ] 998 | }, 999 | { 1000 | "cell_type": "markdown", 1001 | "metadata": {}, 1002 | "source": [ 1003 | "### Element-wise array-array operations" 1004 | ] 1005 | }, 1006 | { 1007 | "cell_type": "markdown", 1008 | "metadata": {}, 1009 | "source": [ 1010 | "When we add, subtract, multiply and divide arrays with each other, the default behaviour is **element-wise** operations:" 1011 | ] 1012 | }, 1013 | { 1014 | "cell_type": "code", 1015 | "execution_count": 33, 1016 | "metadata": {}, 1017 | "outputs": [], 1018 | "source": [ 1019 | "#" 1020 | ] 1021 | }, 1022 | { 1023 | "cell_type": "markdown", 1024 | "metadata": {}, 1025 | "source": [ 1026 | "If we multiply arrays with compatible shapes, we get an element-wise multiplication of each row:" 1027 | ] 1028 | }, 1029 | { 1030 | "cell_type": "code", 1031 | "execution_count": 34, 1032 | "metadata": {}, 1033 | "outputs": [], 1034 | "source": [ 1035 | "#" 1036 | ] 1037 | }, 1038 | { 1039 | "cell_type": "markdown", 1040 | "metadata": {}, 1041 | "source": [ 1042 | "What about matrix mutiplication? There are two ways. We can either use the `dot` function, which applies a matrix-matrix, matrix-vector, or inner vector multiplication to its two arguments: " 1043 | ] 1044 | }, 1045 | { 1046 | "cell_type": "code", 1047 | "execution_count": 35, 1048 | "metadata": {}, 1049 | "outputs": [], 1050 | "source": [ 1051 | "#" 1052 | ] 1053 | }, 1054 | { 1055 | "cell_type": "markdown", 1056 | "metadata": {}, 1057 | "source": [ 1058 | "See also the related functions: `inner`, `outer`, `cross`, `kron`, `tensordot`. Try for example `help(kron)`." 1059 | ] 1060 | }, 1061 | { 1062 | "cell_type": "code", 1063 | "execution_count": 36, 1064 | "metadata": { 1065 | "colab": { 1066 | "base_uri": "https://localhost:8080/", 1067 | "height": 52 1068 | }, 1069 | "colab_type": "code", 1070 | "id": "I3FnmoSeL9iu", 1071 | "outputId": "46f4575a-2e5e-4347-a34e-0cc5bd280110" 1072 | }, 1073 | "outputs": [], 1074 | "source": [ 1075 | "#" 1076 | ] 1077 | }, 1078 | { 1079 | "cell_type": "markdown", 1080 | "metadata": { 1081 | "colab_type": "text", 1082 | "id": "vmxPbrHASVeA" 1083 | }, 1084 | "source": [ 1085 | "You can also use the `@` operator which is equivalent to numpy's `dot` operator." 1086 | ] 1087 | }, 1088 | { 1089 | "cell_type": "code", 1090 | "execution_count": 37, 1091 | "metadata": { 1092 | "colab": { 1093 | "base_uri": "https://localhost:8080/", 1094 | "height": 69 1095 | }, 1096 | "colab_type": "code", 1097 | "id": "zvUODeTxL9iw", 1098 | "outputId": "4093fc76-094f-4453-a421-a212b5226968" 1099 | }, 1100 | "outputs": [], 1101 | "source": [ 1102 | "#" 1103 | ] 1104 | }, 1105 | { 1106 | "cell_type": "markdown", 1107 | "metadata": { 1108 | "colab_type": "text", 1109 | "id": "FbE-1If_L9i0" 1110 | }, 1111 | "source": [ 1112 | "Numpy provides many useful functions for performing computations on arrays; one of the most useful is `sum`:" 1113 | ] 1114 | }, 1115 | { 1116 | "cell_type": "code", 1117 | "execution_count": 38, 1118 | "metadata": { 1119 | "colab": { 1120 | "base_uri": "https://localhost:8080/", 1121 | "height": 69 1122 | }, 1123 | "colab_type": "code", 1124 | "id": "DZUdZvPrL9i0", 1125 | "outputId": "99cad470-d692-4b25-91c9-a57aa25f4c6e" 1126 | }, 1127 | "outputs": [], 1128 | "source": [ 1129 | "#" 1130 | ] 1131 | }, 1132 | { 1133 | "cell_type": "markdown", 1134 | "metadata": { 1135 | "colab_type": "text", 1136 | "id": "ahdVW4iUL9i3" 1137 | }, 1138 | "source": [ 1139 | "You can find the full list of mathematical functions provided by numpy in the [documentation](http://docs.scipy.org/doc/numpy/reference/routines.math.html).\n", 1140 | "\n", 1141 | "Apart from computing mathematical functions using arrays, we frequently need to reshape or otherwise manipulate data in arrays. The simplest example of this type of operation is transposing a matrix; to transpose a matrix, simply use the T attribute of an array object:" 1142 | ] 1143 | }, 1144 | { 1145 | "cell_type": "code", 1146 | "execution_count": 39, 1147 | "metadata": { 1148 | "colab": { 1149 | "base_uri": "https://localhost:8080/", 1150 | "height": 104 1151 | }, 1152 | "colab_type": "code", 1153 | "id": "mkk03eNIL9i4", 1154 | "outputId": "499eec5a-55b7-473a-d4aa-9d023d63885a" 1155 | }, 1156 | "outputs": [], 1157 | "source": [ 1158 | "#" 1159 | ] 1160 | }, 1161 | { 1162 | "cell_type": "markdown", 1163 | "metadata": {}, 1164 | "source": [ 1165 | "#### `np.diag`" 1166 | ] 1167 | }, 1168 | { 1169 | "cell_type": "code", 1170 | "execution_count": 40, 1171 | "metadata": {}, 1172 | "outputs": [], 1173 | "source": [ 1174 | "#" 1175 | ] 1176 | }, 1177 | { 1178 | "cell_type": "markdown", 1179 | "metadata": {}, 1180 | "source": [ 1181 | "Let us experiment with matrices\n", 1182 | "\n", 1183 | "$$ \n", 1184 | " A = \\begin{bmatrix} 2 & -1 \\\\ 3 & 0 \\end{bmatrix} \n", 1185 | " \\quad \\text{and} \\quad\n", 1186 | " b = \\begin{bmatrix} 1 \\\\ 1 \\end{bmatrix}\n", 1187 | "$$" 1188 | ] 1189 | }, 1190 | { 1191 | "cell_type": "code", 1192 | "execution_count": 319, 1193 | "metadata": {}, 1194 | "outputs": [], 1195 | "source": [ 1196 | "A = [[2, -1],\n", 1197 | " [3, 0]]\n", 1198 | "A = np.array(A) # Convert from list to NumPy array\n", 1199 | "b = np.ones((2, 1)) # Shape is 2 x 1" 1200 | ] 1201 | }, 1202 | { 1203 | "cell_type": "markdown", 1204 | "metadata": {}, 1205 | "source": [ 1206 | "#### Inverse" 1207 | ] 1208 | }, 1209 | { 1210 | "cell_type": "code", 1211 | "execution_count": 42, 1212 | "metadata": {}, 1213 | "outputs": [], 1214 | "source": [ 1215 | "#" 1216 | ] 1217 | }, 1218 | { 1219 | "cell_type": "markdown", 1220 | "metadata": {}, 1221 | "source": [ 1222 | "#### Determinant" 1223 | ] 1224 | }, 1225 | { 1226 | "cell_type": "code", 1227 | "execution_count": 19, 1228 | "metadata": {}, 1229 | "outputs": [], 1230 | "source": [ 1231 | "#" 1232 | ] 1233 | }, 1234 | { 1235 | "cell_type": "code", 1236 | "execution_count": 43, 1237 | "metadata": {}, 1238 | "outputs": [], 1239 | "source": [ 1240 | "#" 1241 | ] 1242 | }, 1243 | { 1244 | "cell_type": "markdown", 1245 | "metadata": {}, 1246 | "source": [ 1247 | "#### Eigenvalues and eigenvectors" 1248 | ] 1249 | }, 1250 | { 1251 | "cell_type": "code", 1252 | "execution_count": 41, 1253 | "metadata": {}, 1254 | "outputs": [], 1255 | "source": [ 1256 | "#" 1257 | ] 1258 | }, 1259 | { 1260 | "cell_type": "markdown", 1261 | "metadata": {}, 1262 | "source": [ 1263 | "Let us solve (for $x$) the problem \n", 1264 | "$$A x = b$$" 1265 | ] 1266 | }, 1267 | { 1268 | "cell_type": "code", 1269 | "execution_count": 44, 1270 | "metadata": {}, 1271 | "outputs": [], 1272 | "source": [ 1273 | "#" 1274 | ] 1275 | }, 1276 | { 1277 | "cell_type": "markdown", 1278 | "metadata": {}, 1279 | "source": [ 1280 | "#### Linear Algebra: Exercises\n", 1281 | "a) solve the linear equation system \n", 1282 | "$$x + y = 0\\\\\n", 1283 | "2x - y = 1$$" 1284 | ] 1285 | }, 1286 | { 1287 | "cell_type": "markdown", 1288 | "metadata": {}, 1289 | "source": [ 1290 | "b) check if the linear equation system \n", 1291 | "$$1x + 0y = 1\\\\\n", 1292 | "-2x + 0y = 3$$\n", 1293 | "has a solution." 1294 | ] 1295 | }, 1296 | { 1297 | "cell_type": "code", 1298 | "execution_count": 20, 1299 | "metadata": {}, 1300 | "outputs": [], 1301 | "source": [ 1302 | "#" 1303 | ] 1304 | } 1305 | ], 1306 | "metadata": { 1307 | "kernelspec": { 1308 | "display_name": "Python 3", 1309 | "language": "python", 1310 | "name": "python3" 1311 | }, 1312 | "language_info": { 1313 | "codemirror_mode": { 1314 | "name": "ipython", 1315 | "version": 3 1316 | }, 1317 | "file_extension": ".py", 1318 | "mimetype": "text/x-python", 1319 | "name": "python", 1320 | "nbconvert_exporter": "python", 1321 | "pygments_lexer": "ipython3", 1322 | "version": "3.9.4" 1323 | } 1324 | }, 1325 | "nbformat": 4, 1326 | "nbformat_minor": 2 1327 | } 1328 | --------------------------------------------------------------------------------