├── .gitignore ├── 0. 10 minutes to Pandas.ipynb ├── 01. Dates & Times.ipynb ├── 02. Time Zone Handling.ipynb ├── 03. Reading and working with time-based data.ipynb ├── 04. Resampling.ipynb ├── 05. Moving Window Functions.ipynb ├── 07. Self Correlation.ipynb ├── 08. Trend&Seasonality.ipynb ├── 09a. AR + MA processes.ipynb ├── 09b. Forecasting.ipynb ├── 09c. Spectral Analysis.ipynb ├── 10. Clustering & Classification.ipynb ├── data ├── 50words_TEST.csv ├── AirPassengers.csv ├── Earthquakes.csv ├── ao_monthly.txt └── yahoo_stock.csv ├── readtime.py └── snippets ├── 6_acf_def.py ├── 6_acf_over_time.py ├── 6_ad_test_desc.py ├── 6_multi_vs_add.pu ├── 6_multi_vs_add.py ├── 6_pd.py ├── 6_var.py ├── 7_diff2.py ├── 7ma.py ├── ambig.py ├── changerep.py ├── confirm.py ├── custom_rolling.py ├── custom_rolling2.py ├── daterange.py ├── dtwdistance.py ├── euclidedistance.py ├── offset_aliases.py ├── prac1.py ├── prac2.py ├── prac3.py ├── prac4.py ├── prac5.py ├── prac6.py ├── prac7.py ├── prac8.py ├── readtime.py ├── resampling_end.py ├── shift_future.py ├── startend.py ├── try1.py └── window_funcs_try.py /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints/ 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # dotenv 85 | .env 86 | 87 | # virtualenv 88 | .venv 89 | venv/ 90 | ENV/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ -------------------------------------------------------------------------------- /0. 10 minutes to Pandas.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "%matplotlib inline \n", 12 | "import matplotlib.pylab\n", 13 | "import pandas as pd\n", 14 | "import numpy as np" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# Pandas data frames make data easy to see, references, and manipulate\n", 22 | "\n", 23 | "very much copied from\n", 24 | "http://pandas.pydata.org/pandas-docs/stable/10min.html" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "### You can create a data frame with a dictionary of lists" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": { 38 | "collapsed": false 39 | }, 40 | "outputs": [ 41 | { 42 | "data": { 43 | "text/html": [ 44 | "
\n", 45 | "\n", 58 | "\n", 59 | " \n", 60 | " \n", 61 | " \n", 62 | " \n", 63 | " \n", 64 | " \n", 65 | " \n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | "
agephone
Melanie17555-1212
Bob17555-1234
Vidhya18555-1111
Ming18555-2222
\n", 89 | "
" 90 | ], 91 | "text/plain": [ 92 | "\n", 93 | " age phone\n", 94 | "Melanie 17 555-1212\n", 95 | "Bob 17 555-1234\n", 96 | "Vidhya 18 555-1111\n", 97 | "Ming 18 555-2222" 98 | ] 99 | }, 100 | "metadata": {}, 101 | "output_type": "display_data" 102 | } 103 | ], 104 | "source": [ 105 | "students = pd.DataFrame({'phone': ['555-1212', '555-1234', '555-1111', '555-2222'], 'age':[17, 17, 18, 18]}, index = ['Melanie', 'Bob', 'Vidhya', 'Ming'])\n", 106 | "students" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 3, 112 | "metadata": { 113 | "collapsed": false 114 | }, 115 | "outputs": [ 116 | { 117 | "data": { 118 | "text/plain": [ 119 | "Index(['Melanie', 'Bob', 'Vidhya', 'Ming'], dtype='object')" 120 | ] 121 | }, 122 | "execution_count": 3, 123 | "metadata": {}, 124 | "output_type": "execute_result" 125 | } 126 | ], 127 | "source": [ 128 | "students.index" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "### You can also create a data frame with a numpy array and some column names" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 4, 141 | "metadata": { 142 | "collapsed": false 143 | }, 144 | "outputs": [ 145 | { 146 | "data": { 147 | "text/html": [ 148 | "
\n", 149 | "\n", 162 | "\n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | "
ABCD
Jenny-0.293866-0.011147-0.8110720.777268
Frank-0.5831240.829852-1.1617500.070804
Wenfei0.100019-0.8381100.8209740.016191
Arun1.700588-0.3682540.938544-0.084392
Mary-1.2016941.401805-0.3755430.682025
Ivan0.8879980.700713-1.589795-0.143907
\n", 217 | "
" 218 | ], 219 | "text/plain": [ 220 | "\n", 221 | " A B C D\n", 222 | "Jenny -0.293866 -0.011147 -0.811072 0.777268\n", 223 | "Frank -0.583124 0.829852 -1.161750 0.070804\n", 224 | "Wenfei 0.100019 -0.838110 0.820974 0.016191\n", 225 | "Arun 1.700588 -0.368254 0.938544 -0.084392\n", 226 | "Mary -1.201694 1.401805 -0.375543 0.682025\n", 227 | "Ivan 0.887998 0.700713 -1.589795 -0.143907" 228 | ] 229 | }, 230 | "metadata": {}, 231 | "output_type": "display_data" 232 | } 233 | ], 234 | "source": [ 235 | "df = pd.DataFrame(np.random.randn(6,4), index=['Jenny', 'Frank', 'Wenfei', 'Arun', 'Mary', 'Ivan'], columns=list('ABCD'))\n", 236 | "df" 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": {}, 242 | "source": [ 243 | "### There are also Series, which gets you all the functionality of a data frame when you have a 1-dimensional set of data with an index" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 5, 249 | "metadata": { 250 | "collapsed": false 251 | }, 252 | "outputs": [], 253 | "source": [ 254 | "s = pd.Series([1,3,5,np.nan,6,8])" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": 6, 260 | "metadata": { 261 | "collapsed": false 262 | }, 263 | "outputs": [ 264 | { 265 | "data": { 266 | "text/plain": [ 267 | "\n", 268 | "a 1.0\n", 269 | "b 3.0\n", 270 | "c 5.0\n", 271 | "d NaN\n", 272 | "e 6.0\n", 273 | "f 8.0\n", 274 | "dtype: float64" 275 | ] 276 | }, 277 | "metadata": {}, 278 | "output_type": "display_data" 279 | } 280 | ], 281 | "source": [ 282 | "s.index = ['a', 'b', 'c', 'd', 'e', 'f']\n", 283 | "s" 284 | ] 285 | }, 286 | { 287 | "cell_type": "code", 288 | "execution_count": 7, 289 | "metadata": { 290 | "collapsed": false 291 | }, 292 | "outputs": [ 293 | { 294 | "data": { 295 | "text/plain": [ 296 | "\n", 297 | "a False\n", 298 | "b False\n", 299 | "c False\n", 300 | "d True\n", 301 | "e False\n", 302 | "f False\n", 303 | "dtype: bool" 304 | ] 305 | }, 306 | "metadata": {}, 307 | "output_type": "display_data" 308 | } 309 | ], 310 | "source": [ 311 | "s.isnull()" 312 | ] 313 | }, 314 | { 315 | "cell_type": "markdown", 316 | "metadata": {}, 317 | "source": [ 318 | "### Dataframes and series play nice with plotting" 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": 8, 324 | "metadata": { 325 | "collapsed": false 326 | }, 327 | "outputs": [ 328 | { 329 | "data": { 330 | "text/plain": [ 331 | "" 332 | ] 333 | }, 334 | "execution_count": 8, 335 | "metadata": {}, 336 | "output_type": "execute_result" 337 | }, 338 | { 339 | "data": { 340 | "image/png": "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\nB/wZRGQZjj0AAAAASUVORK5CYII=\n", 341 | "text/plain": [ 342 | "" 343 | ] 344 | }, 345 | "metadata": {}, 346 | "output_type": "display_data" 347 | } 348 | ], 349 | "source": [ 350 | "s.plot()" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": 9, 356 | "metadata": { 357 | "collapsed": false 358 | }, 359 | "outputs": [ 360 | { 361 | "data": { 362 | "text/plain": [ 363 | "" 364 | ] 365 | }, 366 | "execution_count": 9, 367 | "metadata": {}, 368 | "output_type": "execute_result" 369 | }, 370 | { 371 | "data": { 372 | "image/png": "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\nL0XdpRegAAAAAElFTkSuQmCC\n", 373 | "text/plain": [ 374 | "" 375 | ] 376 | }, 377 | "metadata": {}, 378 | "output_type": "display_data" 379 | } 380 | ], 381 | "source": [ 382 | "df.plot()" 383 | ] 384 | }, 385 | { 386 | "cell_type": "markdown", 387 | "metadata": {}, 388 | "source": [ 389 | "### Once you have a data frame, it's easy to see portions of your data that match what you want (same goes for series)" 390 | ] 391 | }, 392 | { 393 | "cell_type": "code", 394 | "execution_count": 10, 395 | "metadata": { 396 | "collapsed": false 397 | }, 398 | "outputs": [ 399 | { 400 | "data": { 401 | "text/plain": [ 402 | "\n", 403 | "d NaN\n", 404 | "e 6.0\n", 405 | "f 8.0\n", 406 | "dtype: float64" 407 | ] 408 | }, 409 | "metadata": {}, 410 | "output_type": "display_data" 411 | } 412 | ], 413 | "source": [ 414 | "s[s.index > 'c']" 415 | ] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": 11, 420 | "metadata": { 421 | "collapsed": false 422 | }, 423 | "outputs": [ 424 | { 425 | "data": { 426 | "text/plain": [ 427 | "\n", 428 | "a 1.0\n", 429 | "b 3.0\n", 430 | "c 5.0\n", 431 | "e 6.0\n", 432 | "f 8.0\n", 433 | "dtype: float64" 434 | ] 435 | }, 436 | "metadata": {}, 437 | "output_type": "display_data" 438 | } 439 | ], 440 | "source": [ 441 | "s[s.isnull() == False]" 442 | ] 443 | }, 444 | { 445 | "cell_type": "code", 446 | "execution_count": 12, 447 | "metadata": { 448 | "collapsed": false 449 | }, 450 | "outputs": [ 451 | { 452 | "data": { 453 | "text/plain": [ 454 | "\n", 455 | "Melanie 17\n", 456 | "Bob 17\n", 457 | "Vidhya 18\n", 458 | "Ming 18\n", 459 | "Name: age, dtype: int64" 460 | ] 461 | }, 462 | "metadata": {}, 463 | "output_type": "display_data" 464 | } 465 | ], 466 | "source": [ 467 | "students['age']" 468 | ] 469 | }, 470 | { 471 | "cell_type": "code", 472 | "execution_count": 13, 473 | "metadata": { 474 | "collapsed": false 475 | }, 476 | "outputs": [ 477 | { 478 | "data": { 479 | "text/plain": [ 480 | "\n", 481 | "Melanie 17\n", 482 | "Bob 17\n", 483 | "Vidhya 18\n", 484 | "Ming 18\n", 485 | "Name: age, dtype: int64" 486 | ] 487 | }, 488 | "metadata": {}, 489 | "output_type": "display_data" 490 | } 491 | ], 492 | "source": [ 493 | "students.age" 494 | ] 495 | }, 496 | { 497 | "cell_type": "code", 498 | "execution_count": 14, 499 | "metadata": { 500 | "collapsed": false 501 | }, 502 | "outputs": [ 503 | { 504 | "data": { 505 | "text/plain": [ 506 | "\n", 507 | "age 17\n", 508 | "phone 555-1212\n", 509 | "Name: Melanie, dtype: object" 510 | ] 511 | }, 512 | "metadata": {}, 513 | "output_type": "display_data" 514 | } 515 | ], 516 | "source": [ 517 | "# 'selection by label'\n", 518 | "students.loc['Melanie']" 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": 15, 524 | "metadata": { 525 | "collapsed": false 526 | }, 527 | "outputs": [ 528 | { 529 | "data": { 530 | "text/plain": [ 531 | "\n", 532 | "age 17\n", 533 | "grades NaN\n", 534 | "Name: Melanie, dtype: object" 535 | ] 536 | }, 537 | "metadata": {}, 538 | "output_type": "display_data" 539 | } 540 | ], 541 | "source": [ 542 | "students.loc['Melanie', ['age', 'grades']]" 543 | ] 544 | }, 545 | { 546 | "cell_type": "code", 547 | "execution_count": 16, 548 | "metadata": { 549 | "collapsed": false 550 | }, 551 | "outputs": [ 552 | { 553 | "data": { 554 | "text/plain": [ 555 | "\n", 556 | "age 17\n", 557 | "phone 555-1234\n", 558 | "Name: Bob, dtype: object" 559 | ] 560 | }, 561 | "metadata": {}, 562 | "output_type": "display_data" 563 | } 564 | ], 565 | "source": [ 566 | "# select by position\n", 567 | "students.iloc[1, :]" 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "execution_count": 17, 573 | "metadata": { 574 | "collapsed": false 575 | }, 576 | "outputs": [ 577 | { 578 | "data": { 579 | "text/html": [ 580 | "
\n", 581 | "\n", 594 | "\n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | "
agephone
Vidhya18555-1111
Ming18555-2222
\n", 615 | "
" 616 | ], 617 | "text/plain": [ 618 | "\n", 619 | " age phone\n", 620 | "Vidhya 18 555-1111\n", 621 | "Ming 18 555-2222" 622 | ] 623 | }, 624 | "metadata": {}, 625 | "output_type": "display_data" 626 | } 627 | ], 628 | "source": [ 629 | "students[students['age'] > 17]" 630 | ] 631 | }, 632 | { 633 | "cell_type": "markdown", 634 | "metadata": {}, 635 | "source": [ 636 | "### It's also easy to summarize your data" 637 | ] 638 | }, 639 | { 640 | "cell_type": "code", 641 | "execution_count": 19, 642 | "metadata": { 643 | "collapsed": false 644 | }, 645 | "outputs": [ 646 | { 647 | "data": { 648 | "text/plain": [ 649 | "17.5" 650 | ] 651 | }, 652 | "execution_count": 19, 653 | "metadata": {}, 654 | "output_type": "execute_result" 655 | } 656 | ], 657 | "source": [ 658 | "students.age.mean()" 659 | ] 660 | }, 661 | { 662 | "cell_type": "code", 663 | "execution_count": 20, 664 | "metadata": { 665 | "collapsed": false 666 | }, 667 | "outputs": [ 668 | { 669 | "data": { 670 | "text/plain": [ 671 | "18" 672 | ] 673 | }, 674 | "execution_count": 20, 675 | "metadata": {}, 676 | "output_type": "execute_result" 677 | } 678 | ], 679 | "source": [ 680 | "students.age.max()" 681 | ] 682 | }, 683 | { 684 | "cell_type": "code", 685 | "execution_count": 21, 686 | "metadata": { 687 | "collapsed": false 688 | }, 689 | "outputs": [ 690 | { 691 | "data": { 692 | "text/plain": [ 693 | "17" 694 | ] 695 | }, 696 | "execution_count": 21, 697 | "metadata": {}, 698 | "output_type": "execute_result" 699 | } 700 | ], 701 | "source": [ 702 | "students.age.min()" 703 | ] 704 | }, 705 | { 706 | "cell_type": "markdown", 707 | "metadata": {}, 708 | "source": [ 709 | "### You can add information to an existing data frame" 710 | ] 711 | }, 712 | { 713 | "cell_type": "code", 714 | "execution_count": 22, 715 | "metadata": { 716 | "collapsed": false 717 | }, 718 | "outputs": [], 719 | "source": [ 720 | "students['grade'] = [100, 97, 80, 85]" 721 | ] 722 | }, 723 | { 724 | "cell_type": "code", 725 | "execution_count": 23, 726 | "metadata": { 727 | "collapsed": false 728 | }, 729 | "outputs": [ 730 | { 731 | "data": { 732 | "text/html": [ 733 | "
\n", 734 | "\n", 747 | "\n", 748 | " \n", 749 | " \n", 750 | " \n", 751 | " \n", 752 | " \n", 753 | " \n", 754 | " \n", 755 | " \n", 756 | " \n", 757 | " \n", 758 | " \n", 759 | " \n", 760 | " \n", 761 | " \n", 762 | " \n", 763 | " \n", 764 | "
agephonegrade
Melanie17555-1212100
\n", 765 | "
" 766 | ], 767 | "text/plain": [ 768 | "\n", 769 | " age phone grade\n", 770 | "Melanie 17 555-1212 100" 771 | ] 772 | }, 773 | "metadata": {}, 774 | "output_type": "display_data" 775 | } 776 | ], 777 | "source": [ 778 | "students[students['grade'] == students['grade'].max()]" 779 | ] 780 | }, 781 | { 782 | "cell_type": "markdown", 783 | "metadata": {}, 784 | "source": [ 785 | "### You can also easily aggregate information" 786 | ] 787 | }, 788 | { 789 | "cell_type": "code", 790 | "execution_count": 24, 791 | "metadata": { 792 | "collapsed": false 793 | }, 794 | "outputs": [ 795 | { 796 | "data": { 797 | "text/plain": [ 798 | "\n", 799 | "age\n", 800 | "17 98.5\n", 801 | "18 82.5\n", 802 | "Name: grade, dtype: float64" 803 | ] 804 | }, 805 | "metadata": {}, 806 | "output_type": "display_data" 807 | } 808 | ], 809 | "source": [ 810 | "students.groupby('age').grade.mean()" 811 | ] 812 | }, 813 | { 814 | "cell_type": "markdown", 815 | "metadata": {}, 816 | "source": [ 817 | "### You can even create categories to aggregate with on-the-fly" 818 | ] 819 | }, 820 | { 821 | "cell_type": "code", 822 | "execution_count": 25, 823 | "metadata": { 824 | "collapsed": false 825 | }, 826 | "outputs": [ 827 | { 828 | "data": { 829 | "text/plain": [ 830 | "\n", 831 | "1 18.0\n", 832 | "2 17.5\n", 833 | "3 17.0\n", 834 | "Name: age, dtype: float64" 835 | ] 836 | }, 837 | "metadata": {}, 838 | "output_type": "display_data" 839 | } 840 | ], 841 | "source": [ 842 | "bins = np.linspace(70, 100, 3)\n", 843 | "bins\n", 844 | "students.groupby(np.digitize(students.grade, bins)).age.mean()" 845 | ] 846 | }, 847 | { 848 | "cell_type": "markdown", 849 | "metadata": {}, 850 | "source": [ 851 | "### Finally applying functions is also quite straight-forward" 852 | ] 853 | }, 854 | { 855 | "cell_type": "code", 856 | "execution_count": 26, 857 | "metadata": { 858 | "collapsed": true 859 | }, 860 | "outputs": [], 861 | "source": [ 862 | "# First let's see what a lambda function looks like / does\n", 863 | "f = lambda x: x + 1" 864 | ] 865 | }, 866 | { 867 | "cell_type": "code", 868 | "execution_count": 27, 869 | "metadata": { 870 | "collapsed": false 871 | }, 872 | "outputs": [ 873 | { 874 | "data": { 875 | "text/plain": [ 876 | "5" 877 | ] 878 | }, 879 | "execution_count": 27, 880 | "metadata": {}, 881 | "output_type": "execute_result" 882 | } 883 | ], 884 | "source": [ 885 | "f(4)" 886 | ] 887 | }, 888 | { 889 | "cell_type": "code", 890 | "execution_count": 28, 891 | "metadata": { 892 | "collapsed": false 893 | }, 894 | "outputs": [ 895 | { 896 | "data": { 897 | "text/plain": [ 898 | "\n", 899 | "Melanie 18\n", 900 | "Bob 18\n", 901 | "Vidhya 19\n", 902 | "Ming 19\n", 903 | "Name: age, dtype: int64" 904 | ] 905 | }, 906 | "metadata": {}, 907 | "output_type": "display_data" 908 | } 909 | ], 910 | "source": [ 911 | "students.age.apply(lambda age: age + 1)" 912 | ] 913 | }, 914 | { 915 | "cell_type": "markdown", 916 | "metadata": {}, 917 | "source": [ 918 | "### Let's take a look at some built methods we might want to apply" 919 | ] 920 | }, 921 | { 922 | "cell_type": "code", 923 | "execution_count": null, 924 | "metadata": { 925 | "collapsed": false 926 | }, 927 | "outputs": [], 928 | "source": [ 929 | "students.age.mean()" 930 | ] 931 | }, 932 | { 933 | "cell_type": "code", 934 | "execution_count": null, 935 | "metadata": { 936 | "collapsed": false 937 | }, 938 | "outputs": [], 939 | "source": [ 940 | "students.age.count()" 941 | ] 942 | }, 943 | { 944 | "cell_type": "code", 945 | "execution_count": null, 946 | "metadata": { 947 | "collapsed": false 948 | }, 949 | "outputs": [], 950 | "source": [ 951 | "students.corr()" 952 | ] 953 | }, 954 | { 955 | "cell_type": "code", 956 | "execution_count": null, 957 | "metadata": { 958 | "collapsed": false 959 | }, 960 | "outputs": [], 961 | "source": [ 962 | "students.cummax()" 963 | ] 964 | } 965 | ], 966 | "metadata": { 967 | "anaconda-cloud": {}, 968 | "kernelspec": { 969 | "display_name": "Python [Root]", 970 | "language": "python", 971 | "name": "Python [Root]" 972 | }, 973 | "language_info": { 974 | "codemirror_mode": { 975 | "name": "ipython", 976 | "version": 3 977 | }, 978 | "file_extension": ".py", 979 | "mimetype": "text/x-python", 980 | "name": "python", 981 | "nbconvert_exporter": "python", 982 | "pygments_lexer": "ipython3", 983 | "version": "3.5.2" 984 | }, 985 | "widgets": { 986 | "state": {}, 987 | "version": "1.1.1" 988 | } 989 | }, 990 | "nbformat": 4, 991 | "nbformat_minor": 0 992 | } 993 | -------------------------------------------------------------------------------- /01. Dates & Times.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import pandas as pd\n", 12 | "import numpy as np" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "# Generate series of times" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": null, 25 | "metadata": { 26 | "collapsed": false 27 | }, 28 | "outputs": [], 29 | "source": [ 30 | "# specify with start date & number of periods\n", 31 | "rng = pd.date_range('2016 Jul 15 10:15', periods = 10, freq = 'M')\n", 32 | "rng" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": { 38 | "collapsed": true 39 | }, 40 | "source": [ 41 | "### let's explore some of the other options for date_range\n", 42 | "http://pandas.pydata.org/pandas-docs/stable/generated/pandas.date_range.html\n", 43 | "\n", 44 | "In particular, let's take a look at 'normalize' and 'end'" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": { 51 | "collapsed": false 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "rng = pd.date_range('2016 Jul 15', periods = 10, freq = 'M')\n", 56 | "rng" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "# Timestamps" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": { 70 | "collapsed": false 71 | }, 72 | "outputs": [], 73 | "source": [ 74 | "# add increasing detail\n", 75 | "pd.Timestamp('2016-07-10')" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "metadata": { 82 | "collapsed": false 83 | }, 84 | "outputs": [], 85 | "source": [ 86 | "pd.Timestamp('2016-07-10 10:15:15')" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "### How much detail can you add?" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": { 100 | "collapsed": false 101 | }, 102 | "outputs": [], 103 | "source": [ 104 | "pd.Timestamp('2016-07-10 10:15:15.05675757')" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "### Which of these formats DON'T work?\n", 112 | "'2016 Jul 1', '7/1/2016', '1/7/2016', 'July 1, 2016', '2016-07-01'" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": { 119 | "collapsed": true 120 | }, 121 | "outputs": [], 122 | "source": [] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "### What are some properties of time stamps? \n", 129 | "Hint: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#time-date-components" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": { 136 | "collapsed": true 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "t = pd.Timestamp('2016-07-10 10:15:15')" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "collapsed": false 148 | }, 149 | "outputs": [], 150 | "source": [ 151 | "t.quarter" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "metadata": { 158 | "collapsed": false 159 | }, 160 | "outputs": [], 161 | "source": [ 162 | "t = pd.Timestamp('2016-07-10 8 pm')\n", 163 | "t" 164 | ] 165 | }, 166 | { 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "### How are time stamps lacking?" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": { 177 | "collapsed": true 178 | }, 179 | "outputs": [], 180 | "source": [] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "# Time offsets" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": { 193 | "collapsed": false 194 | }, 195 | "outputs": [], 196 | "source": [ 197 | "pd.Timedelta('1 day 1us')" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": null, 203 | "metadata": { 204 | "collapsed": false 205 | }, 206 | "outputs": [], 207 | "source": [ 208 | "pd.Timestamp('2016-07-01 8:00') + pd.Timedelta('1.5 hours')" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": { 215 | "collapsed": false 216 | }, 217 | "outputs": [], 218 | "source": [ 219 | "pd.Timedelta('15ns') #bug? what kind of bug?" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "metadata": { 226 | "collapsed": false 227 | }, 228 | "outputs": [], 229 | "source": [ 230 | "rng + pd.Timedelta('1day')" 231 | ] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": {}, 236 | "source": [ 237 | "# Time spans" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": null, 243 | "metadata": { 244 | "collapsed": false 245 | }, 246 | "outputs": [], 247 | "source": [ 248 | "p = pd.Period('7/2016')\n", 249 | "t = pd.Timestamp('7/21/2016')\n", 250 | "p.start_time < t and p.end_time > t" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": null, 256 | "metadata": { 257 | "collapsed": false 258 | }, 259 | "outputs": [], 260 | "source": [ 261 | "rng = pd.period_range('2016-01-01 12:15', freq = 'H', periods = 10)\n", 262 | "rng" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": null, 268 | "metadata": { 269 | "collapsed": false 270 | }, 271 | "outputs": [], 272 | "source": [ 273 | "rng = pd.period_range('2016-01-01 12:15', freq = '60T', periods = 10)\n", 274 | "rng" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": { 281 | "collapsed": false 282 | }, 283 | "outputs": [], 284 | "source": [ 285 | "rng = pd.period_range('2016-01-01 12:15', freq = '1H', periods = 10)\n", 286 | "rng" 287 | ] 288 | }, 289 | { 290 | "cell_type": "markdown", 291 | "metadata": {}, 292 | "source": [ 293 | "### How can you determine whether a timestamp falls within a given period?" 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": null, 299 | "metadata": { 300 | "collapsed": false 301 | }, 302 | "outputs": [], 303 | "source": [ 304 | "%load snippets/startend.py" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": {}, 310 | "source": [ 311 | "### Try out some other functionality with different offset-aliases. Anything interesting?\n", 312 | "\n", 313 | "http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases" 314 | ] 315 | }, 316 | { 317 | "cell_type": "code", 318 | "execution_count": null, 319 | "metadata": { 320 | "collapsed": false 321 | }, 322 | "outputs": [], 323 | "source": [ 324 | "# %load snippets/offset_aliases.py" 325 | ] 326 | }, 327 | { 328 | "cell_type": "markdown", 329 | "metadata": {}, 330 | "source": [ 331 | "### How can you make a pandas Time Series with these aliases?" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": null, 337 | "metadata": { 338 | "collapsed": false 339 | }, 340 | "outputs": [], 341 | "source": [ 342 | "num_periods = 40\n", 343 | "ts_pd = pd.Series(range(num_periods), pd.period_range('2016-07-01 11:15', freq = '60T', periods = num_periods))" 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "execution_count": null, 349 | "metadata": { 350 | "collapsed": false 351 | }, 352 | "outputs": [], 353 | "source": [ 354 | "ts_pd['2016-7-1 11':'2016-7-1 13']" 355 | ] 356 | }, 357 | { 358 | "cell_type": "markdown", 359 | "metadata": {}, 360 | "source": [ 361 | "### How can we index a time series with a date_range?" 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": null, 367 | "metadata": { 368 | "collapsed": true 369 | }, 370 | "outputs": [], 371 | "source": [ 372 | "num_periods = 40\n", 373 | "ts_dt = pd.Series(range(num_periods), pd.date_range('2016-07-01 11:15', freq = '60T', periods = num_periods))" 374 | ] 375 | }, 376 | { 377 | "cell_type": "markdown", 378 | "metadata": {}, 379 | "source": [ 380 | "### What are the use cases for a series with a DateTimeIndex vs a PeriodIndex? Where will we see a difference?" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": null, 386 | "metadata": { 387 | "collapsed": false 388 | }, 389 | "outputs": [], 390 | "source": [ 391 | "ts_dt['2016-7-1 11']" 392 | ] 393 | }, 394 | { 395 | "cell_type": "code", 396 | "execution_count": null, 397 | "metadata": { 398 | "collapsed": false 399 | }, 400 | "outputs": [], 401 | "source": [ 402 | "ts_pd['2016-7-1 11':'2016-7-1 13']" 403 | ] 404 | }, 405 | { 406 | "cell_type": "markdown", 407 | "metadata": {}, 408 | "source": [ 409 | "### How can we convert between a DateTimeIndex and a PeriodIndex?" 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": null, 415 | "metadata": { 416 | "collapsed": false 417 | }, 418 | "outputs": [], 419 | "source": [ 420 | "ts_dt.to_period()\n", 421 | "ts_pd.to_timestamp()" 422 | ] 423 | }, 424 | { 425 | "cell_type": "markdown", 426 | "metadata": {}, 427 | "source": [ 428 | "# Try\n", 429 | "\n", 430 | "(1) How can you create a pd.Timestamp with a European style formatted date string? hint: dayfirst flag\n", 431 | "\n", 432 | "(2) How can you generate string representation in a desired format from a pd.Timestamp? " 433 | ] 434 | }, 435 | { 436 | "cell_type": "code", 437 | "execution_count": null, 438 | "metadata": { 439 | "collapsed": false 440 | }, 441 | "outputs": [], 442 | "source": [ 443 | "# %load snippets/try1.py" 444 | ] 445 | } 446 | ], 447 | "metadata": { 448 | "kernelspec": { 449 | "display_name": "Python 3", 450 | "language": "python", 451 | "name": "python3" 452 | }, 453 | "language_info": { 454 | "codemirror_mode": { 455 | "name": "ipython", 456 | "version": 3 457 | }, 458 | "file_extension": ".py", 459 | "mimetype": "text/x-python", 460 | "name": "python", 461 | "nbconvert_exporter": "python", 462 | "pygments_lexer": "ipython3", 463 | "version": "3.5.3" 464 | }, 465 | "widgets": { 466 | "state": {}, 467 | "version": "1.1.1" 468 | } 469 | }, 470 | "nbformat": 4, 471 | "nbformat_minor": 0 472 | } 473 | -------------------------------------------------------------------------------- /02. Time Zone Handling.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import numpy as np \n", 12 | "import pandas as pd" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "# pandas Time zone information" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": null, 25 | "metadata": { 26 | "collapsed": true 27 | }, 28 | "outputs": [], 29 | "source": [ 30 | "rng = pd.date_range('3/6/2016 00:00', periods = 15, freq = 'd')\n", 31 | "rng.tz" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "metadata": { 38 | "collapsed": false 39 | }, 40 | "outputs": [], 41 | "source": [ 42 | "rng = pd.date_range('3/6/2016 00:00', periods = 15, freq = 'd', tz = 'Europe/London')\n", 43 | "rng.tz" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "### Getting lists of time zones" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": { 57 | "collapsed": false 58 | }, 59 | "outputs": [], 60 | "source": [ 61 | "from pytz import common_timezones, all_timezones\n", 62 | "print(len(common_timezones))" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": { 69 | "collapsed": false 70 | }, 71 | "outputs": [], 72 | "source": [ 73 | "print(len(all_timezones))" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "### What are some time zones not considered 'common'?" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": { 87 | "collapsed": false 88 | }, 89 | "outputs": [], 90 | "source": [ 91 | "set(all_timezones).difference(set(common_timezones))" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "### Localizing a timestamp" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": { 105 | "collapsed": false 106 | }, 107 | "outputs": [], 108 | "source": [ 109 | "t_naive = pd.Timestamp('2016-05-05 08:15')\n", 110 | "t_naive" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": { 117 | "collapsed": false 118 | }, 119 | "outputs": [], 120 | "source": [ 121 | "t = t_naive.tz_localize(tz = 'US/Central')\n", 122 | "t" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": null, 128 | "metadata": { 129 | "collapsed": false 130 | }, 131 | "outputs": [], 132 | "source": [ 133 | "t_naive" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": null, 139 | "metadata": { 140 | "collapsed": false 141 | }, 142 | "outputs": [], 143 | "source": [ 144 | "t.tz_convert('Asia/Tokyo')" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": { 151 | "collapsed": false 152 | }, 153 | "outputs": [], 154 | "source": [ 155 | "t" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "### What is the difference between tz_convert and tz_localize?\n", 163 | "\n", 164 | "hint: try to run tz_convert on a naive time stamp" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "### Fun with daylight savings" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": null, 177 | "metadata": { 178 | "collapsed": false 179 | }, 180 | "outputs": [], 181 | "source": [ 182 | "# You'll get weirdness with timezones based on daylight savings:\n", 183 | "rng = pd.date_range('2016-03-10', periods = 10, tz = 'US/Eastern')\n", 184 | "ts = pd.Series(range(10), index = rng)\n", 185 | "# What do you notice below?\n", 186 | "ts" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "### Ambiguous times" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": null, 199 | "metadata": { 200 | "collapsed": true 201 | }, 202 | "outputs": [], 203 | "source": [ 204 | "# For the same reason you can run into 'ambiguous' dates\n", 205 | "rng_hourly = pd.DatetimeIndex(['11/06/2011 00:00', '11/06/2011 01:00','11/06/2011 01:00', '11/06/2011 02:00','11/06/2011 03:00'])" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": null, 211 | "metadata": { 212 | "collapsed": false 213 | }, 214 | "outputs": [], 215 | "source": [ 216 | "# What happens if we localize?\n", 217 | "rng_hourly.tz_localize('US/Central')" 218 | ] 219 | }, 220 | { 221 | "cell_type": "markdown", 222 | "metadata": {}, 223 | "source": [ 224 | "### How do we deal with this ambiguous time error?\n", 225 | "hint: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#ambiguous-times-when-localizing" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": null, 231 | "metadata": { 232 | "collapsed": false 233 | }, 234 | "outputs": [], 235 | "source": [ 236 | "# %load snippets/ambig.py\n", 237 | "rng_hourly.tz_localize('US/Central', ambiguous = 'infer')" 238 | ] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "metadata": {}, 243 | "source": [ 244 | "### How can we check whether the inference did what we wanted?" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": null, 250 | "metadata": { 251 | "collapsed": false 252 | }, 253 | "outputs": [], 254 | "source": [ 255 | "# %load snippets/confirm.py\n", 256 | "rng_hourly.tz_localize('US/Central', ambiguous = 'infer').tz_convert('utc')" 257 | ] 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "metadata": {}, 262 | "source": [ 263 | "### Pandas goes to amazing length to try to figure things out for you" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": null, 269 | "metadata": { 270 | "collapsed": false 271 | }, 272 | "outputs": [], 273 | "source": [ 274 | "# What's going on here?\n", 275 | "pd.Timestamp('2016-03-13 02:00', tz = 'US/Eastern')" 276 | ] 277 | }, 278 | { 279 | "cell_type": "code", 280 | "execution_count": null, 281 | "metadata": { 282 | "collapsed": true 283 | }, 284 | "outputs": [], 285 | "source": [] 286 | } 287 | ], 288 | "metadata": { 289 | "kernelspec": { 290 | "display_name": "Python 3", 291 | "language": "python", 292 | "name": "python3" 293 | }, 294 | "language_info": { 295 | "codemirror_mode": { 296 | "name": "ipython", 297 | "version": 3 298 | }, 299 | "file_extension": ".py", 300 | "mimetype": "text/x-python", 301 | "name": "python", 302 | "nbconvert_exporter": "python", 303 | "pygments_lexer": "ipython3", 304 | "version": "3.5.3" 305 | }, 306 | "widgets": { 307 | "state": {}, 308 | "version": "1.1.1" 309 | } 310 | }, 311 | "nbformat": 4, 312 | "nbformat_minor": 0 313 | } 314 | -------------------------------------------------------------------------------- /03. Reading and working with time-based data.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "%matplotlib inline \n", 12 | "import matplotlib.pylab\n", 13 | "import pandas as pd\n", 14 | "import numpy as np" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": { 21 | "collapsed": false 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "with open('data/ao_monthly.txt') as f:\n", 26 | " for x in range(5):\n", 27 | " print(next(f))" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": { 34 | "collapsed": false 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "data = pd.read_fwf('data/ao_monthly.txt', header = None)" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": { 45 | "collapsed": false 46 | }, 47 | "outputs": [], 48 | "source": [ 49 | "# Not so great\n", 50 | "data.head()" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "### Look at the options for read_fwf...what looks relevant?" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": { 64 | "collapsed": false 65 | }, 66 | "outputs": [], 67 | "source": [ 68 | "# %load snippets/readtime.py\n", 69 | "data = pd.read_fwf('data/ao_monthly.txt', header = None, index_col = 0, parse_dates = [[0, 1]], infer_datetime_format = True)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": { 76 | "collapsed": false 77 | }, 78 | "outputs": [], 79 | "source": [ 80 | "data.head()" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": { 87 | "collapsed": false 88 | }, 89 | "outputs": [], 90 | "source": [ 91 | "data.index" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "collapsed": false 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "data.index.names = ['Month']\n", 103 | "data.columns = ['Value']\n", 104 | "data.head()" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "### What is the empirical range of dates?" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": { 118 | "collapsed": false 119 | }, 120 | "outputs": [], 121 | "source": [ 122 | "# %load snippets/daterange.py\n", 123 | "print(min(data.index))\n", 124 | "print(max(data.index))" 125 | ] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "metadata": {}, 130 | "source": [ 131 | "### How can we convert to complementary representation?" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": { 138 | "collapsed": false 139 | }, 140 | "outputs": [], 141 | "source": [ 142 | "# %load snippets/changerep.py\n", 143 | "data.to_period()" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "### More about reading in data\n", 151 | "\n", 152 | "When reading in dates with a pd.read function, you have several time-related parameters you can adjust: \n", 153 | "parse_dates, infer_datetime_format, date_parser\n", 154 | "\n", 155 | "Experiment with these using %timeit to see if there are performance differences\n", 156 | "\n", 157 | "Hint:\n", 158 | "infer_datetime_format = True, no date parser provided.\n", 159 | "What other combos can you come up with?" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": { 166 | "collapsed": false 167 | }, 168 | "outputs": [], 169 | "source": [ 170 | "import timeit\n", 171 | "# First, let's see how to use a date_parser:\n", 172 | "dateparse = lambda x, y: pd.datetime.strptime('%s-%s'%(x,y), '%Y-%m')\n", 173 | "\n", 174 | "%timeit data = pd.read_fwf('data/ao_monthly.txt', header = None, index_col = 0, parse_dates = [[0, 1]], date_parser = dateparse)" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": { 181 | "collapsed": false 182 | }, 183 | "outputs": [], 184 | "source": [ 185 | "data.head()" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "metadata": { 192 | "collapsed": false 193 | }, 194 | "outputs": [], 195 | "source": [ 196 | "%timeit data = pd.read_fwf('data/ao_monthly.txt', header = None, index_col = 0, parse_dates = [[0, 1]])" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": { 203 | "collapsed": false 204 | }, 205 | "outputs": [], 206 | "source": [ 207 | "%timeit data = pd.read_fwf('data/ao_monthly.txt', header = None, index_col = 0, parse_dates = [[0, 1]], infer_datetime_format = True)" 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "### You can also extract datetimes from existing Data Frame columns" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": null, 220 | "metadata": { 221 | "collapsed": false 222 | }, 223 | "outputs": [], 224 | "source": [ 225 | "# new in pandas 0.18\n", 226 | "df = pd.DataFrame({'year':[2015, 2016], 'month':[2,3], 'day':[4,5], 'hour':[12, 13]})\n", 227 | "df" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": null, 233 | "metadata": { 234 | "collapsed": false 235 | }, 236 | "outputs": [], 237 | "source": [ 238 | "pd.to_datetime(df)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": { 245 | "collapsed": false 246 | }, 247 | "outputs": [], 248 | "source": [ 249 | "# BUT\n", 250 | "df['value'] = 17\n", 251 | "pd.to_datetime(df)" 252 | ] 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "### Truncating" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": null, 264 | "metadata": { 265 | "collapsed": false 266 | }, 267 | "outputs": [], 268 | "source": [ 269 | "ts = pd.Series(range(10), index = pd.date_range('7/31/15', freq = 'M', periods = 10))\n", 270 | "ts" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": null, 276 | "metadata": { 277 | "collapsed": false 278 | }, 279 | "outputs": [], 280 | "source": [ 281 | "# truncating preserves frequency\n", 282 | "ts.truncate(before = '10/31/2015', after = '12/31/2015')" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": null, 288 | "metadata": { 289 | "collapsed": false, 290 | "scrolled": true 291 | }, 292 | "outputs": [], 293 | "source": [ 294 | "# You can truncate in a way that does not preserve frequency\n", 295 | "ts[[1, 6, 7]].index" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "metadata": { 302 | "collapsed": false 303 | }, 304 | "outputs": [], 305 | "source": [ 306 | "# But Pandas will try to preserve frequency automatically whenever possible/logical\n", 307 | "ts[0:10:2]" 308 | ] 309 | } 310 | ], 311 | "metadata": { 312 | "kernelspec": { 313 | "display_name": "Python 3", 314 | "language": "python", 315 | "name": "python3" 316 | }, 317 | "language_info": { 318 | "codemirror_mode": { 319 | "name": "ipython", 320 | "version": 3 321 | }, 322 | "file_extension": ".py", 323 | "mimetype": "text/x-python", 324 | "name": "python", 325 | "nbconvert_exporter": "python", 326 | "pygments_lexer": "ipython3", 327 | "version": "3.5.3" 328 | }, 329 | "widgets": { 330 | "state": {}, 331 | "version": "1.1.1" 332 | } 333 | }, 334 | "nbformat": 4, 335 | "nbformat_minor": 0 336 | } 337 | -------------------------------------------------------------------------------- /04. Resampling.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import pandas as pd\n", 12 | "import numpy as np" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": null, 18 | "metadata": { 19 | "collapsed": false 20 | }, 21 | "outputs": [], 22 | "source": [ 23 | "rng = pd.date_range('1/1/2011', periods = 72, freq = 'H')\n", 24 | "ts = pd.Series(list(range(len(rng))), index = rng)" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": { 31 | "collapsed": false 32 | }, 33 | "outputs": [], 34 | "source": [ 35 | "ts.head()" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": { 42 | "collapsed": true 43 | }, 44 | "outputs": [], 45 | "source": [ 46 | "converted = ts.asfreq('45Min', method = 'ffill')\n", 47 | "# try 'ffill', 'bfill', None" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "collapsed": false 55 | }, 56 | "outputs": [], 57 | "source": [ 58 | "converted.head()" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "### What does the above code do to the size and content of your data frame?" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": { 72 | "collapsed": false 73 | }, 74 | "outputs": [], 75 | "source": [ 76 | "converted[1:10]" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": { 83 | "collapsed": false 84 | }, 85 | "outputs": [], 86 | "source": [ 87 | "ts[1:10]" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": { 94 | "collapsed": false 95 | }, 96 | "outputs": [], 97 | "source": [ 98 | "converted.shape" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": { 105 | "collapsed": false 106 | }, 107 | "outputs": [], 108 | "source": [ 109 | "ts.shape" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "### Take a look at the specs for .asfreq(). What are your options for filling in missing data?" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": { 123 | "collapsed": true 124 | }, 125 | "outputs": [], 126 | "source": [ 127 | "ts.asfreq??" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "### How can you go to less frequent rather than more frequent?" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "metadata": { 141 | "collapsed": true 142 | }, 143 | "outputs": [], 144 | "source": [ 145 | "converted = ts.asfreq('3H')" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": null, 151 | "metadata": { 152 | "collapsed": false 153 | }, 154 | "outputs": [], 155 | "source": [ 156 | "converted[1:10]" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": { 163 | "collapsed": false 164 | }, 165 | "outputs": [], 166 | "source": [ 167 | "ts[1:10]" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": null, 173 | "metadata": { 174 | "collapsed": false 175 | }, 176 | "outputs": [], 177 | "source": [ 178 | "# Let's try the more flexible .resample()\n", 179 | "ts.resample('2H', label = 'right').mean()[:10]" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": { 186 | "collapsed": true 187 | }, 188 | "outputs": [], 189 | "source": [ 190 | "ts.resample??" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "metadata": { 197 | "collapsed": false 198 | }, 199 | "outputs": [], 200 | "source": [ 201 | "# What's particularly useful is that we can use reample to event out irregular time series\n", 202 | "irreg_ts = ts[list(np.random.choice(a = list(range(len(ts))), size = 10, replace = False))]" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": { 209 | "collapsed": false 210 | }, 211 | "outputs": [], 212 | "source": [ 213 | "irreg_ts" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": null, 219 | "metadata": { 220 | "collapsed": false 221 | }, 222 | "outputs": [], 223 | "source": [ 224 | "irreg_ts.asfreq('D')" 225 | ] 226 | }, 227 | { 228 | "cell_type": "markdown", 229 | "metadata": {}, 230 | "source": [ 231 | "### Why didn't that work?" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": { 238 | "collapsed": false 239 | }, 240 | "outputs": [], 241 | "source": [ 242 | "irreg_ts = irreg_ts.sort_index()\n", 243 | "irreg_ts" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": null, 249 | "metadata": { 250 | "collapsed": false 251 | }, 252 | "outputs": [], 253 | "source": [ 254 | "irreg_ts.asfreq('D', method = 'bfill')" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": { 261 | "collapsed": false 262 | }, 263 | "outputs": [], 264 | "source": [ 265 | "irreg_ts.resample('D').mean()" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "# Try\n", 273 | "\n", 274 | "(1) What if you want to go to a higher frequency, but you don't want to back fill or forward fill? Why might you want to do that?\n", 275 | "\n", 276 | "(2) What is the difference between .resample() and .asfreq()?\n", 277 | "\n", 278 | "(3) How can I forward-fill only a few days? (hint: .fillna())\n", 279 | "\n", 280 | "(4) What are some helpful functions to use with a Resampler object?" 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": null, 286 | "metadata": { 287 | "collapsed": false 288 | }, 289 | "outputs": [], 290 | "source": [ 291 | "# %load snippets/resampling_end.py" 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": null, 297 | "metadata": { 298 | "collapsed": true 299 | }, 300 | "outputs": [], 301 | "source": [] 302 | } 303 | ], 304 | "metadata": { 305 | "kernelspec": { 306 | "display_name": "Python 3", 307 | "language": "python", 308 | "name": "python3" 309 | }, 310 | "language_info": { 311 | "codemirror_mode": { 312 | "name": "ipython", 313 | "version": 3 314 | }, 315 | "file_extension": ".py", 316 | "mimetype": "text/x-python", 317 | "name": "python", 318 | "nbconvert_exporter": "python", 319 | "pygments_lexer": "ipython3", 320 | "version": "3.5.3" 321 | }, 322 | "widgets": { 323 | "state": {}, 324 | "version": "1.1.1" 325 | } 326 | }, 327 | "nbformat": 4, 328 | "nbformat_minor": 0 329 | } 330 | -------------------------------------------------------------------------------- /05. Moving Window Functions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "%matplotlib inline\n", 12 | "import matplotlib.pylab\n", 13 | "\n", 14 | "%pylab inline\n", 15 | "pylab.rcParams['figure.figsize'] = (10, 6)\n", 16 | "\n", 17 | "import numpy as np\n", 18 | "import pandas as pd" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "# The special thing about time series is that data points relate to one another...they are not independent\n", 26 | "So we can to compare them and relate them. One way to do this is to look at how they change. For example, we can 'difference' a time series" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": { 33 | "collapsed": false 34 | }, 35 | "outputs": [], 36 | "source": [ 37 | "ts = pd.Series(np.random.randn(20) + 10, pd.date_range('7/1/16', freq = 'D', periods = 20))\n", 38 | "ts_lagged = ts.shift()" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": { 45 | "collapsed": false 46 | }, 47 | "outputs": [], 48 | "source": [ 49 | "ts.head()" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": { 56 | "collapsed": false 57 | }, 58 | "outputs": [], 59 | "source": [ 60 | "ts_lagged.head()" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": { 67 | "collapsed": false 68 | }, 69 | "outputs": [], 70 | "source": [ 71 | "ts.diff()" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": { 78 | "collapsed": false 79 | }, 80 | "outputs": [], 81 | "source": [ 82 | "plt.plot(ts, color = 'blue')\n", 83 | "plt.plot(ts_lagged, color = 'red')\n", 84 | "plt.plot(ts - ts_lagged, color = 'green')" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "### But the need to difference is quite common, so Pandas does it for you" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "collapsed": false 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "plt.plot(ts.diff(), color = 'black')" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "### Query: how can I shift my time series 'into the future' instead of into the past?" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "metadata": { 116 | "collapsed": false 117 | }, 118 | "outputs": [], 119 | "source": [ 120 | "# %load snippets/shift_future.py" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "# Window functions give you moving aggregate measures of a time series" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": { 134 | "collapsed": true 135 | }, 136 | "outputs": [], 137 | "source": [ 138 | "# Window functions are like aggregation/summary functions\n", 139 | "# You can use them in conjunction with .resample()" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": { 146 | "collapsed": true 147 | }, 148 | "outputs": [], 149 | "source": [ 150 | "df = pd.DataFrame(np.random.randn(600, 3), index = pd.date_range('5/1/2016', freq = 'D', periods = 600), columns = ['A', 'B', 'C'])" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": null, 156 | "metadata": { 157 | "collapsed": false 158 | }, 159 | "outputs": [], 160 | "source": [ 161 | "r = df.rolling(window = 20)\n", 162 | "r" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": { 169 | "collapsed": false 170 | }, 171 | "outputs": [], 172 | "source": [ 173 | "df['A'].plot(color = 'gray')\n", 174 | "r.mean()['A'].plot(color = 'red')" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": { 181 | "collapsed": false 182 | }, 183 | "outputs": [], 184 | "source": [ 185 | "df['A'].plot(color = 'gray')\n", 186 | "r.min()['A'].plot(color = 'red')" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "### Try out some of these options with .rolling()\n", 194 | "\n", 195 | "r.agg, r.apply, r.count, r.max, r.median, r.name, r.quantile, r.kurt, \n", 196 | "r.aggregate, r.std, r.skew, r.sum, r.var" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": { 203 | "collapsed": false 204 | }, 205 | "outputs": [], 206 | "source": [ 207 | "df['A'].plot(color = 'gray')\n", 208 | "r.quantile(.30)['A'].plot(color = 'red')" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "### What about a custom function?" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": { 222 | "collapsed": false 223 | }, 224 | "outputs": [], 225 | "source": [ 226 | "# %load snippets/custom_rolling.py" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": null, 232 | "metadata": { 233 | "collapsed": false 234 | }, 235 | "outputs": [], 236 | "source": [ 237 | "# %load snippets/custom_rolling2.py" 238 | ] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "metadata": {}, 243 | "source": [ 244 | "## Expanding windows" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": null, 250 | "metadata": { 251 | "collapsed": false 252 | }, 253 | "outputs": [], 254 | "source": [ 255 | "df.expanding(min_periods = 1).mean()[1:5]" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": { 262 | "collapsed": false 263 | }, 264 | "outputs": [], 265 | "source": [ 266 | "df.expanding(min_periods = 1).median().plot()" 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": {}, 272 | "source": [ 273 | "# Try" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "(1) How can you perform an exponentially weight moving average rather than a window function? (hint: look for ewma + pandas docs)\n", 281 | "\n", 282 | "(2) When would you use an expanding window vs. a rolling window?\n", 283 | "\n", 284 | "(3) Write a custom function to repace .quantile(.5) function for a moving average\n", 285 | "\n", 286 | "(4) How would you compute more than one aggregation function on a moving window function at the same time? " 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": { 293 | "collapsed": false 294 | }, 295 | "outputs": [], 296 | "source": [ 297 | "# %load snippets/window_funcs_try.py" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": null, 303 | "metadata": { 304 | "collapsed": true 305 | }, 306 | "outputs": [], 307 | "source": [] 308 | } 309 | ], 310 | "metadata": { 311 | "anaconda-cloud": {}, 312 | "kernelspec": { 313 | "display_name": "Python [Root]", 314 | "language": "python", 315 | "name": "Python [Root]" 316 | }, 317 | "language_info": { 318 | "codemirror_mode": { 319 | "name": "ipython", 320 | "version": 3 321 | }, 322 | "file_extension": ".py", 323 | "mimetype": "text/x-python", 324 | "name": "python", 325 | "nbconvert_exporter": "python", 326 | "pygments_lexer": "ipython3", 327 | "version": "3.5.2" 328 | }, 329 | "widgets": { 330 | "state": {}, 331 | "version": "1.1.1" 332 | } 333 | }, 334 | "nbformat": 4, 335 | "nbformat_minor": 0 336 | } 337 | -------------------------------------------------------------------------------- /09a. AR + MA processes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "%matplotlib inline\n", 12 | "import matplotlib.pylab as plt\n", 13 | "\n", 14 | "import pandas as pd\n", 15 | "import numpy as np\n", 16 | "\n", 17 | "from statsmodels.tsa.stattools import acf, pacf" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "### First let's figure out how to generate an AR proces" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": { 31 | "collapsed": false 32 | }, 33 | "outputs": [], 34 | "source": [ 35 | "def ar1(phi = .9, n = 1000, init = 0):\n", 36 | " time_series = [init]\n", 37 | " error = np.random.randn(n)\n", 38 | " for period in range(n):\n", 39 | " time_series.append(error[period] + phi*time_series[-1])\n", 40 | " return pd.Series(time_series[1:], index = range(n))\n", 41 | " \n", 42 | "def ar2(phi1 = .9, phi2 = -.8, n = 1000, init = 0):\n", 43 | " time_series = [init, init]\n", 44 | " error = np.random.randn(n)\n", 45 | " for period in range(2,n):\n", 46 | " time_series.append(error[period] + phi1*time_series[-1] + phi2*time_series[-2])\n", 47 | " return pd.Series(time_series[1:], index = range(1,n))\n", 48 | " " 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "metadata": { 55 | "collapsed": false 56 | }, 57 | "outputs": [], 58 | "source": [ 59 | "# try out different values of phi >=1 as compared to < 1\n", 60 | "# sometimes you need to make a large n to see lack of stationarity\n", 61 | "a1 = ar1(phi = 1.1, n = 40)\n", 62 | "a1.plot()" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": { 69 | "collapsed": false 70 | }, 71 | "outputs": [], 72 | "source": [ 73 | "# try out different values of phi >=1 as compared to < 1\n", 74 | "# sometimes you need to make a large n to see lack of stationarity\n", 75 | "a2 = ar2(n = 50, phi2 = 1.7)\n", 76 | "a2.plot()" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "### Now let's generate an MA process" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": { 90 | "collapsed": false 91 | }, 92 | "outputs": [], 93 | "source": [ 94 | "# %load snippets/7ma.py" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": { 101 | "collapsed": false 102 | }, 103 | "outputs": [], 104 | "source": [ 105 | "m1 = ma1(theta = -1000)\n", 106 | "m1.plot()" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "### Let's look at ACF + PACF for each kind of process" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": null, 119 | "metadata": { 120 | "collapsed": false 121 | }, 122 | "outputs": [], 123 | "source": [ 124 | "a1 = ar1(phi = .5, n = 1000)\n", 125 | "a1_acf = acf(a1, nlags = 20)\n", 126 | "plt.plot(a1_acf)\n", 127 | "plt.axhline(y=0,linestyle='--', color = 'black')\n", 128 | "plt.axhline(y=-1.96/np.sqrt(len(a1)),linestyle='--', color = 'red')\n", 129 | "plt.axhline(y=1.96/np.sqrt(len(a1)),linestyle='--', color = 'red')" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": { 136 | "collapsed": false 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "a1 = ar1(phi = .5, n = 1000)\n", 141 | "a1_pacf = pacf(a1, nlags = 20)\n", 142 | "plt.plot(a1_pacf)\n", 143 | "plt.axhline(y=0,linestyle='--', color = 'black')\n", 144 | "plt.axhline(y=-1.96/np.sqrt(len(a1)),linestyle='--', color = 'red')\n", 145 | "plt.axhline(y=1.96/np.sqrt(len(a1)),linestyle='--', color = 'red')" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": null, 151 | "metadata": { 152 | "collapsed": false 153 | }, 154 | "outputs": [], 155 | "source": [ 156 | "m1 = ma1(n = 1000, theta = .9)\n", 157 | "m1_acf = acf(m1, nlags = 20)\n", 158 | "plt.plot(m1_acf)\n", 159 | "plt.axhline(y=0,linestyle='--', color = 'black')\n", 160 | "plt.axhline(y=-1.96/np.sqrt(len(m1)),linestyle='--', color = 'red')\n", 161 | "plt.axhline(y=1.96/np.sqrt(len(m1)),linestyle='--', color = 'red')" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": { 168 | "collapsed": false 169 | }, 170 | "outputs": [], 171 | "source": [ 172 | "m1 = ma1(n = 1000, theta = .9)\n", 173 | "m1_pacf = pacf(m1, nlags = 20)\n", 174 | "plt.plot(m1_pacf)\n", 175 | "plt.axhline(y=0,linestyle='--', color = 'black')\n", 176 | "plt.axhline(y=-1.96/np.sqrt(len(m1)),linestyle='--', color = 'red')\n", 177 | "plt.axhline(y=1.96/np.sqrt(len(m1)),linestyle='--', color = 'red')" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": { 184 | "collapsed": true 185 | }, 186 | "outputs": [], 187 | "source": [] 188 | } 189 | ], 190 | "metadata": { 191 | "anaconda-cloud": {}, 192 | "kernelspec": { 193 | "display_name": "Python [Root]", 194 | "language": "python", 195 | "name": "Python [Root]" 196 | }, 197 | "language_info": { 198 | "codemirror_mode": { 199 | "name": "ipython", 200 | "version": 3 201 | }, 202 | "file_extension": ".py", 203 | "mimetype": "text/x-python", 204 | "name": "python", 205 | "nbconvert_exporter": "python", 206 | "pygments_lexer": "ipython3", 207 | "version": "3.5.2" 208 | }, 209 | "widgets": { 210 | "state": {}, 211 | "version": "1.1.1" 212 | } 213 | }, 214 | "nbformat": 4, 215 | "nbformat_minor": 0 216 | } 217 | -------------------------------------------------------------------------------- /09b. Forecasting.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import pandas as pd\n", 12 | "import numpy as np\n", 13 | "import matplotlib.pylab as plt\n", 14 | "%matplotlib inline\n", 15 | "from matplotlib.pylab import rcParams\n", 16 | "rcParams['figure.figsize'] = 15, 6" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Let's do a quick and dirty detrend" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": { 30 | "collapsed": false 31 | }, 32 | "outputs": [], 33 | "source": [ 34 | "air_passengers = pd.read_csv(\"./data/AirPassengers.csv\", header = 0, parse_dates = [0], names = ['Month', 'Passengers'], index_col = 0)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": { 41 | "collapsed": false 42 | }, 43 | "outputs": [], 44 | "source": [ 45 | "log_air_passengers = np.log(air_passengers.Passengers)" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": { 52 | "collapsed": false 53 | }, 54 | "outputs": [], 55 | "source": [ 56 | "log_air_passengers_diff = log_air_passengers - log_air_passengers.shift()" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "collapsed": false 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "plt.plot(log_air_passengers_diff)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "### By the way, how would I difference again?" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": { 81 | "collapsed": false 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "# %load snippets/7_diff2.py\n", 86 | "\n" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "### What information are you losing when you difference? What about when you difference twice?" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": { 100 | "collapsed": true 101 | }, 102 | "outputs": [], 103 | "source": [ 104 | "# think physics!" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": { 111 | "collapsed": false 112 | }, 113 | "outputs": [], 114 | "source": [ 115 | "log_air_passengers_diff.dropna(inplace=True)" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": null, 121 | "metadata": { 122 | "collapsed": false 123 | }, 124 | "outputs": [], 125 | "source": [ 126 | "# try out nc, ct, ctt\n", 127 | "# http://www.statsmodels.org/0.6.1/generated/statsmodels.tsa.stattools.adfuller.html\n", 128 | "from statsmodels.tsa.stattools import adfuller\n", 129 | "useful_values_raw = adfuller(log_air_passengers_diff, autolag = 'AIC', regression = 'c')[:5]\n", 130 | "useful_values = [v for v in useful_values_raw[:4]]\n", 131 | "useful_values.extend([useful_values_raw[4]['1%'], useful_values_raw[4]['5%'], useful_values_raw[4]['10%']])\n", 132 | "pd.DataFrame({ 'Value':useful_values, 'Label':['Test Statistic','p-value','#Lags Used','Number of Observations Used', 'Critical value for 1%', 'Critical value for 5%', 'Critical value for 10%']})" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": { 139 | "collapsed": true 140 | }, 141 | "outputs": [], 142 | "source": [ 143 | "# Let's talk about the ARIMA model\n", 144 | "# Auto-Regressive Integrated Moving Average\n", 145 | "# In this case we're talking about a series with dependence among values (more natural)" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": null, 151 | "metadata": { 152 | "collapsed": true 153 | }, 154 | "outputs": [], 155 | "source": [ 156 | "# Nothing but a linear regression with a few times\n", 157 | "# 1. The number of Auto-Regressive Terms (p)\n", 158 | "# 2. The number of differences taken (d)\n", 159 | "# 3. The number of Moving Average Terms (q)" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "# Let's do it" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": { 173 | "collapsed": false 174 | }, 175 | "outputs": [], 176 | "source": [ 177 | "# We don't pull these out of thin air, but rather draw them from the data\n", 178 | "from statsmodels.tsa.stattools import acf, pacf\n", 179 | "\n", 180 | "lag_acf = acf(log_air_passengers_diff.values, nlags = 20)\n", 181 | "lag_pacf = pacf(log_air_passengers_diff.values, nlags = 20)" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": null, 187 | "metadata": { 188 | "collapsed": false 189 | }, 190 | "outputs": [], 191 | "source": [ 192 | "plt.subplot(121) \n", 193 | "plt.bar(left = range(len(lag_acf)), height = lag_acf)\n", 194 | "plt.axhline(y=0,linestyle='--')\n", 195 | "plt.axhline(y=-1.96/np.sqrt(len(log_air_passengers_diff)),linestyle='--')\n", 196 | "plt.axhline(y=1.96/np.sqrt(len(log_air_passengers_diff)),linestyle='--')" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": { 203 | "collapsed": true 204 | }, 205 | "outputs": [], 206 | "source": [ 207 | "# look at where the plot crosses the upper confidence interval for the first time\n", 208 | "# for ACF this is 1 and gives us the p value" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": { 215 | "collapsed": false 216 | }, 217 | "outputs": [], 218 | "source": [ 219 | "plt.subplot(121) \n", 220 | "plt.bar(left = range(len(lag_pacf)), height = lag_pacf)\n", 221 | "plt.axhline(y=0,linestyle='--')\n", 222 | "plt.axhline(y=-1.96/np.sqrt(len(log_air_passengers_diff)),linestyle='--')\n", 223 | "plt.axhline(y=1.96/np.sqrt(len(log_air_passengers_diff)),linestyle='--')" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": null, 229 | "metadata": { 230 | "collapsed": true 231 | }, 232 | "outputs": [], 233 | "source": [ 234 | "# look at where the plot crosses the upper confidence interval for the first time\n", 235 | "# for PACF this is 2 and gives us the p value" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": null, 241 | "metadata": { 242 | "collapsed": true 243 | }, 244 | "outputs": [], 245 | "source": [ 246 | "from statsmodels.tsa.arima_model import ARIMA" 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": null, 252 | "metadata": { 253 | "collapsed": false 254 | }, 255 | "outputs": [], 256 | "source": [ 257 | "# AR model\n", 258 | "# try different values of p\n", 259 | "model = ARIMA(log_air_passengers, order=(2, 1, 0)) \n", 260 | "results_AR = model.fit(disp=-1) \n", 261 | "plt.plot(log_air_passengers_diff)\n", 262 | "plt.plot(results_AR.fittedvalues, color='red')\n", 263 | "plt.title('RSS: %.4f'% sum((results_AR.fittedvalues-log_air_passengers_diff)**2))" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": null, 269 | "metadata": { 270 | "collapsed": false 271 | }, 272 | "outputs": [], 273 | "source": [ 274 | "# try different values of q\n", 275 | "# MA model\n", 276 | "model = ARIMA(log_air_passengers, order=(0, 1, 1)) \n", 277 | "results_MA = model.fit(disp=-1) \n", 278 | "plt.plot(log_air_passengers_diff)\n", 279 | "plt.plot(results_MA.fittedvalues, color='red')\n", 280 | "plt.title('RSS: %.4f'% sum((results_MA.fittedvalues-log_air_passengers_diff)**2))" 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": null, 286 | "metadata": { 287 | "collapsed": false 288 | }, 289 | "outputs": [], 290 | "source": [ 291 | "# ARIMA model\n", 292 | "# try p = 1 or 2\n", 293 | "model = ARIMA(log_air_passengers, order=(1, 1, 1)) \n", 294 | "results_ARIMA = model.fit(disp=-1) \n", 295 | "plt.plot(log_air_passengers_diff)\n", 296 | "plt.plot(results_ARIMA.fittedvalues, color='red')\n", 297 | "plt.title('RSS: %.4f'% sum((results_ARIMA.fittedvalues-log_air_passengers_diff)**2))" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": null, 303 | "metadata": { 304 | "collapsed": true 305 | }, 306 | "outputs": [], 307 | "source": [ 308 | "# should we do un-log and then un-diff?\n", 309 | "# or un-diff and then un-log?\n", 310 | "# let's go back and see what we did" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": null, 316 | "metadata": { 317 | "collapsed": false 318 | }, 319 | "outputs": [], 320 | "source": [ 321 | "predictions_ARIMA_diff = pd.Series(results_ARIMA.fittedvalues, copy=True)\n", 322 | "print(predictions_ARIMA_diff.head())" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": null, 328 | "metadata": { 329 | "collapsed": false 330 | }, 331 | "outputs": [], 332 | "source": [ 333 | "predictions_ARIMA_diff_cumsum = predictions_ARIMA_diff.cumsum()\n", 334 | "print(predictions_ARIMA_diff_cumsum.head())" 335 | ] 336 | }, 337 | { 338 | "cell_type": "code", 339 | "execution_count": null, 340 | "metadata": { 341 | "collapsed": false 342 | }, 343 | "outputs": [], 344 | "source": [ 345 | "predictions_ARIMA_log = pd.Series(log_air_passengers.iloc[0], index=log_air_passengers.index)" 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": null, 351 | "metadata": { 352 | "collapsed": false 353 | }, 354 | "outputs": [], 355 | "source": [ 356 | "predictions_ARIMA_log = pd.Series(log_air_passengers.ix[0], index=log_air_passengers.index)\n", 357 | "predictions_ARIMA_log = predictions_ARIMA_log.add(predictions_ARIMA_diff_cumsum,fill_value=0)\n", 358 | "predictions_ARIMA_log.head()" 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": null, 364 | "metadata": { 365 | "collapsed": false 366 | }, 367 | "outputs": [], 368 | "source": [ 369 | "predictions_ARIMA = np.exp(predictions_ARIMA_log)\n", 370 | "plt.plot(air_passengers)\n", 371 | "plt.plot(predictions_ARIMA)" 372 | ] 373 | }, 374 | { 375 | "cell_type": "markdown", 376 | "metadata": {}, 377 | "source": [ 378 | "# Know more" 379 | ] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "execution_count": null, 384 | "metadata": { 385 | "collapsed": true 386 | }, 387 | "outputs": [], 388 | "source": [ 389 | "# Seasonal ARIMA\n", 390 | "# http://www.statsmodels.org/dev/generated/statsmodels.tsa.statespace.sarimax.SARIMAX.html\n", 391 | "# Confidence interval for ARIMA \n", 392 | "# http://statsmodels.sourceforge.net/devel/generated/statsmodels.tsa.arima_model.ARIMAResults.forecast.html#statsmodels.tsa.arima_model.ARMAResults.forecast" 393 | ] 394 | }, 395 | { 396 | "cell_type": "code", 397 | "execution_count": null, 398 | "metadata": { 399 | "collapsed": true 400 | }, 401 | "outputs": [], 402 | "source": [] 403 | } 404 | ], 405 | "metadata": { 406 | "anaconda-cloud": {}, 407 | "kernelspec": { 408 | "display_name": "Python [Root]", 409 | "language": "python", 410 | "name": "Python [Root]" 411 | }, 412 | "language_info": { 413 | "codemirror_mode": { 414 | "name": "ipython", 415 | "version": 3 416 | }, 417 | "file_extension": ".py", 418 | "mimetype": "text/x-python", 419 | "name": "python", 420 | "nbconvert_exporter": "python", 421 | "pygments_lexer": "ipython3", 422 | "version": "3.5.2" 423 | }, 424 | "widgets": { 425 | "state": {}, 426 | "version": "1.1.1" 427 | } 428 | }, 429 | "nbformat": 4, 430 | "nbformat_minor": 0 431 | } 432 | -------------------------------------------------------------------------------- /09c. Spectral Analysis.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import matplotlib.pylab as plt\n", 12 | "%matplotlib inline\n", 13 | "import numpy as np\n", 14 | "from numpy import fft\n", 15 | "import pandas as pd" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "### Let's use Fourier coefficients as a quick way to determine the principal cosine components of a time series" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 2, 28 | "metadata": { 29 | "collapsed": true 30 | }, 31 | "outputs": [], 32 | "source": [ 33 | "# courtesy of https://gist.github.com/tartakynov/83f3cd8f44208a1856ce\n", 34 | "def fourierExtrapolation(x, n_predict):\n", 35 | " n = x.size\n", 36 | " n_harm = 5 # number of harmonics in model\n", 37 | " t = np.arange(0, n)\n", 38 | " p = np.polyfit(t, x, 1) # find linear trend in x\n", 39 | " x_notrend = x - p[0] * t # detrended x\n", 40 | " x_freqdom = fft.fft(x_notrend) # detrended x in frequency domain\n", 41 | " f = fft.fftfreq(n) # frequencies\n", 42 | " indexes = list(range(n))\n", 43 | " # sort indexes by frequency, lower -> higher\n", 44 | " indexes.sort(key = lambda i: np.absolute(f[i]))\n", 45 | " \n", 46 | " t = np.arange(0, n + n_predict)\n", 47 | " restored_sig = np.zeros(t.size)\n", 48 | " for i in indexes[:1 + n_harm * 2]:\n", 49 | " ampli = np.absolute(x_freqdom[i]) / n # amplitude\n", 50 | " phase = np.angle(x_freqdom[i]) # phase\n", 51 | " restored_sig += ampli * np.cos(2 * np.pi * f[i] * t + phase)\n", 52 | " return restored_sig + p[0] * t" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 3, 58 | "metadata": { 59 | "collapsed": false 60 | }, 61 | "outputs": [ 62 | { 63 | "data": { 64 | "text/plain": [ 65 | "" 66 | ] 67 | }, 68 | "execution_count": 3, 69 | "metadata": {}, 70 | "output_type": "execute_result" 71 | }, 72 | { 73 | "data": { 74 | "image/png": "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\nDYaY4XQZ2RPdGRKLCRMmMGbMGL766qu41UEi7AG51XX06NHlVa1yw+QyMkRFqlkIRhASF6VU2Ab5\nUILkMI+krsmAEQRDpcIpCAcPxqcelY1NmzZx+eWX06BBA4477jheeuklAC666CLuv//+kv169+5N\nv379+Omnn7jtttuYN28etWrVom7dugD06dOH/v37c9FFF1GrVi1yc3OZNm0a7du3p3bt2jRr1oyh\nQ4eWnG/t2rWkpaXx+uuvk52dTXZ2NiNH+gMiDxw4wN133012djZNmjThnnvuoaioyPUzPPPMMzRv\n3pzDDz+cNm3a8OGHHwKErOvjjz9ecvzrr79OixYtqF+/Pj179mTTpk0l76WlpfHqq6/SsmVL6tat\ny+23317WW146lFIJ96erZUgUdDOq/26+Od61KRsdOwZ+nrlz412j2JDIv5lDhw6pU089VQ0bNkwd\nPHhQ/fbbb+q4445TM2bMUJs3b1YNGzZUs2fPVm+99ZY67rjj1P79+5VSSo0fP16dddZZAee64YYb\nVJ06ddS8efOUUkoVFhaqOXPmqKVLlyqllFqyZIlq1KiR+uijj5RSSq1Zs0aJiLrqqqtUfn6+WrJk\niTriiCPUrFmzlFJKPfbYY6pTp05q27Ztatu2ber0009Xjz/+uFJKqdzcXNW0adOSa7/33ntq8+bN\nSimlpkyZomrWrFny2quujz32mFJKqVmzZqn69eurvLw8deDAAXXHHXeozp07l+wrIupvf/ub2rNn\nj1q3bp064ogj1PTp0z3vqdf37SsvddtrLARDpaLSWgjxWlAZWLhwIdu2beORRx4hPT2do48+mn79\n+jF58mQaNmzI6NGjue6667jnnnt48803qVGjRsjz9ejRg44dOwKQmZlJ586dad26NQBt2rShd+/e\nzLGHkqHD2KtVq0abNm3o06dPSertSZMmMXjwYOrVq0e9evUYPHgwb775put1L7vsMho2bAjAFVdc\nQYsWLViwYEFE92DSpEn07duXk08+mYyMDIYPH868efNYZ0u9O3DgQGrVqkXTpk3p2rUreXl5EZ07\nlhhBMFQqnC7nVFlTOSyBhlHp/0rB2rVr2bBhA3Xr1qVu3bpkZWUxfPhw/vjjDwAuvvhiiouLOf74\n4+nUqVPY8zkjfxYsWMDZZ59NgwYNqFOnDq+++irbtm0reV9EaNKkScnrZs2asXHjRgA2btzIUUcd\n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\nAAAAAElFTkSuQmCC\n", 75 | "text/plain": [ 76 | "" 77 | ] 78 | }, 79 | "metadata": {}, 80 | "output_type": "display_data" 81 | } 82 | ], 83 | "source": [ 84 | "x = np.array([669, 592, 664, 1005, 699, 401, 646, 472, 598, 681, 1126, 1260, 562, 491, 714, 530, 521, 687, 776, 802, 499, 536, 871, 801, 965, 768, 381, 497, 458, 699, 549, 427, 358, 219, 635, 756, 775, 969, 598, 630, 649, 722, 835, 812, 724, 966, 778, 584, 697, 737, 777, 1059, 1218, 848, 713, 884, 879, 1056, 1273, 1848, 780, 1206, 1404, 1444, 1412, 1493, 1576, 1178, 836, 1087, 1101, 1082, 775, 698, 620, 651, 731, 906, 958, 1039, 1105, 620, 576, 707, 888, 1052, 1072, 1357, 768, 986, 816, 889, 973, 983, 1351, 1266, 1053, 1879, 2085, 2419, 1880, 2045, 2212, 1491, 1378, 1524, 1231, 1577, 2459, 1848, 1506, 1589, 1386, 1111, 1180, 1075, 1595, 1309, 2092, 1846, 2321, 2036, 3587, 1637, 1416, 1432, 1110, 1135, 1233, 1439, 894, 628, 967, 1176, 1069, 1193, 1771, 1199, 888, 1155, 1254, 1403, 1502, 1692, 1187, 1110, 1382, 1808, 2039, 1810, 1819, 1408, 803, 1568, 1227, 1270, 1268, 1535, 873, 1006, 1328, 1733, 1352, 1906, 2029, 1734, 1314, 1810, 1540, 1958, 1420, 1530, 1126, 721, 771, 874, 997, 1186, 1415, 973, 1146, 1147, 1079, 3854, 3407, 2257, 1200, 734, 1051, 1030, 1370, 2422, 1531, 1062, 530, 1030, 1061, 1249, 2080, 2251, 1190, 756, 1161, 1053, 1063, 932, 1604, 1130, 744, 930, 948, 1107, 1161, 1194, 1366, 1155, 785, 602, 903, 1142, 1410, 1256, 742, 985, 1037, 1067, 1196, 1412, 1127, 779, 911, 989, 946, 888, 1349, 1124, 761, 994, 1068, 971, 1157, 1558, 1223, 782, 2790, 1835, 1444, 1098, 1399, 1255, 950, 1110, 1345, 1224, 1092, 1446, 1210, 1122, 1259, 1181, 1035, 1325, 1481, 1278, 769, 911, 876, 877, 950, 1383, 980, 705, 888, 877, 638, 1065, 1142, 1090, 1316, 1270, 1048, 1256, 1009, 1175, 1176, 870, 856, 860])\n", 85 | "n_predict = 100\n", 86 | "extrapolation = fourierExtrapolation(x, n_predict)\n", 87 | "plt.plot(np.arange(0, x.size), x, 'b', label = 'x', linewidth = 3)\n", 88 | "plt.plot(np.arange(0, extrapolation.size), extrapolation, 'r', label = 'extrapolation')\n", 89 | "plt.legend()" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 4, 95 | "metadata": { 96 | "collapsed": false 97 | }, 98 | "outputs": [ 99 | { 100 | "data": { 101 | "text/plain": [ 102 | "" 103 | ] 104 | }, 105 | "execution_count": 4, 106 | "metadata": {}, 107 | "output_type": "execute_result" 108 | }, 109 | { 110 | "data": { 111 | "image/png": "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\n", 112 | "text/plain": [ 113 | "" 114 | ] 115 | }, 116 | "metadata": {}, 117 | "output_type": "display_data" 118 | } 119 | ], 120 | "source": [ 121 | "air_passengers = pd.read_csv('data/AirPassengers.csv')\n", 122 | "x = np.array(air_passengers['#Passengers'].values)\n", 123 | "n_predict = 300\n", 124 | "extrapolation = fourierExtrapolation(x, n_predict)\n", 125 | "plt.plot(np.arange(0, x.size), x, 'b', label = 'x', linewidth = 3)\n", 126 | "plt.plot(np.arange(0, extrapolation.size), extrapolation, 'r', label = 'extrapolation')\n", 127 | "plt.legend()" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": { 134 | "collapsed": true 135 | }, 136 | "outputs": [], 137 | "source": [] 138 | } 139 | ], 140 | "metadata": { 141 | "anaconda-cloud": {}, 142 | "kernelspec": { 143 | "display_name": "Python [Root]", 144 | "language": "python", 145 | "name": "Python [Root]" 146 | }, 147 | "language_info": { 148 | "codemirror_mode": { 149 | "name": "ipython", 150 | "version": 3 151 | }, 152 | "file_extension": ".py", 153 | "mimetype": "text/x-python", 154 | "name": "python", 155 | "nbconvert_exporter": "python", 156 | "pygments_lexer": "ipython3", 157 | "version": "3.5.2" 158 | }, 159 | "widgets": { 160 | "state": {}, 161 | "version": "1.1.1" 162 | } 163 | }, 164 | "nbformat": 4, 165 | "nbformat_minor": 0 166 | } 167 | -------------------------------------------------------------------------------- /10. Clustering & Classification.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "%matplotlib inline\n", 12 | "import matplotlib.pylab as plt\n", 13 | "\n", 14 | "from matplotlib.pylab import rcParams\n", 15 | "rcParams['figure.figsize'] = 15, 6\n", 16 | "\n", 17 | "from datetime import datetime\n", 18 | "from scipy.cluster.hierarchy import dendrogram, linkage\n", 19 | "import pandas as pd\n", 20 | "import numpy as np\n", 21 | "from sklearn.metrics.pairwise import pairwise_distances\n", 22 | "from math import sqrt\n", 23 | "from scipy.spatial.distance import squareform" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": { 30 | "collapsed": false 31 | }, 32 | "outputs": [], 33 | "source": [ 34 | "words = pd.read_csv('data/50words_TEST.csv', index_col = 0, header = None)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": { 41 | "collapsed": false 42 | }, 43 | "outputs": [], 44 | "source": [ 45 | "words.index" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "### Let's take a look at some of the words 'on average'" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": { 59 | "collapsed": false 60 | }, 61 | "outputs": [], 62 | "source": [ 63 | "for i in range(7):\n", 64 | " row = words.groupby(words.index).mean().iloc[i]\n", 65 | " row.plot()" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "### We can also check to see whether the 'average' matches the individual plot for a given type\n", 73 | "\n", 74 | "First, the 'average'" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": { 81 | "collapsed": false 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "word_type = 7\n", 86 | "row = words.groupby(words.index).mean().iloc[word_type-1]\n", 87 | "row.plot()" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": { 94 | "collapsed": false 95 | }, 96 | "outputs": [], 97 | "source": [ 98 | "word_type = 7\n", 99 | "row = words.groupby(words.index).median().iloc[word_type-1]\n", 100 | "row.plot()" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "Next the full sample of all those words" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": { 114 | "collapsed": false 115 | }, 116 | "outputs": [], 117 | "source": [ 118 | "for i in range(words[words.index == word_type].shape[0]):\n", 119 | " row = words[words.index == word_type].iloc[i]\n", 120 | " row.plot()" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "### Let's try to code up the sensible distance function to describe the distance between two times series" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": { 134 | "collapsed": true 135 | }, 136 | "outputs": [], 137 | "source": [ 138 | "# courtesy of http://alexminnaar.com/time-series-classification-and-clustering-with-python.html\n", 139 | "# %load snippets/dtwdistance.py" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": { 146 | "collapsed": false 147 | }, 148 | "outputs": [], 149 | "source": [ 150 | "chosen_words = words[words.index == word_type]\n", 151 | "s1 = chosen_words.iloc[2]\n", 152 | "s2 = chosen_words.iloc[3]\n", 153 | "print(type(s1))\n", 154 | "DTWDistance(s1.values, s2.values)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": null, 160 | "metadata": { 161 | "collapsed": false 162 | }, 163 | "outputs": [], 164 | "source": [ 165 | "s3 = words.iloc[0]\n", 166 | "DTWDistance(s1.values, s3.values)" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": { 173 | "collapsed": false 174 | }, 175 | "outputs": [], 176 | "source": [ 177 | "s3 = words.iloc[0]\n", 178 | "DTWDistance(s2.values, s3.values)" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": { 185 | "collapsed": false 186 | }, 187 | "outputs": [], 188 | "source": [ 189 | "plt.plot(s1)\n", 190 | "plt.plot(s2)\n", 191 | "plt.plot(s3)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "### Compare the performance of Euclidean distance with that of DTDW for s1, s2, s3 as specified above" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": { 205 | "collapsed": true 206 | }, 207 | "outputs": [], 208 | "source": [ 209 | "# %load snippets/euclidedistance.py" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": null, 215 | "metadata": { 216 | "collapsed": false 217 | }, 218 | "outputs": [], 219 | "source": [ 220 | "EuclidDistance(s1.values, s2.values)" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": null, 226 | "metadata": { 227 | "collapsed": false 228 | }, 229 | "outputs": [], 230 | "source": [ 231 | "EuclidDistance(s3.values, s2.values)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": { 238 | "collapsed": false 239 | }, 240 | "outputs": [], 241 | "source": [ 242 | "EuclidDistance(s1.values, s3.values)" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "### Can you classify a random row by determining which 'mean' curve it is closest to? How successful is this?" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": null, 255 | "metadata": { 256 | "collapsed": false 257 | }, 258 | "outputs": [], 259 | "source": [ 260 | "mean_curve = {}\n", 261 | "for j in range(1,len(set(words.index))):\n", 262 | " row = words[words.index == j].mean()\n", 263 | " mean_curve[j] = row" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": null, 269 | "metadata": { 270 | "collapsed": false 271 | }, 272 | "outputs": [], 273 | "source": [ 274 | "test_word = words[words.index == 5].iloc[3]" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": { 281 | "collapsed": false 282 | }, 283 | "outputs": [], 284 | "source": [ 285 | "distance_dict = {key:DTWDistance(test_word.values, value.values) for (key, value) in mean_curve.items() }\n" 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": null, 291 | "metadata": { 292 | "collapsed": false 293 | }, 294 | "outputs": [], 295 | "source": [ 296 | "from collections import OrderedDict\n", 297 | "\n", 298 | "OrderedDict(sorted(distance_dict.items(), key=lambda t: t[1]))" 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "metadata": {}, 304 | "source": [ 305 | "### Can you cluster the words using the DTW metric?" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": { 312 | "collapsed": true 313 | }, 314 | "outputs": [], 315 | "source": [ 316 | "# Yes, but this would take a really long time, so we're not going to do it" 317 | ] 318 | }, 319 | { 320 | "cell_type": "markdown", 321 | "metadata": {}, 322 | "source": [ 323 | "### Instead cluster with features" 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": { 330 | "collapsed": false 331 | }, 332 | "outputs": [], 333 | "source": [ 334 | "max_location = []\n", 335 | "first_local_max_location = []\n", 336 | "second_local_max_location = []\n", 337 | "num_inflections = []\n", 338 | "ratio_first_local_max_to_abs_max = []\n", 339 | "word_type = []\n", 340 | "\n", 341 | "def smooth(y, box_pts):\n", 342 | " box = np.ones(box_pts)/box_pts\n", 343 | " y_smooth = np.convolve(y, box, mode='same')\n", 344 | " return y_smooth\n", 345 | "\n", 346 | "for row in range(words.shape[1]):\n", 347 | " word_type.append(words.index[row])\n", 348 | " \n", 349 | " # locations of maximum, locations of first and second inflection points, number of inflection points\n", 350 | " w = words.iloc[row]\n", 351 | " \n", 352 | " # max point\n", 353 | " max_location.append(w.idxmax())\n", 354 | " \n", 355 | " # local maxima and minima\n", 356 | " w_arr = np.array(w)\n", 357 | " w_arr = smooth(w_arr, 10)\n", 358 | " \n", 359 | " lows = np.where(np.r_[True, w_arr[1:] < w_arr[:-1]] & np.r_[w_arr[:-1] < w_arr[1:], True])\n", 360 | " lows = lows[0]\n", 361 | " mask = ((265 > lows ) & (lows > 5))\n", 362 | " lows = lows[mask]\n", 363 | " \n", 364 | " highs = np.where(np.r_[True, w_arr[1:] > w_arr[:-1]] & np.r_[w_arr[:-1] > w_arr[1:], True])\n", 365 | " highs = highs[0]\n", 366 | " mask = ((265 > highs) & (highs > 5))\n", 367 | " highs = highs[mask]\n", 368 | " \n", 369 | " first_local_max_location.append(highs[0])\n", 370 | " second_local_max_location.append(highs[1])\n", 371 | "\n", 372 | " ratio_first_local_max_to_abs_max.append(w_arr[highs[0]]/w_arr[w.idxmax()])\n", 373 | " \n", 374 | " num_inflections.append(len(highs) + len(lows))" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": null, 380 | "metadata": { 381 | "collapsed": true 382 | }, 383 | "outputs": [], 384 | "source": [ 385 | "results = pd.DataFrame({'word_type' : word_type,\n", 386 | " 'max_location': max_location, \n", 387 | " 'first_local_max_location' : first_local_max_location,\n", 388 | " 'second_local_max_location' : second_local_max_location,\n", 389 | " 'num_inflections' : num_inflections,\n", 390 | " 'ratio_first_local_max_to_abs_max' : ratio_first_local_max_to_abs_max})" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": null, 396 | "metadata": { 397 | "collapsed": false 398 | }, 399 | "outputs": [], 400 | "source": [ 401 | "results.head()" 402 | ] 403 | }, 404 | { 405 | "cell_type": "code", 406 | "execution_count": null, 407 | "metadata": { 408 | "collapsed": true 409 | }, 410 | "outputs": [], 411 | "source": [ 412 | "from sklearn.cluster import KMeans" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": null, 418 | "metadata": { 419 | "collapsed": false 420 | }, 421 | "outputs": [], 422 | "source": [ 423 | "estimator = KMeans(n_clusters=50)\n", 424 | "estimator.fit(results.drop('word_type', axis=1))" 425 | ] 426 | }, 427 | { 428 | "cell_type": "code", 429 | "execution_count": null, 430 | "metadata": { 431 | "collapsed": false 432 | }, 433 | "outputs": [], 434 | "source": [ 435 | "results['labels'] = estimator.labels_" 436 | ] 437 | }, 438 | { 439 | "cell_type": "code", 440 | "execution_count": null, 441 | "metadata": { 442 | "collapsed": false 443 | }, 444 | "outputs": [], 445 | "source": [ 446 | "results[results.word_type == 5]" 447 | ] 448 | }, 449 | { 450 | "cell_type": "code", 451 | "execution_count": null, 452 | "metadata": { 453 | "collapsed": true 454 | }, 455 | "outputs": [], 456 | "source": [] 457 | } 458 | ], 459 | "metadata": { 460 | "anaconda-cloud": {}, 461 | "kernelspec": { 462 | "display_name": "Python [Root]", 463 | "language": "python", 464 | "name": "Python [Root]" 465 | }, 466 | "language_info": { 467 | "codemirror_mode": { 468 | "name": "ipython", 469 | "version": 3 470 | }, 471 | "file_extension": ".py", 472 | "mimetype": "text/x-python", 473 | "name": "python", 474 | "nbconvert_exporter": "python", 475 | "pygments_lexer": "ipython3", 476 | "version": "3.5.2" 477 | }, 478 | "widgets": { 479 | "state": {}, 480 | "version": "1.1.1" 481 | } 482 | }, 483 | "nbformat": 4, 484 | "nbformat_minor": 0 485 | } 486 | -------------------------------------------------------------------------------- /data/AirPassengers.csv: -------------------------------------------------------------------------------- 1 | Month,#Passengers 1949-01,112 1949-02,118 1949-03,132 1949-04,129 1949-05,121 1949-06,135 1949-07,148 1949-08,148 1949-09,136 1949-10,119 1949-11,104 1949-12,118 1950-01,115 1950-02,126 1950-03,141 1950-04,135 1950-05,125 1950-06,149 1950-07,170 1950-08,170 1950-09,158 1950-10,133 1950-11,114 1950-12,140 1951-01,145 1951-02,150 1951-03,178 1951-04,163 1951-05,172 1951-06,178 1951-07,199 1951-08,199 1951-09,184 1951-10,162 1951-11,146 1951-12,166 1952-01,171 1952-02,180 1952-03,193 1952-04,181 1952-05,183 1952-06,218 1952-07,230 1952-08,242 1952-09,209 1952-10,191 1952-11,172 1952-12,194 1953-01,196 1953-02,196 1953-03,236 1953-04,235 1953-05,229 1953-06,243 1953-07,264 1953-08,272 1953-09,237 1953-10,211 1953-11,180 1953-12,201 1954-01,204 1954-02,188 1954-03,235 1954-04,227 1954-05,234 1954-06,264 1954-07,302 1954-08,293 1954-09,259 1954-10,229 1954-11,203 1954-12,229 1955-01,242 1955-02,233 1955-03,267 1955-04,269 1955-05,270 1955-06,315 1955-07,364 1955-08,347 1955-09,312 1955-10,274 1955-11,237 1955-12,278 1956-01,284 1956-02,277 1956-03,317 1956-04,313 1956-05,318 1956-06,374 1956-07,413 1956-08,405 1956-09,355 1956-10,306 1956-11,271 1956-12,306 1957-01,315 1957-02,301 1957-03,356 1957-04,348 1957-05,355 1957-06,422 1957-07,465 1957-08,467 1957-09,404 1957-10,347 1957-11,305 1957-12,336 1958-01,340 1958-02,318 1958-03,362 1958-04,348 1958-05,363 1958-06,435 1958-07,491 1958-08,505 1958-09,404 1958-10,359 1958-11,310 1958-12,337 1959-01,360 1959-02,342 1959-03,406 1959-04,396 1959-05,420 1959-06,472 1959-07,548 1959-08,559 1959-09,463 1959-10,407 1959-11,362 1959-12,405 1960-01,417 1960-02,391 1960-03,419 1960-04,461 1960-05,472 1960-06,535 1960-07,622 1960-08,606 1960-09,508 1960-10,461 1960-11,390 1960-12,432 -------------------------------------------------------------------------------- /data/ao_monthly.txt: -------------------------------------------------------------------------------- 1 | 1950 1 -0.60310E-01 2 | 1950 2 0.62681E+00 3 | 1950 3 -0.81275E-02 4 | 1950 4 0.55510E+00 5 | 1950 5 0.71577E-01 6 | 1950 6 0.53857E+00 7 | 1950 7 -0.80248E+00 8 | 1950 8 -0.85101E+00 9 | 1950 9 0.35797E+00 10 | 1950 10 -0.37890E+00 11 | 1950 11 -0.51511E+00 12 | 1950 12 -0.19281E+01 13 | 1951 1 -0.84969E-01 14 | 1951 2 -0.39993E+00 15 | 1951 3 -0.19341E+01 16 | 1951 4 -0.77648E+00 17 | 1951 5 -0.86278E+00 18 | 1951 6 -0.91786E+00 19 | 1951 7 0.90023E-01 20 | 1951 8 -0.37741E+00 21 | 1951 9 -0.81778E+00 22 | 1951 10 -0.21291E+00 23 | 1951 11 -0.68519E-01 24 | 1951 12 0.19872E+01 25 | 1952 1 0.36825E+00 26 | 1952 2 -0.17472E+01 27 | 1952 3 -0.18595E+01 28 | 1952 4 0.53852E+00 29 | 1952 5 -0.77351E+00 30 | 1952 6 -0.44093E+00 31 | 1952 7 0.38308E+00 32 | 1952 8 -0.30367E-01 33 | 1952 9 -0.38345E+00 34 | 1952 10 -0.43717E+00 35 | 1952 11 -0.18909E+01 36 | 1952 12 -0.18267E+01 37 | 1953 1 -0.10362E+01 38 | 1953 2 -0.24930E+00 39 | 1953 3 0.10683E+01 40 | 1953 4 -0.12558E+01 41 | 1953 5 -0.56207E+00 42 | 1953 6 0.22535E-01 43 | 1953 7 0.33317E+00 44 | 1953 8 0.84960E-01 45 | 1953 9 0.66161E+00 46 | 1953 10 -0.19446E+00 47 | 1953 11 0.35360E+00 48 | 1953 12 0.57547E+00 49 | 1954 1 -0.14829E+00 50 | 1954 2 -0.18094E+00 51 | 1954 3 0.47572E+00 52 | 1954 4 0.51169E+00 53 | 1954 5 -0.16561E+01 54 | 1954 6 -0.26811E+00 55 | 1954 7 0.34089E+00 56 | 1954 8 -0.12241E+00 57 | 1954 9 0.30150E+00 58 | 1954 10 0.51257E+00 59 | 1954 11 -0.32835E+00 60 | 1954 12 0.55259E+00 61 | 1955 1 -0.11631E+01 62 | 1955 2 -0.15423E+01 63 | 1955 3 -0.15681E+01 64 | 1955 4 0.19423E+00 65 | 1955 5 0.24161E+00 66 | 1955 6 -0.26578E+00 67 | 1955 7 0.33194E+00 68 | 1955 8 0.76012E+00 69 | 1955 9 0.35676E+00 70 | 1955 10 0.99053E-01 71 | 1955 11 -0.13422E+01 72 | 1955 12 -0.44403E+00 73 | 1956 1 -0.12044E+01 74 | 1956 2 -0.20286E+01 75 | 1956 3 0.47036E+00 76 | 1956 4 -0.86753E+00 77 | 1956 5 0.13911E+01 78 | 1956 6 0.28014E+00 79 | 1956 7 -0.21460E+00 80 | 1956 8 -0.65221E+00 81 | 1956 9 -0.20195E+00 82 | 1956 10 0.11392E+01 83 | 1956 11 -0.66280E-01 84 | 1956 12 0.89139E-03 85 | 1957 1 0.20621E+01 86 | 1957 2 -0.15132E+01 87 | 1957 3 -0.20126E+01 88 | 1957 4 0.23766E+00 89 | 1957 5 -0.96610E+00 90 | 1957 6 -0.75999E+00 91 | 1957 7 -0.64620E+00 92 | 1957 8 0.96898E-01 93 | 1957 9 -0.95588E+00 94 | 1957 10 0.90314E+00 95 | 1957 11 -0.13800E+01 96 | 1957 12 0.82801E+00 97 | 1958 1 -0.14382E+01 98 | 1958 2 -0.22282E+01 99 | 1958 3 -0.25218E+01 100 | 1958 4 -0.36002E+00 101 | 1958 5 -0.33635E+00 102 | 1958 6 -0.11493E+01 103 | 1958 7 -0.68374E+00 104 | 1958 8 -0.75479E+00 105 | 1958 9 -0.12058E-01 106 | 1958 10 0.77009E+00 107 | 1958 11 -0.10675E-01 108 | 1958 12 -0.16865E+01 109 | 1959 1 -0.20128E+01 110 | 1959 2 0.25445E+01 111 | 1959 3 0.14318E+01 112 | 1959 4 0.11924E+00 113 | 1959 5 -0.34076E+00 114 | 1959 6 -0.33434E-01 115 | 1959 7 0.10472E+00 116 | 1959 8 -0.74521E+00 117 | 1959 9 -0.28076E+00 118 | 1959 10 -0.24905E+00 119 | 1959 11 -0.14106E+01 120 | 1959 12 -0.41950E-01 121 | 1960 1 -0.24842E+01 122 | 1960 2 -0.22124E+01 123 | 1960 3 -0.16246E+01 124 | 1960 4 -0.29731E+00 125 | 1960 5 -0.85743E+00 126 | 1960 6 0.54978E-01 127 | 1960 7 -0.61906E+00 128 | 1960 8 -0.10079E+01 129 | 1960 9 -0.38164E+00 130 | 1960 10 -0.11870E+01 131 | 1960 11 -0.55323E+00 132 | 1960 12 -0.34295E+00 133 | 1961 1 -0.15060E+01 134 | 1961 2 0.62115E+00 135 | 1961 3 0.34144E+00 136 | 1961 4 -0.23749E+00 137 | 1961 5 0.15748E+00 138 | 1961 6 0.83696E+00 139 | 1961 7 -0.10797E+00 140 | 1961 8 0.12693E-01 141 | 1961 9 0.81485E+00 142 | 1961 10 0.20308E+00 143 | 1961 11 -0.10438E-01 144 | 1961 12 -0.16682E+01 145 | 1962 1 0.16445E+01 146 | 1962 2 -0.35815E+00 147 | 1962 3 -0.28480E+01 148 | 1962 4 0.11692E+01 149 | 1962 5 0.67997E-01 150 | 1962 6 0.28707E+00 151 | 1962 7 -0.92651E+00 152 | 1962 8 0.15207E+00 153 | 1962 9 -0.55986E-01 154 | 1962 10 -0.15827E-01 155 | 1962 11 -0.11123E+01 156 | 1962 12 -0.71143E+00 157 | 1963 1 -0.33112E+01 158 | 1963 2 -0.17208E+01 159 | 1963 3 0.72422E+00 160 | 1963 4 -0.34769E+00 161 | 1963 5 0.77098E+00 162 | 1963 6 -0.58500E+00 163 | 1963 7 -0.30347E+00 164 | 1963 8 -0.62474E+00 165 | 1963 9 0.83110E-01 166 | 1963 10 0.10692E+01 167 | 1963 11 -0.41944E+00 168 | 1963 12 -0.11781E+01 169 | 1964 1 0.38463E+00 170 | 1964 2 -0.57491E+00 171 | 1964 3 -0.55817E+00 172 | 1964 4 0.66339E+00 173 | 1964 5 0.11740E+01 174 | 1964 6 0.14159E+00 175 | 1964 7 0.73418E+00 176 | 1964 8 -0.12066E+01 177 | 1964 9 -0.22718E+00 178 | 1964 10 0.34171E+00 179 | 1964 11 -0.34440E+00 180 | 1964 12 -0.24609E+00 181 | 1965 1 -0.10458E+01 182 | 1965 2 -0.20841E+01 183 | 1965 3 -0.90496E+00 184 | 1965 4 0.56812E+00 185 | 1965 5 -0.15253E+00 186 | 1965 6 0.37800E-01 187 | 1965 7 -0.50987E+00 188 | 1965 8 -0.25487E+00 189 | 1965 9 -0.69781E+00 190 | 1965 10 0.39367E+00 191 | 1965 11 -0.13412E+01 192 | 1965 12 0.16297E+00 193 | 1966 1 -0.32320E+01 194 | 1966 2 -0.14381E+01 195 | 1966 3 -0.91066E+00 196 | 1966 4 -0.18373E+01 197 | 1966 5 0.11243E+01 198 | 1966 6 0.40797E+00 199 | 1966 7 0.10944E-01 200 | 1966 8 -0.94527E+00 201 | 1966 9 0.11063E-01 202 | 1966 10 -0.10766E+01 203 | 1966 11 0.11056E+00 204 | 1966 12 -0.14015E+01 205 | 1967 1 -0.57592E+00 206 | 1967 2 0.11801E+01 207 | 1967 3 0.19668E+01 208 | 1967 4 0.16996E+01 209 | 1967 5 0.12651E+00 210 | 1967 6 0.64659E+00 211 | 1967 7 0.25926E+00 212 | 1967 8 -0.29302E+00 213 | 1967 9 0.13293E+00 214 | 1967 10 0.12986E+01 215 | 1967 11 0.33356E+00 216 | 1967 12 -0.34693E+00 217 | 1968 1 -0.40879E+00 218 | 1968 2 -0.21537E+01 219 | 1968 3 0.17408E+01 220 | 1968 4 0.32768E+00 221 | 1968 5 -0.24062E+00 222 | 1968 6 0.41966E+00 223 | 1968 7 -0.83611E+00 224 | 1968 8 -0.67063E+00 225 | 1968 9 -0.10089E+01 226 | 1968 10 -0.10132E+01 227 | 1968 11 -0.21826E+01 228 | 1968 12 -0.78317E+00 229 | 1969 1 -0.29675E+01 230 | 1969 2 -0.31135E+01 231 | 1969 3 -0.15822E+01 232 | 1969 4 0.43846E+00 233 | 1969 5 -0.72032E+00 234 | 1969 6 -0.34780E+00 235 | 1969 7 0.40951E+00 236 | 1969 8 -0.78176E+00 237 | 1969 9 -0.83420E-01 238 | 1969 10 0.97581E-01 239 | 1969 11 0.32577E+00 240 | 1969 12 -0.18556E+01 241 | 1970 1 -0.24124E+01 242 | 1970 2 -0.13253E+01 243 | 1970 3 -0.20841E+01 244 | 1970 4 0.30205E+00 245 | 1970 5 0.53057E+00 246 | 1970 6 0.87539E+00 247 | 1970 7 0.13865E+00 248 | 1970 8 -0.26255E+00 249 | 1970 9 0.29661E-01 250 | 1970 10 0.98180E-01 251 | 1970 11 0.37838E+00 252 | 1970 12 -0.39915E+00 253 | 1971 1 -0.16273E+00 254 | 1971 2 -0.92190E+00 255 | 1971 3 -0.10907E+01 256 | 1971 4 -0.58343E+00 257 | 1971 5 0.67926E+00 258 | 1971 6 -0.66827E+00 259 | 1971 7 -0.57847E+00 260 | 1971 8 0.81753E+00 261 | 1971 9 0.15341E+00 262 | 1971 10 0.11847E+01 263 | 1971 11 0.41883E+00 264 | 1971 12 0.82387E+00 265 | 1972 1 0.16650E+00 266 | 1972 2 -0.19542E+00 267 | 1972 3 -0.14068E+00 268 | 1972 4 0.10074E+01 269 | 1972 5 0.14023E+00 270 | 1972 6 -0.49071E-01 271 | 1972 7 -0.55291E+00 272 | 1972 8 -0.82042E-01 273 | 1972 9 -0.91956E+00 274 | 1972 10 0.39177E+00 275 | 1972 11 -0.38032E+00 276 | 1972 12 0.12375E+01 277 | 1973 1 0.12318E+01 278 | 1973 2 0.78621E+00 279 | 1973 3 0.53717E+00 280 | 1973 4 -0.11257E+01 281 | 1973 5 0.73456E-01 282 | 1973 6 0.53116E+00 283 | 1973 7 0.27047E+00 284 | 1973 8 0.31251E+00 285 | 1973 9 0.11416E+00 286 | 1973 10 0.33710E+00 287 | 1973 11 0.22447E-02 288 | 1973 12 -0.18148E+00 289 | 1974 1 0.23216E+00 290 | 1974 2 -0.48927E+00 291 | 1974 3 -0.74628E+00 292 | 1974 4 0.30882E+00 293 | 1974 5 -0.50704E+00 294 | 1974 6 -0.47510E-01 295 | 1974 7 0.38996E+00 296 | 1974 8 -0.53337E+00 297 | 1974 9 -0.13579E+00 298 | 1974 10 -0.10239E+01 299 | 1974 11 -0.43475E+00 300 | 1974 12 0.55645E+00 301 | 1975 1 0.15945E+01 302 | 1975 2 0.19446E+00 303 | 1975 3 0.15120E+00 304 | 1975 4 0.40878E+00 305 | 1975 5 -0.61433E+00 306 | 1975 6 -0.32323E+00 307 | 1975 7 0.34529E+00 308 | 1975 8 0.13004E+00 309 | 1975 9 0.12783E+01 310 | 1975 10 0.13771E+00 311 | 1975 11 0.61870E+00 312 | 1975 12 0.12898E+01 313 | 1976 1 0.34333E-01 314 | 1976 2 0.16563E+01 315 | 1976 3 0.58709E+00 316 | 1976 4 0.43968E+00 317 | 1976 5 0.59626E-01 318 | 1976 6 0.32800E+00 319 | 1976 7 -0.32529E+00 320 | 1976 8 0.55859E+00 321 | 1976 9 -0.74252E+00 322 | 1976 10 -0.80412E+00 323 | 1976 11 -0.87349E-01 324 | 1976 12 -0.20743E+01 325 | 1977 1 -0.37671E+01 326 | 1977 2 -0.20105E+01 327 | 1977 3 0.34446E+00 328 | 1977 4 0.13285E+01 329 | 1977 5 0.10432E+00 330 | 1977 6 -0.22616E+00 331 | 1977 7 -0.49173E+00 332 | 1977 8 -0.14122E+01 333 | 1977 9 0.58648E+00 334 | 1977 10 -0.91780E-02 335 | 1977 11 0.60528E+00 336 | 1977 12 -0.23965E+00 337 | 1978 1 -0.34696E+00 338 | 1978 2 -0.30136E+01 339 | 1978 3 0.50191E+00 340 | 1978 4 -0.96708E+00 341 | 1978 5 0.59049E-01 342 | 1978 6 0.63464E+00 343 | 1978 7 -0.60399E+00 344 | 1978 8 -0.35366E+00 345 | 1978 9 -0.98999E-01 346 | 1978 10 0.89460E+00 347 | 1978 11 0.24695E+01 348 | 1978 12 -0.98014E+00 349 | 1979 1 -0.22328E+01 350 | 1979 2 -0.69671E+00 351 | 1979 3 -0.81414E+00 352 | 1979 4 -0.11568E+01 353 | 1979 5 -0.25009E+00 354 | 1979 6 0.93316E+00 355 | 1979 7 0.38511E-01 356 | 1979 8 -0.68413E+00 357 | 1979 9 -0.45949E-01 358 | 1979 10 -0.12434E+01 359 | 1979 11 0.47508E+00 360 | 1979 12 0.12948E+01 361 | 1980 1 -0.20657E+01 362 | 1980 2 -0.93372E+00 363 | 1980 3 -0.14333E+01 364 | 1980 4 -0.41913E+00 365 | 1980 5 -0.11548E+01 366 | 1980 6 0.72149E+00 367 | 1980 7 -0.62221E+00 368 | 1980 8 -0.18519E+00 369 | 1980 9 0.31262E+00 370 | 1980 10 -0.52121E+00 371 | 1980 11 -0.13610E+01 372 | 1980 12 -0.57300E-01 373 | 1981 1 -0.11634E+00 374 | 1981 2 -0.33158E+00 375 | 1981 3 -0.16447E+01 376 | 1981 4 0.43041E+00 377 | 1981 5 0.17956E+00 378 | 1981 6 -0.43793E+00 379 | 1981 7 0.56055E+00 380 | 1981 8 -0.24411E+00 381 | 1981 9 -0.10401E+01 382 | 1981 10 -0.11675E+01 383 | 1981 11 -0.18767E+00 384 | 1981 12 -0.12157E+01 385 | 1982 1 -0.88341E+00 386 | 1982 2 0.97391E+00 387 | 1982 3 0.10741E+01 388 | 1982 4 0.14538E+01 389 | 1982 5 -0.20870E+00 390 | 1982 6 -0.11801E+01 391 | 1982 7 0.47753E-02 392 | 1982 8 0.36223E+00 393 | 1982 9 0.55772E+00 394 | 1982 10 -0.21098E+00 395 | 1982 11 0.66093E+00 396 | 1982 12 0.96718E+00 397 | 1983 1 0.13591E+01 398 | 1983 2 -0.18059E+01 399 | 1983 3 -0.56707E+00 400 | 1983 4 -0.73776E+00 401 | 1983 5 -0.44093E+00 402 | 1983 6 0.31253E+00 403 | 1983 7 0.13055E+00 404 | 1983 8 0.10978E+01 405 | 1983 9 0.16689E+00 406 | 1983 10 0.13689E+01 407 | 1983 11 -0.68793E+00 408 | 1983 12 0.18625E+00 409 | 1984 1 0.90504E+00 410 | 1984 2 -0.30272E+00 411 | 1984 3 -0.23860E+01 412 | 1984 4 -0.28359E+00 413 | 1984 5 0.47918E+00 414 | 1984 6 0.72895E-02 415 | 1984 7 0.18871E-01 416 | 1984 8 0.46569E+00 417 | 1984 9 -0.41276E+00 418 | 1984 10 -0.27026E+00 419 | 1984 11 -0.96587E+00 420 | 1984 12 0.44600E+00 421 | 1985 1 -0.28057E+01 422 | 1985 2 -0.14398E+01 423 | 1985 3 0.55144E+00 424 | 1985 4 0.65242E+00 425 | 1985 5 -0.43221E+00 426 | 1985 6 -0.34656E+00 427 | 1985 7 -0.38958E+00 428 | 1985 8 -0.14289E-02 429 | 1985 9 0.11441E+00 430 | 1985 10 0.10351E+01 431 | 1985 11 -0.12175E+01 432 | 1985 12 -0.19476E+01 433 | 1986 1 -0.56764E+00 434 | 1986 2 -0.29041E+01 435 | 1986 3 0.19308E+01 436 | 1986 4 0.10299E+00 437 | 1986 5 0.36687E+00 438 | 1986 6 0.53457E+00 439 | 1986 7 -0.82585E-02 440 | 1986 8 -0.82629E+00 441 | 1986 9 -0.23385E-01 442 | 1986 10 0.14246E+01 443 | 1986 11 0.92572E+00 444 | 1986 12 0.59768E-01 445 | 1987 1 -0.11476E+01 446 | 1987 2 -0.14732E+01 447 | 1987 3 -0.17465E+01 448 | 1987 4 0.38697E+00 449 | 1987 5 0.32524E+00 450 | 1987 6 -0.71027E+00 451 | 1987 7 -0.46627E+00 452 | 1987 8 -0.83570E+00 453 | 1987 9 0.28653E+00 454 | 1987 10 -0.80009E-01 455 | 1987 11 -0.53584E+00 456 | 1987 12 -0.53391E+00 457 | 1988 1 0.26466E+00 458 | 1988 2 -0.10662E+01 459 | 1988 3 -0.19707E+00 460 | 1988 4 -0.56071E+00 461 | 1988 5 -0.84614E+00 462 | 1988 6 0.60528E-01 463 | 1988 7 -0.14337E+00 464 | 1988 8 0.25457E+00 465 | 1988 9 0.10393E+01 466 | 1988 10 0.32359E-01 467 | 1988 11 -0.34655E-01 468 | 1988 12 0.16788E+01 469 | 1989 1 0.31060E+01 470 | 1989 2 0.32793E+01 471 | 1989 3 0.15303E+01 472 | 1989 4 -0.25024E+00 473 | 1989 5 0.88883E+00 474 | 1989 6 0.34498E+00 475 | 1989 7 0.86555E+00 476 | 1989 8 0.55090E+00 477 | 1989 9 0.70313E+00 478 | 1989 10 0.99069E+00 479 | 1989 11 0.33782E-01 480 | 1989 12 -0.64365E+00 481 | 1990 1 0.10007E+01 482 | 1990 2 0.34016E+01 483 | 1990 3 0.29900E+01 484 | 1990 4 0.18788E+01 485 | 1990 5 0.94282E+00 486 | 1990 6 0.30430E+00 487 | 1990 7 -0.29581E+00 488 | 1990 8 -0.18024E+00 489 | 1990 9 -0.21040E+00 490 | 1990 10 0.66034E+00 491 | 1990 11 0.52064E+00 492 | 1990 12 0.12767E+01 493 | 1991 1 0.72323E+00 494 | 1991 2 -0.87599E+00 495 | 1991 3 -0.52680E+00 496 | 1991 4 0.53021E+00 497 | 1991 5 0.48649E+00 498 | 1991 6 -0.11536E+00 499 | 1991 7 -0.18797E+00 500 | 1991 8 0.79688E+00 501 | 1991 9 -0.11221E+00 502 | 1991 10 -0.25195E+00 503 | 1991 11 0.28465E+00 504 | 1991 12 0.16132E+01 505 | 1992 1 0.55003E+00 506 | 1992 2 0.11217E+01 507 | 1992 3 0.98423E+00 508 | 1992 4 -0.52053E+00 509 | 1992 5 0.13414E+01 510 | 1992 6 -0.30196E+00 511 | 1992 7 0.19113E+00 512 | 1992 8 0.53534E+00 513 | 1992 9 -0.64030E+00 514 | 1992 10 -0.36589E+00 515 | 1992 11 0.71699E+00 516 | 1992 12 0.16267E+01 517 | 1993 1 0.34953E+01 518 | 1993 2 0.18450E+00 519 | 1993 3 0.76435E+00 520 | 1993 4 -0.43545E+00 521 | 1993 5 -0.16075E+01 522 | 1993 6 -0.51951E+00 523 | 1993 7 -0.51070E+00 524 | 1993 8 -0.39299E+00 525 | 1993 9 -0.36063E+00 526 | 1993 10 -0.56501E+00 527 | 1993 11 0.10018E+01 528 | 1993 12 -0.10412E+00 529 | 1994 1 -0.28785E+00 530 | 1994 2 -0.86154E+00 531 | 1994 3 0.18810E+01 532 | 1994 4 0.22474E+00 533 | 1994 5 -0.11545E+00 534 | 1994 6 0.16063E+01 535 | 1994 7 0.35074E+00 536 | 1994 8 0.82753E+00 537 | 1994 9 -0.84055E-01 538 | 1994 10 0.17403E+00 539 | 1994 11 0.17794E+01 540 | 1994 12 0.89383E+00 541 | 1995 1 -0.15377E+00 542 | 1995 2 0.14289E+01 543 | 1995 3 0.39323E+00 544 | 1995 4 -0.96313E+00 545 | 1995 5 -0.89120E+00 546 | 1995 6 -0.11182E+00 547 | 1995 7 -0.21708E+00 548 | 1995 8 0.54359E+00 549 | 1995 9 -0.54903E+00 550 | 1995 10 0.75041E-01 551 | 1995 11 -0.72327E+00 552 | 1995 12 -0.21271E+01 553 | 1996 1 -0.12004E+01 554 | 1996 2 0.16321E+00 555 | 1996 3 -0.14832E+01 556 | 1996 4 -0.15251E+01 557 | 1996 5 -0.22642E+00 558 | 1996 6 0.49673E+00 559 | 1996 7 0.71457E+00 560 | 1996 8 0.12471E+00 561 | 1996 9 -0.11400E+01 562 | 1996 10 0.18253E+00 563 | 1996 11 0.13637E+00 564 | 1996 12 -0.17208E+01 565 | 1997 1 -0.45677E+00 566 | 1997 2 0.18887E+01 567 | 1997 3 0.10908E+01 568 | 1997 4 0.32363E+00 569 | 1997 5 -0.96113E+00 570 | 1997 6 -0.81499E+00 571 | 1997 7 -0.43061E+00 572 | 1997 8 0.12062E+00 573 | 1997 9 0.19451E+00 574 | 1997 10 -0.69971E+00 575 | 1997 11 -0.66113E+00 576 | 1997 12 -0.71116E-01 577 | 1998 1 -0.20806E+01 578 | 1998 2 -0.18318E+00 579 | 1998 3 -0.25442E+00 580 | 1998 4 -0.37912E-01 581 | 1998 5 0.42864E+00 582 | 1998 6 -0.71073E+00 583 | 1998 7 -0.21167E+00 584 | 1998 8 0.65033E+00 585 | 1998 9 -0.10499E+01 586 | 1998 10 0.29433E+00 587 | 1998 11 -0.14494E+01 588 | 1998 12 0.13534E+01 589 | 1999 1 0.11035E+00 590 | 1999 2 0.48213E+00 591 | 1999 3 -0.14916E+01 592 | 1999 4 0.28445E+00 593 | 1999 5 0.22587E+00 594 | 1999 6 0.70703E+00 595 | 1999 7 -0.20418E-02 596 | 1999 8 -0.67215E+00 597 | 1999 9 0.59078E-01 598 | 1999 10 -0.58023E-02 599 | 1999 11 0.61094E+00 600 | 1999 12 0.10431E+01 601 | 2000 1 0.12702E+01 602 | 2000 2 0.10758E+01 603 | 2000 3 -0.45136E+00 604 | 2000 4 -0.27852E+00 605 | 2000 5 0.96909E+00 606 | 2000 6 0.58610E+00 607 | 2000 7 -0.64943E+00 608 | 2000 8 0.14389E+00 609 | 2000 9 0.39486E+00 610 | 2000 10 0.31678E+00 611 | 2000 11 -0.15815E+01 612 | 2000 12 -0.23544E+01 613 | 2001 1 -0.95883E+00 614 | 2001 2 -0.62241E+00 615 | 2001 3 -0.16865E+01 616 | 2001 4 0.90598E+00 617 | 2001 5 0.45196E+00 618 | 2001 6 -0.15338E-01 619 | 2001 7 -0.30988E-01 620 | 2001 8 0.52050E+00 621 | 2001 9 -0.70660E+00 622 | 2001 10 0.70747E+00 623 | 2001 11 0.81865E+00 624 | 2001 12 -0.13224E+01 625 | 2002 1 0.13813E+01 626 | 2002 2 0.13035E+01 627 | 2002 3 0.90200E+00 628 | 2002 4 0.74841E+00 629 | 2002 5 0.40136E+00 630 | 2002 6 0.57274E+00 631 | 2002 7 0.32764E+00 632 | 2002 8 -0.22853E+00 633 | 2002 9 -0.42744E-01 634 | 2002 10 -0.14885E+01 635 | 2002 11 -0.14251E+01 636 | 2002 12 -0.15921E+01 637 | 2003 1 -0.47167E+00 638 | 2003 2 0.12780E+00 639 | 2003 3 0.93297E+00 640 | 2003 4 -0.17811E+00 641 | 2003 5 0.10167E+01 642 | 2003 6 -0.10212E+00 643 | 2003 7 0.75316E-01 644 | 2003 8 -0.28037E+00 645 | 2003 9 0.46658E+00 646 | 2003 10 -0.66981E+00 647 | 2003 11 0.64242E+00 648 | 2003 12 0.26521E+00 649 | 2004 1 -0.16858E+01 650 | 2004 2 -0.15285E+01 651 | 2004 3 0.31806E+00 652 | 2004 4 -0.40938E+00 653 | 2004 5 -0.94252E-01 654 | 2004 6 -0.23587E+00 655 | 2004 7 -0.20054E+00 656 | 2004 8 -0.72019E+00 657 | 2004 9 0.85501E+00 658 | 2004 10 -0.51542E+00 659 | 2004 11 0.67827E+00 660 | 2004 12 0.12301E+01 661 | 2005 1 0.35617E+00 662 | 2005 2 -0.12706E+01 663 | 2005 3 -0.13479E+01 664 | 2005 4 -0.46214E-01 665 | 2005 5 -0.76336E+00 666 | 2005 6 -0.38324E+00 667 | 2005 7 -0.30247E-01 668 | 2005 8 0.26141E-01 669 | 2005 9 0.80239E+00 670 | 2005 10 0.29768E-01 671 | 2005 11 0.22769E+00 672 | 2005 12 -0.21039E+01 673 | 2006 1 -0.17047E+00 674 | 2006 2 -0.15577E+00 675 | 2006 3 -0.16038E+01 676 | 2006 4 0.13833E+00 677 | 2006 5 0.15581E+00 678 | 2006 6 0.10708E+01 679 | 2006 7 0.10270E+00 680 | 2006 8 -0.26525E+00 681 | 2006 9 0.60649E+00 682 | 2006 10 -0.10291E+01 683 | 2006 11 0.52131E+00 684 | 2006 12 0.22817E+01 685 | 2007 1 0.20338E+01 686 | 2007 2 -0.13069E+01 687 | 2007 3 0.11821E+01 688 | 2007 4 0.54427E+00 689 | 2007 5 0.89367E+00 690 | 2007 6 -0.55496E+00 691 | 2007 7 -0.39652E+00 692 | 2007 8 -0.33738E-01 693 | 2007 9 0.17892E+00 694 | 2007 10 0.38348E+00 695 | 2007 11 -0.51866E+00 696 | 2007 12 0.82113E+00 697 | 2008 1 0.81896E+00 698 | 2008 2 0.93807E+00 699 | 2008 3 0.58559E+00 700 | 2008 4 -0.45501E+00 701 | 2008 5 -0.12047E+01 702 | 2008 6 -0.89780E-01 703 | 2008 7 -0.47992E+00 704 | 2008 8 -0.80482E-01 705 | 2008 9 -0.32657E+00 706 | 2008 10 0.16758E+01 707 | 2008 11 0.92205E-01 708 | 2008 12 0.64778E+00 709 | 2009 1 0.79975E+00 710 | 2009 2 -0.67230E+00 711 | 2009 3 0.12134E+00 712 | 2009 4 0.97253E+00 713 | 2009 5 0.11937E+01 714 | 2009 6 -0.13507E+01 715 | 2009 7 -0.13559E+01 716 | 2009 8 -0.53666E-01 717 | 2009 9 0.87451E+00 718 | 2009 10 -0.15399E+01 719 | 2009 11 0.45885E+00 720 | 2009 12 -0.34128E+01 721 | 2010 1 -0.25868E+01 722 | 2010 2 -0.42657E+01 723 | 2010 3 -0.43208E+00 724 | 2010 4 -0.27450E+00 725 | 2010 5 -0.91864E+00 726 | 2010 6 -0.13004E-01 727 | 2010 7 0.43527E+00 728 | 2010 8 -0.11660E+00 729 | 2010 9 -0.86464E+00 730 | 2010 10 -0.46697E+00 731 | 2010 11 -0.37575E+00 732 | 2010 12 -0.26310E+01 733 | 2011 1 -0.16831E+01 734 | 2011 2 0.15754E+01 735 | 2011 3 0.14241E+01 736 | 2011 4 0.22748E+01 737 | 2011 5 -0.35093E-01 738 | 2011 6 -0.85775E+00 739 | 2011 7 -0.47162E+00 740 | 2011 8 -0.10626E+01 741 | 2011 9 0.66474E+00 742 | 2011 10 0.79975E+00 743 | 2011 11 0.14592E+01 744 | 2011 12 0.22208E+01 745 | 2012 1 -0.21966E+00 746 | 2012 2 -0.36335E-01 747 | 2012 3 0.10371E+01 748 | 2012 4 -0.34571E-01 749 | 2012 5 0.16841E+00 750 | 2012 6 -0.67241E+00 751 | 2012 7 0.16779E+00 752 | 2012 8 0.13999E-01 753 | 2012 9 0.77225E+00 754 | 2012 10 -0.15140E+01 755 | 2012 11 -0.11057E+00 756 | 2012 12 -0.17486E+01 757 | 2013 1 -0.60952E+00 758 | 2013 2 -0.10074E+01 759 | 2013 3 -0.31854E+01 760 | 2013 4 0.32221E+00 761 | 2013 5 0.49401E+00 762 | 2013 6 0.54865E+00 763 | 2013 7 -0.11112E-01 764 | 2013 8 0.15425E+00 765 | 2013 9 -0.46088E+00 766 | 2013 10 0.26276E+00 767 | 2013 11 0.20290E+01 768 | 2013 12 0.14749E+01 769 | 2014 1 -0.96876E+00 770 | 2014 2 0.43775E-01 771 | 2014 3 0.12058E+01 772 | 2014 4 0.97197E+00 773 | 2014 5 0.46421E+00 774 | 2014 6 -0.50745E+00 775 | 2014 7 -0.48894E+00 776 | 2014 8 -0.37154E+00 777 | 2014 9 0.10191E+00 778 | 2014 10 -0.11344E+01 779 | 2014 11 -0.53030E+00 780 | 2014 12 0.41292E+00 781 | 2015 1 0.10916E+01 782 | 2015 2 0.10426E+01 783 | 2015 3 0.18374E+01 784 | 2015 4 0.12157E+01 785 | 2015 5 0.76276E+00 786 | 2015 6 0.42704E+00 787 | 2015 7 -0.11079E+01 788 | 2015 8 -0.68902E+00 789 | 2015 9 -0.16451E+00 790 | 2015 10 -0.25006E+00 791 | 2015 11 0.19450E+01 792 | 2015 12 0.14441E+01 793 | 2016 1 -0.14487E+01 794 | 2016 2 -0.23521E-01 795 | 2016 3 0.28024E+00 796 | 2016 4 -0.10511E+01 797 | 2016 5 -0.35739E-01 798 | 2016 6 0.31288E+00 799 | -------------------------------------------------------------------------------- /readtime.py: -------------------------------------------------------------------------------- 1 | data = pd.read_fwf('data/ao_monthly.txt', header = None, index_col = 0, parse_dates = [[0, 1]], infer_datetime_format = True) -------------------------------------------------------------------------------- /snippets/6_acf_def.py: -------------------------------------------------------------------------------- 1 | """ 2 | Autocorrelation, also known as serial correlation, is the correlation of a signal with itself at different points in time. Informally, it is the similarity between observations as a function of the time lag between them. 3 | """ 4 | 5 | pd.Series(acf(air_passengers.Passengers, nlags = 36)).plot() 6 | -------------------------------------------------------------------------------- /snippets/6_acf_over_time.py: -------------------------------------------------------------------------------- 1 | air_passengers.rolling(window = 20).apply(lambda x: acf(x, nlags = 10)[10]).plot() 2 | -------------------------------------------------------------------------------- /snippets/6_ad_test_desc.py: -------------------------------------------------------------------------------- 1 | print(""" 2 | The null hypothesis of the Augmented Dickey-Fuller is that there is a unit root, with the alternative that there is no unit root. If the pvalue is above a critical size, then we cannot reject that there is a unit root. 3 | 4 | Rejecting that there is a unit root -> time series is stationary. 5 | """) 6 | -------------------------------------------------------------------------------- /snippets/6_multi_vs_add.pu: -------------------------------------------------------------------------------- 1 | """ 2 | The additive model is most appropriate if the magnitude of the seasonal fluctuations or the variation around the trend-cycle does not vary with the level of the time series. When the variation in the seasonal pattern, or the variation around the trend-cycle, appears to be proportional to the level of the time series, then a multiplicative model is more appropriate. With economic time series, multiplicative models are common. 3 | """ -------------------------------------------------------------------------------- /snippets/6_multi_vs_add.py: -------------------------------------------------------------------------------- 1 | """ 2 | The additive model is most appropriate if the magnitude of the seasonal fluctuations or the variation around the trend-cycle does not vary with the level of the time series. When the variation in the seasonal pattern, or the variation around the trend-cycle, appears to be proportional to the level of the time series, then a multiplicative model is more appropriate. With economic time series, multiplicative models are common. 3 | """ 4 | -------------------------------------------------------------------------------- /snippets/6_pd.py: -------------------------------------------------------------------------------- 1 | air_passengers = air_passengers.to_period() 2 | -------------------------------------------------------------------------------- /snippets/6_var.py: -------------------------------------------------------------------------------- 1 | air_passengers.rolling(window = 20).var().plot() 2 | -------------------------------------------------------------------------------- /snippets/7_diff2.py: -------------------------------------------------------------------------------- 1 | log_air_passengers_diff_2 = log_air_passengers_diff - log_air_passengers_diff.shift() 2 | fig, ax = plt.subplots() 3 | ax.set_color_cycle(['red', 'blue']) 4 | plt.plot(log_air_passengers_diff) 5 | plt.plot(log_air_passengers_diff_2) 6 | plt.legend(loc = 'best') 7 | -------------------------------------------------------------------------------- /snippets/7ma.py: -------------------------------------------------------------------------------- 1 | def ma1(theta = .5, n = 100): 2 | time_series = [] 3 | error = np.random.randn(n) 4 | for period in range(1,n): 5 | time_series.append(error[period] + theta*error[period-1]) 6 | return pd.Series(time_series[1:], index = range(1,n-1)) 7 | -------------------------------------------------------------------------------- /snippets/ambig.py: -------------------------------------------------------------------------------- 1 | rng_hourly.tz_localize('US/Central', ambiguous = 'infer') -------------------------------------------------------------------------------- /snippets/changerep.py: -------------------------------------------------------------------------------- 1 | data.to_period() -------------------------------------------------------------------------------- /snippets/confirm.py: -------------------------------------------------------------------------------- 1 | rng_hourly.tz_localize('US/Central', ambiguous = 'infer').tz_convert('utc') -------------------------------------------------------------------------------- /snippets/custom_rolling.py: -------------------------------------------------------------------------------- 1 | df.rolling(window = 10, center = False).apply(lambda x: x[1]/x[2])[1:10] -------------------------------------------------------------------------------- /snippets/custom_rolling2.py: -------------------------------------------------------------------------------- 1 | df['A'].plot(color = 'gray') 2 | df.rolling(window = 10, center = False)['A'].apply(lambda x: x[1]/x[2]).plot(color = 'red') 3 | -------------------------------------------------------------------------------- /snippets/daterange.py: -------------------------------------------------------------------------------- 1 | print(min(data.index)) 2 | print(max(data.index)) -------------------------------------------------------------------------------- /snippets/dtwdistance.py: -------------------------------------------------------------------------------- 1 | def DTWDistance(s1, s2): 2 | DTW={} 3 | 4 | for i in range(len(s1)): 5 | DTW[(i, -1)] = float('inf') 6 | for i in range(len(s2)): 7 | DTW[(-1, i)] = float('inf') 8 | DTW[(-1, -1)] = 0 9 | 10 | for i in range(len(s1)): 11 | for j in range(len(s2)): 12 | dist= (s1[i]-s2[j])**2 13 | DTW[(i, j)] = dist + min(DTW[(i-1, j)],DTW[(i, j-1)], DTW[(i-1, j-1)]) 14 | 15 | return sqrt(DTW[len(s1)-1, len(s2)-1]) -------------------------------------------------------------------------------- /snippets/euclidedistance.py: -------------------------------------------------------------------------------- 1 | def EuclidDistance(s1, s2): 2 | sum_squares = 0 3 | for i in range(len(s1)): 4 | sum_squares = sum_squares + (s1[i] - s2[i])**2 5 | return sqrt(sum_squares) -------------------------------------------------------------------------------- /snippets/offset_aliases.py: -------------------------------------------------------------------------------- 1 | pd.date_range(start, periods=10, freq='2h20min') 2 | -------------------------------------------------------------------------------- /snippets/prac1.py: -------------------------------------------------------------------------------- 1 | f['2012-07':'2012-08'][['High', 'Low']].plot() -------------------------------------------------------------------------------- /snippets/prac2.py: -------------------------------------------------------------------------------- 1 | r = f.rolling(50).var()['Volume'].plot() -------------------------------------------------------------------------------- /snippets/prac3.py: -------------------------------------------------------------------------------- 1 | r = f.expanding().var()['Volume'].plot() -------------------------------------------------------------------------------- /snippets/prac4.py: -------------------------------------------------------------------------------- 1 | lagged = f.shift(1) 2 | sum((f - lagged)['Open'] > 0) 3 | f['DayGain'] = f['Open'] - lagged['Open'] 4 | sum(f['DayGain'] > 0)/len(f['DayGain']) -------------------------------------------------------------------------------- /snippets/prac5.py: -------------------------------------------------------------------------------- 1 | f.rolling(window = 25)['DayGain'].apply(lambda x: len([x_i for x_i in x if x_i > 0])/len(x)).plot() -------------------------------------------------------------------------------- /snippets/prac6.py: -------------------------------------------------------------------------------- 1 | f.resample('M').mean()['High'].plot() -------------------------------------------------------------------------------- /snippets/prac7.py: -------------------------------------------------------------------------------- 1 | volume = f.Volume 2 | volume_lagged = f.Volume.shift() 3 | diffed_volume = volume - volume_lagged 4 | diffed_volume.rolling(window = 20).var().plot() -------------------------------------------------------------------------------- /snippets/prac8.py: -------------------------------------------------------------------------------- 1 | pd.DataFrame({'real':f.Volume, 'lagged':f.Volume.shift()}).corr() -------------------------------------------------------------------------------- /snippets/readtime.py: -------------------------------------------------------------------------------- 1 | data = pd.read_fwf('data/ao_monthly.txt', header = None, index_col = 0, parse_dates = [[0, 1]], infer_datetime_format = True) -------------------------------------------------------------------------------- /snippets/resampling_end.py: -------------------------------------------------------------------------------- 1 | # 1 2 | # method = 'None' 3 | # do this perhaps to join to other temporal data 4 | 5 | # 2 6 | # asfreq is more rigid 7 | 8 | # 3 9 | converted.asfreq('10Min', method = None).fillna(method = 'ffill', limit =3) 10 | 11 | # 4 12 | # It's basically like a groupby operation 13 | -------------------------------------------------------------------------------- /snippets/shift_future.py: -------------------------------------------------------------------------------- 1 | ts = pd.Series(np.random.randn(20), pd.date_range('7/1/16', freq = 'D', periods = 20)) 2 | ts_lagged = ts.shift(-1) 3 | plt.plot(ts, color = 'blue') 4 | plt.plot(ts_lagged, color = 'red') -------------------------------------------------------------------------------- /snippets/startend.py: -------------------------------------------------------------------------------- 1 | p = pd.Period('2016-07') 2 | p.start_time 3 | p.end_time -------------------------------------------------------------------------------- /snippets/try1.py: -------------------------------------------------------------------------------- 1 | t1 = pd.to_datetime('2016-06-18 12:15pm', dayfirst = True).strftime(format = '%Y/%M/%D') 2 | 3 | t2 = pd.Timestamp('2016-06-18 12:15pm').strftime(format = '%Y/%M/%D') -------------------------------------------------------------------------------- /snippets/window_funcs_try.py: -------------------------------------------------------------------------------- 1 | #1 2 | ts = pd.Series(np.random.randn(1000), index = pd.date_range(start = '1/1/16', periods = 1000, freq = 'D')) 3 | ts.ewm(span = 60, freq = 'D', min_periods = 0, adjust = True).mean().plot() 4 | ts.rolling(window = 60).mean().plot() 5 | 6 | #2 7 | # To get a more reliable statistic if it makes logical sense 8 | 9 | #3 10 | r = df.rolling(window = 20) 11 | r.apply(lambda x: sorted(x)[round(len(x)*.5)]) 12 | 13 | #4 14 | r = df.rolling(window = 20) 15 | r.agg(['sum', 'mean']).head(30) 16 | --------------------------------------------------------------------------------