├── README.md ├── numpy └── quickstart │ ├── Quickstart.ipynb │ ├── Quickstart.md │ ├── output_67_0.png │ ├── output_75_0.png │ └── output_75_1.png └── pandas └── ten_minutes_to_pandas ├── output_133_1.png ├── output_135_1.png ├── ten_minutes_to_pandas.ipynb └── ten_minutes_to_pandas.md /README.md: -------------------------------------------------------------------------------- 1 | [NumPy快速入门(官网部分内容翻译)](https://github.com/cxylpy/self_tutorial/blob/master/numpy/quickstart/Quickstart.md) 2 | 3 | [10分钟快速上手Pandas(官网部分内容翻译)](https://github.com/cxylpy/self_tutorial/blob/master/pandas/ten_minutes_to_pandas/ten_minutes_to_pandas.md) 4 | -------------------------------------------------------------------------------- /numpy/quickstart/Quickstart.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 基本概念\n", 8 | "Numpy 的核心是连续的多维数组。 \n", 9 | "Numpy中的数组叫做```np.ndarray```,也可以使用别名```np.array```。 \n", 10 | "但这里的np.array与Python标准库中的array.array是不同的。\n", 11 | "下列是几个```ndarray```中的重要属性: \n", 12 | "\n", 13 | "**ndarray.ndim** \n", 14 | "  数组的维数。 \n", 15 | "**ndarray.shape** \n", 16 | "  数组的形状。 \n", 17 | "**ndarray.size** \n", 18 | "  数组的元素个数。 \n", 19 | "**ndarray.dtype** \n", 20 | "  数组的元素类型。 \n", 21 | " \n", 22 | "例子: " 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 1, 28 | "metadata": { 29 | "ExecuteTime": { 30 | "end_time": "2018-01-06T10:13:15.508912Z", 31 | "start_time": "2018-01-06T10:13:15.410282Z" 32 | } 33 | }, 34 | "outputs": [ 35 | { 36 | "name": "stdout", 37 | "output_type": "stream", 38 | "text": [ 39 | "[[ 0 1 2 3 4]\n", 40 | " [ 5 6 7 8 9]\n", 41 | " [10 11 12 13 14]]\n", 42 | "(3, 5)\n", 43 | "2\n", 44 | "15\n", 45 | "int32\n" 46 | ] 47 | } 48 | ], 49 | "source": [ 50 | "import numpy as np\n", 51 | "data=np.arange(15).reshape(3,5)\n", 52 | "print(data)\n", 53 | "print(data.shape)\n", 54 | "print(data.ndim)\n", 55 | "print(data.size)\n", 56 | "print(data.dtype.name)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "#### 数组的创建\n", 64 | "创建数组有多种方式。你可以使用```np.array```直接用Python的元组和列表来创建。" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 2, 70 | "metadata": { 71 | "ExecuteTime": { 72 | "end_time": "2018-01-06T10:13:17.093467Z", 73 | "start_time": "2018-01-06T10:13:17.076436Z" 74 | } 75 | }, 76 | "outputs": [ 77 | { 78 | "name": "stdout", 79 | "output_type": "stream", 80 | "text": [ 81 | "int32\n", 82 | "float64\n", 83 | "[[ 1. 2. 3. ]\n", 84 | " [ 4.5 5. 6. ]]\n", 85 | "[[ 1.+0.j 2.+0.j]\n", 86 | " [ 3.+0.j 4.+0.j]]\n" 87 | ] 88 | } 89 | ], 90 | "source": [ 91 | "import numpy as np\n", 92 | "a=np.array([1,2,3])\n", 93 | "print(a.dtype)\n", 94 | "b=np.array([1.1,2.2,3.3])\n", 95 | "print(b.dtype)\n", 96 | "c=np.array([(1,2,3),(4.5,5,6)]) #创建二维数组\n", 97 | "print(c)\n", 98 | "d=np.array([(1,2),(3,4)],dtype=complex) #数组的类型可以在创建时显式声明\n", 99 | "print(d)" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "通常,数组的元素的未知的,但是形状确实已知的。所以NumPy提供了多种创建空数组的方法。 \n", 107 | "```np.zeros``` 创建全是0的数组。 \n", 108 | "```np.ones``` 创建全是1的数组。 \n", 109 | "```np.empty``` 创建初始值是随机数的数组。 \n", 110 | "需要注意的是上述方法创建的数组元素的类型是 ```float64```" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 3, 116 | "metadata": { 117 | "ExecuteTime": { 118 | "end_time": "2018-01-06T10:13:18.701291Z", 119 | "start_time": "2018-01-06T10:13:18.690262Z" 120 | } 121 | }, 122 | "outputs": [ 123 | { 124 | "name": "stdout", 125 | "output_type": "stream", 126 | "text": [ 127 | "[[ 0. 0. 0. 0.]\n", 128 | " [ 0. 0. 0. 0.]\n", 129 | " [ 0. 0. 0. 0.]]\n", 130 | "[[[1 1 1 1]\n", 131 | " [1 1 1 1]\n", 132 | " [1 1 1 1]]\n", 133 | "\n", 134 | " [[1 1 1 1]\n", 135 | " [1 1 1 1]\n", 136 | " [1 1 1 1]]]\n", 137 | "[[ 1. 2. 3. ]\n", 138 | " [ 4.5 5. 6. ]]\n" 139 | ] 140 | } 141 | ], 142 | "source": [ 143 | "e=np.zeros((3,4))\n", 144 | "print(e)\n", 145 | "f=np.ones((2,3,4),dtype=np.int16)#可以更改数据类型\n", 146 | "print(f)\n", 147 | "g=np.empty((2,3))\n", 148 | "print(g)" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "为了创建列表,NumPy提供了和 ```range``` 类似的函数。 \n", 156 | "```np.arange(start,end,step)```" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 4, 162 | "metadata": { 163 | "ExecuteTime": { 164 | "end_time": "2018-01-06T10:13:20.256614Z", 165 | "start_time": "2018-01-06T10:13:20.249595Z" 166 | } 167 | }, 168 | "outputs": [ 169 | { 170 | "name": "stdout", 171 | "output_type": "stream", 172 | "text": [ 173 | "[10 15 20 25]\n", 174 | "[ 0. 0.3 0.6 0.9 1.2 1.5 1.8]\n" 175 | ] 176 | } 177 | ], 178 | "source": [ 179 | "a=np.arange(10,30,5)\n", 180 | "print(a)\n", 181 | "b=np.arange(0,2,0.3)#同样可以接收浮点数\n", 182 | "print(b)" 183 | ] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "metadata": {}, 188 | "source": [ 189 | "在生成浮点数列表时,最好不要使用```np.arange```,而是使用```np.linspace```。 \n", 190 | "```np.linspace(start,stop,num)```" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": 5, 196 | "metadata": { 197 | "ExecuteTime": { 198 | "end_time": "2018-01-06T10:13:22.146904Z", 199 | "start_time": "2018-01-06T10:13:22.132868Z" 200 | } 201 | }, 202 | "outputs": [ 203 | { 204 | "data": { 205 | "text/plain": [ 206 | "array([ 0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])" 207 | ] 208 | }, 209 | "execution_count": 5, 210 | "metadata": {}, 211 | "output_type": "execute_result" 212 | } 213 | ], 214 | "source": [ 215 | "np.linspace(0,2,9)" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": { 221 | "ExecuteTime": { 222 | "end_time": "2018-01-06T08:16:41.728753Z", 223 | "start_time": "2018-01-06T08:16:41.719703Z" 224 | } 225 | }, 226 | "source": [ 227 | "#### 打印数组\n", 228 | "当你打印一个数组时,NumPy显示数组的方式和嵌套的列表类似,但是会遵循以下布局:\n", 229 | " - 最后一维从左到右显示\n", 230 | " - 第二维到最后一维从上到下显示\n", 231 | " - 剩下的同样从上到下显示,以空行分隔\n", 232 | " \n", 233 | "一维数组显示成一行,二维数组显示成矩阵,三维数组显示成矩阵的列表。\n", 234 | " " 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 6, 240 | "metadata": { 241 | "ExecuteTime": { 242 | "end_time": "2018-01-06T10:13:23.582619Z", 243 | "start_time": "2018-01-06T10:13:23.574596Z" 244 | } 245 | }, 246 | "outputs": [ 247 | { 248 | "name": "stdout", 249 | "output_type": "stream", 250 | "text": [ 251 | "[0 1 2 3 4 5]\n", 252 | "[[ 0 1 2]\n", 253 | " [ 3 4 5]\n", 254 | " [ 6 7 8]\n", 255 | " [ 9 10 11]]\n", 256 | "[[[ 0 1 2 3]\n", 257 | " [ 4 5 6 7]\n", 258 | " [ 8 9 10 11]]\n", 259 | "\n", 260 | " [[12 13 14 15]\n", 261 | " [16 17 18 19]\n", 262 | " [20 21 22 23]]]\n" 263 | ] 264 | } 265 | ], 266 | "source": [ 267 | "a=np.arange(6)\n", 268 | "print(a)\n", 269 | "b=np.arange(12).reshape(4,3)\n", 270 | "print(b)\n", 271 | "c=np.arange(24).reshape(2,3,4)\n", 272 | "print(c)" 273 | ] 274 | }, 275 | { 276 | "cell_type": "markdown", 277 | "metadata": { 278 | "ExecuteTime": { 279 | "end_time": "2018-01-06T08:20:26.779079Z", 280 | "start_time": "2018-01-06T08:20:26.773063Z" 281 | } 282 | }, 283 | "source": [ 284 | "当一个数组元素太多,不方便显示时,NumPy会自动数组的中间部分,只显示边角的数据。" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "execution_count": 7, 290 | "metadata": { 291 | "ExecuteTime": { 292 | "end_time": "2018-01-06T10:13:24.971984Z", 293 | "start_time": "2018-01-06T10:13:24.966998Z" 294 | } 295 | }, 296 | "outputs": [ 297 | { 298 | "name": "stdout", 299 | "output_type": "stream", 300 | "text": [ 301 | "[ 0 1 2 ..., 9997 9998 9999]\n" 302 | ] 303 | } 304 | ], 305 | "source": [ 306 | "print(np.arange(10000))" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "#### 基本操作\n", 314 | "数组的算数计算是在元素层级运算的。计算结果会存在一个新创建的数组中。" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 8, 320 | "metadata": { 321 | "ExecuteTime": { 322 | "end_time": "2018-01-06T10:13:26.373878Z", 323 | "start_time": "2018-01-06T10:13:26.363841Z" 324 | } 325 | }, 326 | "outputs": [ 327 | { 328 | "name": "stdout", 329 | "output_type": "stream", 330 | "text": [ 331 | "[0 1 2 3]\n", 332 | "[20 29 38 47]\n", 333 | "[0 1 4 9]\n", 334 | "[ 9.12945251 -9.88031624 7.4511316 -2.62374854]\n", 335 | "[ True True False False]\n" 336 | ] 337 | } 338 | ], 339 | "source": [ 340 | "import numpy as np\n", 341 | "a=np.array([20,30,40,50])\n", 342 | "b=np.arange(4)\n", 343 | "print(b)\n", 344 | "c=a-b\n", 345 | "print(c)\n", 346 | "print(b**2)\n", 347 | "print(10*np.sin(a))\n", 348 | "print(a<35)" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "在NumPy中```*```号仍然表示乘法,矩阵乘积用```np.dot```来计算。" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": 9, 361 | "metadata": { 362 | "ExecuteTime": { 363 | "end_time": "2018-01-06T10:13:27.856146Z", 364 | "start_time": "2018-01-06T10:13:27.846118Z" 365 | } 366 | }, 367 | "outputs": [ 368 | { 369 | "name": "stdout", 370 | "output_type": "stream", 371 | "text": [ 372 | "[[2 0]\n", 373 | " [0 4]]\n", 374 | "[[5 4]\n", 375 | " [3 4]]\n", 376 | "[[5 4]\n", 377 | " [3 4]]\n" 378 | ] 379 | } 380 | ], 381 | "source": [ 382 | "A=np.array([(1,1),(0,1)])\n", 383 | "B=np.array([(2,0),(3,4)])\n", 384 | "print(A*B)\n", 385 | "print(A.dot(B))\n", 386 | "print(np.dot(A,B))" 387 | ] 388 | }, 389 | { 390 | "cell_type": "markdown", 391 | "metadata": {}, 392 | "source": [ 393 | "类似于```+=```和```*=```的运算是直接在现有数组上计算的,没有创建新的数组。Numpy中的计算同样也是向上转型的,可以简单理解成浮点数和整数运算的结果是浮点数。" 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "execution_count": 10, 399 | "metadata": { 400 | "ExecuteTime": { 401 | "end_time": "2018-01-06T10:13:29.189724Z", 402 | "start_time": "2018-01-06T10:13:29.178692Z" 403 | } 404 | }, 405 | "outputs": [ 406 | { 407 | "name": "stdout", 408 | "output_type": "stream", 409 | "text": [ 410 | "[[3 3 3]\n", 411 | " [3 3 3]]\n", 412 | "[[ 3.36167598 3.63342297 3.22543331]\n", 413 | " [ 3.17992397 3.01462584 3.87847828]]\n" 414 | ] 415 | } 416 | ], 417 | "source": [ 418 | "a = np.ones((2,3), dtype=int)\n", 419 | "b = np.random.random((2,3))\n", 420 | "a*=3\n", 421 | "print(a)\n", 422 | "b += a\n", 423 | "print(b)\n", 424 | "# a += b # 浮点数不会自动转换成整数" 425 | ] 426 | }, 427 | { 428 | "cell_type": "markdown", 429 | "metadata": {}, 430 | "source": [ 431 | "```np.ndarray```提供了许多一元操作。比如数组求和、求最大最小值等。" 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": 11, 437 | "metadata": { 438 | "ExecuteTime": { 439 | "end_time": "2018-01-06T10:13:30.434374Z", 440 | "start_time": "2018-01-06T10:13:30.425346Z" 441 | } 442 | }, 443 | "outputs": [ 444 | { 445 | "name": "stdout", 446 | "output_type": "stream", 447 | "text": [ 448 | "[[ 0.06108727 0.21625055 0.066292 ]\n", 449 | " [ 0.20271722 0.93946432 0.37747181]]\n", 450 | "1.86328317161\n", 451 | "0.310547195269\n", 452 | "0.939464322779\n", 453 | "0.0610872663968\n" 454 | ] 455 | } 456 | ], 457 | "source": [ 458 | "a=np.random.random((2,3))\n", 459 | "print(a)\n", 460 | "print(a.sum())\n", 461 | "print(a.mean())\n", 462 | "print(a.max())\n", 463 | "print(a.min())" 464 | ] 465 | }, 466 | { 467 | "cell_type": "markdown", 468 | "metadata": {}, 469 | "source": [ 470 | "默认的,这些一元操作是对整个数组进行计算,没有考虑到数组的形状。你可以设置```axis```参数来指定运算方向。```axis```表示第n维(从0开始)。" 471 | ] 472 | }, 473 | { 474 | "cell_type": "code", 475 | "execution_count": 12, 476 | "metadata": { 477 | "ExecuteTime": { 478 | "end_time": "2018-01-06T10:13:32.155868Z", 479 | "start_time": "2018-01-06T10:13:32.145852Z" 480 | } 481 | }, 482 | "outputs": [ 483 | { 484 | "name": "stdout", 485 | "output_type": "stream", 486 | "text": [ 487 | "[[ 0 1 2 3]\n", 488 | " [ 4 5 6 7]\n", 489 | " [ 8 9 10 11]]\n", 490 | "[12 15 18 21]\n", 491 | "[ 6 22 38]\n", 492 | "[0 4 8]\n", 493 | "[[ 0 1 3 6]\n", 494 | " [ 4 9 15 22]\n", 495 | " [ 8 17 27 38]]\n" 496 | ] 497 | } 498 | ], 499 | "source": [ 500 | "b=np.arange(12).reshape(3,4)\n", 501 | "print(b)\n", 502 | "print(b.sum(axis=0)) #对第0维的元素求和\n", 503 | "print(b.sum(axis=1)) #对第1维的元素求和\n", 504 | "print(b.min(axis=1))\n", 505 | "print(b.cumsum(axis=1)) #对第1维的元素累加求和" 506 | ] 507 | }, 508 | { 509 | "cell_type": "markdown", 510 | "metadata": { 511 | "ExecuteTime": { 512 | "end_time": "2018-01-06T08:36:59.436308Z", 513 | "start_time": "2018-01-06T08:36:59.431294Z" 514 | } 515 | }, 516 | "source": [ 517 | "#### 广播函数\n", 518 | "NumPy提供了熟知的数学方法,如:sin、cos、exp等。在NumPy中,这些方法被称作广播函数。这些函数会对数组中的每个元素进行计算,返回计算后的数组。" 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": 13, 524 | "metadata": { 525 | "ExecuteTime": { 526 | "end_time": "2018-01-06T10:13:33.755312Z", 527 | "start_time": "2018-01-06T10:13:33.744772Z" 528 | } 529 | }, 530 | "outputs": [ 531 | { 532 | "name": "stdout", 533 | "output_type": "stream", 534 | "text": [ 535 | "[0 1 2]\n", 536 | "[ 1. 2.71828183 7.3890561 ]\n", 537 | "[ 0. 1. 1.41421356]\n", 538 | "[2 0 6]\n", 539 | "[2 0 6]\n" 540 | ] 541 | } 542 | ], 543 | "source": [ 544 | "B=np.arange(3)\n", 545 | "print(B)\n", 546 | "print(np.exp(B))\n", 547 | "print(np.sqrt(B))\n", 548 | "C=np.array([2,-1,4])\n", 549 | "print(np.add(B,C))\n", 550 | "print(B+C)\n" 551 | ] 552 | }, 553 | { 554 | "cell_type": "markdown", 555 | "metadata": { 556 | "ExecuteTime": { 557 | "end_time": "2018-01-06T08:38:28.434285Z", 558 | "start_time": "2018-01-06T08:38:28.428279Z" 559 | } 560 | }, 561 | "source": [ 562 | "#### 索引、切片和迭代\n", 563 | "一维数组可以被索引、切片和迭代,就和Python中的列表一样。" 564 | ] 565 | }, 566 | { 567 | "cell_type": "code", 568 | "execution_count": 14, 569 | "metadata": { 570 | "ExecuteTime": { 571 | "end_time": "2018-01-06T10:13:35.042210Z", 572 | "start_time": "2018-01-06T10:13:35.027669Z" 573 | }, 574 | "scrolled": true 575 | }, 576 | "outputs": [ 577 | { 578 | "name": "stdout", 579 | "output_type": "stream", 580 | "text": [ 581 | "[ 0 1 8 27 64 125 216 343 512 729]\n", 582 | "8\n", 583 | "[ 8 27 64]\n", 584 | "[-1000 1 -1000 27 -1000 125 216 343 512 729]\n", 585 | "[ 729 512 343 216 125 -1000 27 -1000 1 -1000]\n", 586 | "-1000\n", 587 | "1\n", 588 | "-1000\n", 589 | "27\n", 590 | "-1000\n", 591 | "125\n", 592 | "216\n", 593 | "343\n", 594 | "512\n", 595 | "729\n" 596 | ] 597 | } 598 | ], 599 | "source": [ 600 | "a=np.arange(10)**3\n", 601 | "print(a)\n", 602 | "print(a[2])\n", 603 | "print(a[2:5])\n", 604 | "a[:6:2]=-1000\n", 605 | "print(a)\n", 606 | "print(a[::-1])\n", 607 | "for i in a:\n", 608 | " print(i)" 609 | ] 610 | }, 611 | { 612 | "cell_type": "markdown", 613 | "metadata": { 614 | "ExecuteTime": { 615 | "end_time": "2018-01-06T08:41:33.786671Z", 616 | "start_time": "2018-01-06T08:41:33.782690Z" 617 | } 618 | }, 619 | "source": [ 620 | "多维数组可以在每一个维度有一个索引,这些索引构成元组来进行访问。" 621 | ] 622 | }, 623 | { 624 | "cell_type": "code", 625 | "execution_count": 15, 626 | "metadata": { 627 | "ExecuteTime": { 628 | "end_time": "2018-01-06T10:13:36.210243Z", 629 | "start_time": "2018-01-06T10:13:36.198705Z" 630 | } 631 | }, 632 | "outputs": [ 633 | { 634 | "name": "stdout", 635 | "output_type": "stream", 636 | "text": [ 637 | "[[ 0 1 2 3]\n", 638 | " [10 11 12 13]\n", 639 | " [20 21 22 23]\n", 640 | " [30 31 32 33]\n", 641 | " [40 41 42 43]]\n", 642 | "23\n", 643 | "[ 1 11 21 31 41]\n", 644 | "[ 1 11 21 31 41]\n", 645 | "[[10 11 12 13]\n", 646 | " [20 21 22 23]]\n" 647 | ] 648 | } 649 | ], 650 | "source": [ 651 | "def f(x,y):return 10*x+y\n", 652 | "b=np.fromfunction(f,(5,4),dtype=int)\n", 653 | "print(b)\n", 654 | "print(b[2,3])\n", 655 | "print(b[0:5,1])\n", 656 | "print(b[:,1])\n", 657 | "print(b[1:3,:])\n" 658 | ] 659 | }, 660 | { 661 | "cell_type": "markdown", 662 | "metadata": {}, 663 | "source": [ 664 | "```...```表示对索引的省略。如下所示:" 665 | ] 666 | }, 667 | { 668 | "cell_type": "code", 669 | "execution_count": 16, 670 | "metadata": { 671 | "ExecuteTime": { 672 | "end_time": "2018-01-06T10:13:37.279065Z", 673 | "start_time": "2018-01-06T10:13:37.270040Z" 674 | } 675 | }, 676 | "outputs": [ 677 | { 678 | "name": "stdout", 679 | "output_type": "stream", 680 | "text": [ 681 | "(2, 2, 3)\n", 682 | "[[100 101 102]\n", 683 | " [110 112 113]]\n", 684 | "[[ 2 13]\n", 685 | " [102 113]]\n" 686 | ] 687 | } 688 | ], 689 | "source": [ 690 | "c = np.array( [[[ 0, 1, 2], # 三维数组\n", 691 | " [ 10, 12, 13]],\n", 692 | " [[100,101,102],\n", 693 | " [110,112,113]]])\n", 694 | "print(c.shape)\n", 695 | "print(c[1,...]) # 和 c[1,:,:] 、 c[1]效果相同\n", 696 | "print(c[...,2]) # 和c[:,:,2]效果相同\n" 697 | ] 698 | }, 699 | { 700 | "cell_type": "code", 701 | "execution_count": null, 702 | "metadata": {}, 703 | "outputs": [], 704 | "source": [ 705 | "对多维数组的迭代是在第一维进行迭代的。" 706 | ] 707 | }, 708 | { 709 | "cell_type": "code", 710 | "execution_count": 17, 711 | "metadata": { 712 | "ExecuteTime": { 713 | "end_time": "2018-01-06T10:13:38.226489Z", 714 | "start_time": "2018-01-06T10:13:38.220471Z" 715 | } 716 | }, 717 | "outputs": [ 718 | { 719 | "name": "stdout", 720 | "output_type": "stream", 721 | "text": [ 722 | "[0 1 2 3]\n", 723 | "[10 11 12 13]\n", 724 | "[20 21 22 23]\n", 725 | "[30 31 32 33]\n", 726 | "[40 41 42 43]\n" 727 | ] 728 | } 729 | ], 730 | "source": [ 731 | "for row in b:\n", 732 | " print(row)" 733 | ] 734 | }, 735 | { 736 | "cell_type": "markdown", 737 | "metadata": {}, 738 | "source": [ 739 | "如果需要遍历多维数组的所有元素,可以使用```flat```这个属性。" 740 | ] 741 | }, 742 | { 743 | "cell_type": "code", 744 | "execution_count": 18, 745 | "metadata": { 746 | "ExecuteTime": { 747 | "end_time": "2018-01-06T10:13:39.171487Z", 748 | "start_time": "2018-01-06T10:13:39.164465Z" 749 | }, 750 | "scrolled": true 751 | }, 752 | "outputs": [ 753 | { 754 | "name": "stdout", 755 | "output_type": "stream", 756 | "text": [ 757 | "0\n", 758 | "1\n", 759 | "2\n", 760 | "3\n", 761 | "10\n", 762 | "11\n", 763 | "12\n", 764 | "13\n", 765 | "20\n", 766 | "21\n", 767 | "22\n", 768 | "23\n", 769 | "30\n", 770 | "31\n", 771 | "32\n", 772 | "33\n", 773 | "40\n", 774 | "41\n", 775 | "42\n", 776 | "43\n" 777 | ] 778 | } 779 | ], 780 | "source": [ 781 | "for element in b.flat:\n", 782 | " print(element)" 783 | ] 784 | }, 785 | { 786 | "cell_type": "markdown", 787 | "metadata": { 788 | "ExecuteTime": { 789 | "end_time": "2018-01-06T08:47:20.987748Z", 790 | "start_time": "2018-01-06T08:47:20.984739Z" 791 | } 792 | }, 793 | "source": [ 794 | "### 数组形状操作\n", 795 | "#### 更改数组的形状\n", 796 | "有很多种方式可以更改数组的形状。下列的函数都没有对原数组进行更改,而是返回了一个更改后的新数组。" 797 | ] 798 | }, 799 | { 800 | "cell_type": "code", 801 | "execution_count": 19, 802 | "metadata": { 803 | "ExecuteTime": { 804 | "end_time": "2018-01-06T10:13:40.325824Z", 805 | "start_time": "2018-01-06T10:13:40.316768Z" 806 | } 807 | }, 808 | "outputs": [ 809 | { 810 | "name": "stdout", 811 | "output_type": "stream", 812 | "text": [ 813 | "[ 5. 0. 9. 5. 5. 4. 2. 2. 3. 2. 0. 7.]\n", 814 | "[[ 5. 0.]\n", 815 | " [ 9. 5.]\n", 816 | " [ 5. 4.]\n", 817 | " [ 2. 2.]\n", 818 | " [ 3. 2.]\n", 819 | " [ 0. 7.]]\n", 820 | "[[ 5. 5. 3.]\n", 821 | " [ 0. 4. 2.]\n", 822 | " [ 9. 2. 0.]\n", 823 | " [ 5. 2. 7.]]\n" 824 | ] 825 | } 826 | ], 827 | "source": [ 828 | "a = np.floor(10*np.random.random((3,4)))\n", 829 | "print(a.ravel()) #返回铺平后的数组\n", 830 | "print(a.reshape(6,2)) #按照指定的形状更改\n", 831 | "print(a.T)#返回转置矩阵" 832 | ] 833 | }, 834 | { 835 | "cell_type": "markdown", 836 | "metadata": {}, 837 | "source": [ 838 | "如果一个维度填的是-1,则该维度的形状会自动进行计算" 839 | ] 840 | }, 841 | { 842 | "cell_type": "code", 843 | "execution_count": 20, 844 | "metadata": { 845 | "ExecuteTime": { 846 | "end_time": "2018-01-06T10:13:41.276676Z", 847 | "start_time": "2018-01-06T10:13:41.272133Z" 848 | } 849 | }, 850 | "outputs": [ 851 | { 852 | "name": "stdout", 853 | "output_type": "stream", 854 | "text": [ 855 | "[[ 5. 0. 9. 5.]\n", 856 | " [ 5. 4. 2. 2.]\n", 857 | " [ 3. 2. 0. 7.]]\n" 858 | ] 859 | } 860 | ], 861 | "source": [ 862 | "print(a.reshape(3,-1))" 863 | ] 864 | }, 865 | { 866 | "cell_type": "markdown", 867 | "metadata": {}, 868 | "source": [ 869 | "#### 堆砌不同的数组\n", 870 | "多个数组可以按照不同的轴合在一起" 871 | ] 872 | }, 873 | { 874 | "cell_type": "code", 875 | "execution_count": 21, 876 | "metadata": { 877 | "ExecuteTime": { 878 | "end_time": "2018-01-06T10:13:42.426568Z", 879 | "start_time": "2018-01-06T10:13:42.410526Z" 880 | } 881 | }, 882 | "outputs": [ 883 | { 884 | "name": "stdout", 885 | "output_type": "stream", 886 | "text": [ 887 | "[[ 5. 1.]\n", 888 | " [ 4. 2.]]\n", 889 | "[[ 8. 1.]\n", 890 | " [ 7. 8.]]\n", 891 | "[[ 5. 1.]\n", 892 | " [ 4. 2.]\n", 893 | " [ 8. 1.]\n", 894 | " [ 7. 8.]]\n", 895 | "[[ 5. 1. 8. 1.]\n", 896 | " [ 4. 2. 7. 8.]]\n", 897 | "[[[ 5. 1.]]\n", 898 | "\n", 899 | " [[ 4. 2.]]]\n" 900 | ] 901 | } 902 | ], 903 | "source": [ 904 | "a=np.floor(10*np.random.random((2,2)))\n", 905 | "print(a)\n", 906 | "b=np.floor(10*np.random.random((2,2)))\n", 907 | "print(b)\n", 908 | "print(np.vstack((a,b)))#垂直方向堆砌\n", 909 | "print(np.hstack((a,b)))#水平方向堆砌\n", 910 | "from numpy import newaxis\n", 911 | "print(a[:,newaxis])" 912 | ] 913 | }, 914 | { 915 | "cell_type": "markdown", 916 | "metadata": {}, 917 | "source": [ 918 | "#### 将一个数组划分为多个更小的数组\n", 919 | "使用```hsplit```,```vsplit```可以对数组按照水平方向和垂直方向进行划分。" 920 | ] 921 | }, 922 | { 923 | "cell_type": "code", 924 | "execution_count": 22, 925 | "metadata": { 926 | "ExecuteTime": { 927 | "end_time": "2018-01-06T10:13:43.857295Z", 928 | "start_time": "2018-01-06T10:13:43.845263Z" 929 | } 930 | }, 931 | "outputs": [ 932 | { 933 | "name": "stdout", 934 | "output_type": "stream", 935 | "text": [ 936 | "[[ 7. 4. 0. 7. 5. 6. 4. 4. 4. 7. 7. 0.]\n", 937 | " [ 0. 1. 7. 7. 4. 9. 7. 0. 0. 2. 7. 5.]]\n", 938 | "[array([[ 7., 4., 0., 7.],\n", 939 | " [ 0., 1., 7., 7.]]), array([[ 5., 6., 4., 4.],\n", 940 | " [ 4., 9., 7., 0.]]), array([[ 4., 7., 7., 0.],\n", 941 | " [ 0., 2., 7., 5.]])]\n", 942 | "[array([[ 7.],\n", 943 | " [ 0.]]), array([[ 4.],\n", 944 | " [ 1.]]), array([[ 0.],\n", 945 | " [ 7.]]), array([[ 7., 5., 6., 4., 4., 4., 7., 7., 0.],\n", 946 | " [ 7., 4., 9., 7., 0., 0., 2., 7., 5.]])]\n" 947 | ] 948 | } 949 | ], 950 | "source": [ 951 | "a=np.floor(10*np.random.random((2,12)))\n", 952 | "print(a)\n", 953 | "print(np.hsplit(a,3))\n", 954 | "print(np.hsplit(a,(1,2,3)))#在第一列,第二列,第三列进行划分" 955 | ] 956 | }, 957 | { 958 | "cell_type": "markdown", 959 | "metadata": {}, 960 | "source": [ 961 | "### 复制和视图\n", 962 | "当操作数组时,数组的数据有时会复制到新数组中,有时又不会。这通常令初学者感到困难。总的来说有下面三种情况:" 963 | ] 964 | }, 965 | { 966 | "cell_type": "markdown", 967 | "metadata": {}, 968 | "source": [ 969 | "#### 不复制\n", 970 | "简单的赋值不会复制数组的数据。" 971 | ] 972 | }, 973 | { 974 | "cell_type": "code", 975 | "execution_count": 23, 976 | "metadata": { 977 | "ExecuteTime": { 978 | "end_time": "2018-01-06T10:13:46.265174Z", 979 | "start_time": "2018-01-06T10:13:46.258101Z" 980 | } 981 | }, 982 | "outputs": [ 983 | { 984 | "name": "stdout", 985 | "output_type": "stream", 986 | "text": [ 987 | "True\n", 988 | "(3, 4)\n" 989 | ] 990 | } 991 | ], 992 | "source": [ 993 | "a=np.arange(12)\n", 994 | "b=a\n", 995 | "print(b is a)\n", 996 | "b.shape=3,4\n", 997 | "print(a.shape)" 998 | ] 999 | }, 1000 | { 1001 | "cell_type": "markdown", 1002 | "metadata": {}, 1003 | "source": [ 1004 | "#### 视图和浅复制\n", 1005 | "不同的数组可以使用同一份数据,```view```函数在同一份数据上创建了新的数组对象。" 1006 | ] 1007 | }, 1008 | { 1009 | "cell_type": "code", 1010 | "execution_count": 24, 1011 | "metadata": { 1012 | "ExecuteTime": { 1013 | "end_time": "2018-01-06T10:13:47.551565Z", 1014 | "start_time": "2018-01-06T10:13:47.539557Z" 1015 | } 1016 | }, 1017 | "outputs": [ 1018 | { 1019 | "name": "stdout", 1020 | "output_type": "stream", 1021 | "text": [ 1022 | "False\n", 1023 | "True\n", 1024 | "False\n", 1025 | "(3, 4)\n", 1026 | "[[ 0 1 2 3]\n", 1027 | " [ 4 5 6 7]\n", 1028 | " [ 8 1234 10 11]]\n" 1029 | ] 1030 | } 1031 | ], 1032 | "source": [ 1033 | "c=a.view()\n", 1034 | "print(c is a)\n", 1035 | "print(c.base is a) #c是a的数据的视图\n", 1036 | "print(c.flags.owndata)\n", 1037 | "c.shape=6,2\n", 1038 | "print(a.shape) #a的形状没有改变\n", 1039 | "c[4,1]=1234 #a的数据改变了\n", 1040 | "print(a)" 1041 | ] 1042 | }, 1043 | { 1044 | "cell_type": "markdown", 1045 | "metadata": {}, 1046 | "source": [ 1047 | "对数组切片会返回数组的视图" 1048 | ] 1049 | }, 1050 | { 1051 | "cell_type": "code", 1052 | "execution_count": 25, 1053 | "metadata": { 1054 | "ExecuteTime": { 1055 | "end_time": "2018-01-06T10:13:50.279056Z", 1056 | "start_time": "2018-01-06T10:13:50.274041Z" 1057 | } 1058 | }, 1059 | "outputs": [ 1060 | { 1061 | "name": "stdout", 1062 | "output_type": "stream", 1063 | "text": [ 1064 | "[[ 0 10 10 3]\n", 1065 | " [ 4 10 10 7]\n", 1066 | " [ 8 10 10 11]]\n" 1067 | ] 1068 | } 1069 | ], 1070 | "source": [ 1071 | "s=a[:,1:3]\n", 1072 | "s[:]=10\n", 1073 | "print(a)" 1074 | ] 1075 | }, 1076 | { 1077 | "cell_type": "markdown", 1078 | "metadata": {}, 1079 | "source": [ 1080 | "#### 深复制\n", 1081 | "```copy```函数实现了对数据和数组的完全复制。" 1082 | ] 1083 | }, 1084 | { 1085 | "cell_type": "code", 1086 | "execution_count": 26, 1087 | "metadata": { 1088 | "ExecuteTime": { 1089 | "end_time": "2018-01-06T10:13:51.476104Z", 1090 | "start_time": "2018-01-06T10:13:51.469336Z" 1091 | } 1092 | }, 1093 | "outputs": [ 1094 | { 1095 | "name": "stdout", 1096 | "output_type": "stream", 1097 | "text": [ 1098 | "False\n", 1099 | "False\n", 1100 | "[[ 0 10 10 3]\n", 1101 | " [ 4 10 10 7]\n", 1102 | " [ 8 10 10 11]]\n" 1103 | ] 1104 | } 1105 | ], 1106 | "source": [ 1107 | "d=a.copy()\n", 1108 | "print(d is a)\n", 1109 | "print(d.base is a)\n", 1110 | "d[0,0]=9999\n", 1111 | "print(a)" 1112 | ] 1113 | }, 1114 | { 1115 | "cell_type": "markdown", 1116 | "metadata": {}, 1117 | "source": [ 1118 | "### 多种多样的索引和索引的小技巧\n", 1119 | "相比Python的列表,NumPy提供了更多的索引功能。除了可以用整数和列表来访问数组之外,数组还可以被整型数组和布尔数组访问。\n", 1120 | "#### 用数组访问数组" 1121 | ] 1122 | }, 1123 | { 1124 | "cell_type": "code", 1125 | "execution_count": 27, 1126 | "metadata": { 1127 | "ExecuteTime": { 1128 | "end_time": "2018-01-06T10:13:52.539431Z", 1129 | "start_time": "2018-01-06T10:13:52.531402Z" 1130 | } 1131 | }, 1132 | "outputs": [ 1133 | { 1134 | "name": "stdout", 1135 | "output_type": "stream", 1136 | "text": [ 1137 | "[ 1 1 9 64 25]\n", 1138 | "[[ 9 16]\n", 1139 | " [64 25]]\n" 1140 | ] 1141 | } 1142 | ], 1143 | "source": [ 1144 | "a=np.arange(12)**2\n", 1145 | "i=np.array([1,1,3,8,5])\n", 1146 | "print(a[i])\n", 1147 | "j=np.array([[3,4],[8,5]]) #用二维数组来访问数组\n", 1148 | "print(a[j]) #产生和访问的数组相同形状的结果" 1149 | ] 1150 | }, 1151 | { 1152 | "cell_type": "markdown", 1153 | "metadata": {}, 1154 | "source": [ 1155 | "在时间序列的数据上寻找最大值通常会用到数组索引" 1156 | ] 1157 | }, 1158 | { 1159 | "cell_type": "code", 1160 | "execution_count": 28, 1161 | "metadata": { 1162 | "ExecuteTime": { 1163 | "end_time": "2018-01-06T10:13:53.692386Z", 1164 | "start_time": "2018-01-06T10:13:53.679352Z" 1165 | } 1166 | }, 1167 | "outputs": [ 1168 | { 1169 | "name": "stdout", 1170 | "output_type": "stream", 1171 | "text": [ 1172 | "[ 20. 51.25 82.5 113.75 145. ]\n", 1173 | "[[ 0. 0.84147098 0.90929743 0.14112001]\n", 1174 | " [-0.7568025 -0.95892427 -0.2794155 0.6569866 ]\n", 1175 | " [ 0.98935825 0.41211849 -0.54402111 -0.99999021]\n", 1176 | " [-0.53657292 0.42016704 0.99060736 0.65028784]\n", 1177 | " [-0.28790332 -0.96139749 -0.75098725 0.14987721]]\n", 1178 | "[ 82.5 20. 113.75 51.25]\n", 1179 | "[ 0.98935825 0.84147098 0.99060736 0.6569866 ]\n" 1180 | ] 1181 | } 1182 | ], 1183 | "source": [ 1184 | "time=np.linspace(20,145,5)\n", 1185 | "data=np.sin(np.arange(20)).reshape(5,4)\n", 1186 | "print(time)\n", 1187 | "print(data)\n", 1188 | "ind=data.argmax(axis=0)#返回按照指定轴的方向的最大值的索引\n", 1189 | "time_max=time[ind]\n", 1190 | "print(time_max)\n", 1191 | "data_max=data[ind,range(data.shape[1])]\n", 1192 | "print(data_max)" 1193 | ] 1194 | }, 1195 | { 1196 | "cell_type": "markdown", 1197 | "metadata": {}, 1198 | "source": [ 1199 | "你也可以使用数组索引来赋值" 1200 | ] 1201 | }, 1202 | { 1203 | "cell_type": "code", 1204 | "execution_count": 29, 1205 | "metadata": { 1206 | "ExecuteTime": { 1207 | "end_time": "2018-01-06T10:13:54.692395Z", 1208 | "start_time": "2018-01-06T10:13:54.686390Z" 1209 | } 1210 | }, 1211 | "outputs": [ 1212 | { 1213 | "name": "stdout", 1214 | "output_type": "stream", 1215 | "text": [ 1216 | "[0 0 2 0 0]\n" 1217 | ] 1218 | } 1219 | ], 1220 | "source": [ 1221 | "a=np.arange(5)\n", 1222 | "a[[1,3,4]]=0\n", 1223 | "print(a)" 1224 | ] 1225 | }, 1226 | { 1227 | "cell_type": "markdown", 1228 | "metadata": {}, 1229 | "source": [ 1230 | "如果赋值时有重复的索引,则赋值会执行多次,留下最后一次执行的结果" 1231 | ] 1232 | }, 1233 | { 1234 | "cell_type": "code", 1235 | "execution_count": 30, 1236 | "metadata": { 1237 | "ExecuteTime": { 1238 | "end_time": "2018-01-06T10:13:55.584598Z", 1239 | "start_time": "2018-01-06T10:13:55.577579Z" 1240 | } 1241 | }, 1242 | "outputs": [ 1243 | { 1244 | "name": "stdout", 1245 | "output_type": "stream", 1246 | "text": [ 1247 | "[3 1 2 3 4]\n" 1248 | ] 1249 | } 1250 | ], 1251 | "source": [ 1252 | "a=np.arange(5)\n", 1253 | "a[[0,0,0]]=[1,2,3]\n", 1254 | "print(a)" 1255 | ] 1256 | }, 1257 | { 1258 | "cell_type": "markdown", 1259 | "metadata": {}, 1260 | "source": [ 1261 | "但是赋值时使用```+=```时,并不会重复计算" 1262 | ] 1263 | }, 1264 | { 1265 | "cell_type": "code", 1266 | "execution_count": 31, 1267 | "metadata": { 1268 | "ExecuteTime": { 1269 | "end_time": "2018-01-06T10:13:56.561040Z", 1270 | "start_time": "2018-01-06T10:13:56.554021Z" 1271 | } 1272 | }, 1273 | "outputs": [ 1274 | { 1275 | "name": "stdout", 1276 | "output_type": "stream", 1277 | "text": [ 1278 | "[1 1 2 3 4]\n" 1279 | ] 1280 | } 1281 | ], 1282 | "source": [ 1283 | "a=np.arange(5)\n", 1284 | "a[[0,0,0]]+=1\n", 1285 | "print(a)" 1286 | ] 1287 | }, 1288 | { 1289 | "cell_type": "markdown", 1290 | "metadata": {}, 1291 | "source": [ 1292 | "这是因为\"a+=1\"最终是解释成了\"a=a+1\"" 1293 | ] 1294 | }, 1295 | { 1296 | "cell_type": "markdown", 1297 | "metadata": {}, 1298 | "source": [ 1299 | "#### 用布尔数组来访问数组\n", 1300 | "通过使用布尔数组索引,我们可以选择哪些数据是需要的,哪些是不需要的。 \n", 1301 | "在赋值中也非常有用。" 1302 | ] 1303 | }, 1304 | { 1305 | "cell_type": "code", 1306 | "execution_count": 32, 1307 | "metadata": { 1308 | "ExecuteTime": { 1309 | "end_time": "2018-01-06T10:14:01.181551Z", 1310 | "start_time": "2018-01-06T10:14:01.174550Z" 1311 | } 1312 | }, 1313 | "outputs": [ 1314 | { 1315 | "name": "stdout", 1316 | "output_type": "stream", 1317 | "text": [ 1318 | "[[False False False False]\n", 1319 | " [False True True True]\n", 1320 | " [ True True True True]]\n", 1321 | "[ 5 6 7 8 9 10 11]\n", 1322 | "[[ 0 1 2 3]\n", 1323 | " [ 4 10 10 10]\n", 1324 | " [10 10 10 10]]\n" 1325 | ] 1326 | } 1327 | ], 1328 | "source": [ 1329 | "a = np.arange(12).reshape(3,4)\n", 1330 | "b = a > 4\n", 1331 | "print(b)\n", 1332 | "print(a[b])\n", 1333 | "a[b]=10\n", 1334 | "print(a)" 1335 | ] 1336 | }, 1337 | { 1338 | "cell_type": "markdown", 1339 | "metadata": {}, 1340 | "source": [ 1341 | "下面的代码用布尔数组索引产生了曼德布洛特集合的图像。" 1342 | ] 1343 | }, 1344 | { 1345 | "cell_type": "code", 1346 | "execution_count": 33, 1347 | "metadata": { 1348 | "ExecuteTime": { 1349 | "end_time": "2018-01-06T10:14:04.359463Z", 1350 | "start_time": "2018-01-06T10:14:03.824840Z" 1351 | } 1352 | }, 1353 | "outputs": [ 1354 | { 1355 | "data": { 1356 | "image/png": "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\nAAAAAABJRU5ErkJggg==\n", 1357 | "text/plain": [ 1358 | "" 1359 | ] 1360 | }, 1361 | "metadata": {}, 1362 | "output_type": "display_data" 1363 | } 1364 | ], 1365 | "source": [ 1366 | "import numpy as np\n", 1367 | "import matplotlib.pyplot as plt\n", 1368 | "def mandelbrot( h,w, maxit=20 ):\n", 1369 | " \"\"\"Returns an image of the Mandelbrot fractal of size (h,w).\"\"\"\n", 1370 | " y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ]\n", 1371 | " c = x+y*1j\n", 1372 | " z = c\n", 1373 | " divtime = maxit + np.zeros(z.shape, dtype=int)\n", 1374 | "\n", 1375 | " for i in range(maxit):\n", 1376 | " z = z**2 + c\n", 1377 | " diverge = z*np.conj(z) > 2**2 # who is diverging\n", 1378 | " div_now = diverge & (divtime==maxit) # who is diverging now\n", 1379 | " divtime[div_now] = i # note when\n", 1380 | " z[diverge] = 2 # avoid diverging too much\n", 1381 | "\n", 1382 | " return divtime\n", 1383 | "plt.imshow(mandelbrot(400,400))\n", 1384 | "plt.show()" 1385 | ] 1386 | }, 1387 | { 1388 | "cell_type": "markdown", 1389 | "metadata": {}, 1390 | "source": [ 1391 | "#### ix_()函数\n", 1392 | "ix_函数被用来计算不同的向量的乘积。" 1393 | ] 1394 | }, 1395 | { 1396 | "cell_type": "code", 1397 | "execution_count": 34, 1398 | "metadata": { 1399 | "ExecuteTime": { 1400 | "end_time": "2018-01-06T10:14:06.371119Z", 1401 | "start_time": "2018-01-06T10:14:06.354074Z" 1402 | } 1403 | }, 1404 | "outputs": [ 1405 | { 1406 | "name": "stdout", 1407 | "output_type": "stream", 1408 | "text": [ 1409 | "[[[2]]\n", 1410 | "\n", 1411 | " [[3]]\n", 1412 | "\n", 1413 | " [[4]]\n", 1414 | "\n", 1415 | " [[5]]]\n", 1416 | "[[[8]\n", 1417 | " [5]\n", 1418 | " [4]]]\n", 1419 | "[[[5 4 6 8 3]]]\n", 1420 | "(4, 1, 1) (1, 3, 1) (1, 1, 5)\n", 1421 | "[[[ 82 66 98 130 50]\n", 1422 | " [ 52 42 62 82 32]\n", 1423 | " [ 42 34 50 66 26]]\n", 1424 | "\n", 1425 | " [[123 99 147 195 75]\n", 1426 | " [ 78 63 93 123 48]\n", 1427 | " [ 63 51 75 99 39]]\n", 1428 | "\n", 1429 | " [[164 132 196 260 100]\n", 1430 | " [104 84 124 164 64]\n", 1431 | " [ 84 68 100 132 52]]\n", 1432 | "\n", 1433 | " [[205 165 245 325 125]\n", 1434 | " [130 105 155 205 80]\n", 1435 | " [105 85 125 165 65]]]\n", 1436 | "65\n", 1437 | "65\n" 1438 | ] 1439 | } 1440 | ], 1441 | "source": [ 1442 | "a = np.array([2,3,4,5])\n", 1443 | "b = np.array([8,5,4])\n", 1444 | "c = np.array([5,4,6,8,3])\n", 1445 | "ax,bx,cx = np.ix_(a,b,c)\n", 1446 | "print(ax)\n", 1447 | "print(bx)\n", 1448 | "print(cx)\n", 1449 | "print(ax.shape, bx.shape, cx.shape)\n", 1450 | "result = ax*bx*cx + ax\n", 1451 | "print(result)\n", 1452 | "print(result[3,2,4])\n", 1453 | "print(a[3]*b[2]*c[4]+a[3])#计算的结果是相同的" 1454 | ] 1455 | }, 1456 | { 1457 | "cell_type": "markdown", 1458 | "metadata": {}, 1459 | "source": [ 1460 | "### 线性代数\n", 1461 | "提供基本的线性代数操作\n", 1462 | "#### 简单的数组操作\n" 1463 | ] 1464 | }, 1465 | { 1466 | "cell_type": "code", 1467 | "execution_count": 35, 1468 | "metadata": { 1469 | "ExecuteTime": { 1470 | "end_time": "2018-01-06T10:14:08.238699Z", 1471 | "start_time": "2018-01-06T10:14:08.221678Z" 1472 | } 1473 | }, 1474 | "outputs": [ 1475 | { 1476 | "name": "stdout", 1477 | "output_type": "stream", 1478 | "text": [ 1479 | "[[ 1. 2.]\n", 1480 | " [ 3. 4.]]\n", 1481 | "[[-3.]\n", 1482 | " [ 4.]]\n", 1483 | "(array([ 0.+1.j, 0.-1.j]), array([[ 0.70710678+0.j , 0.70710678-0.j ],\n", 1484 | " [ 0.00000000-0.70710678j, 0.00000000+0.70710678j]]))\n" 1485 | ] 1486 | } 1487 | ], 1488 | "source": [ 1489 | "import numpy as np\n", 1490 | "a = np.array([[1.0, 2.0], [3.0, 4.0]])\n", 1491 | "print(a)\n", 1492 | "a.transpose()\n", 1493 | "np.linalg.inv(a)\n", 1494 | "u = np.eye(2) # unit 2x2 matrix; \"eye\" represents \"I\"\n", 1495 | "j = np.array([[0.0, -1.0], [1.0, 0.0]])\n", 1496 | "np.dot (j, j) # 点积\n", 1497 | "np.trace(u) # 矩阵的迹\n", 1498 | "y = np.array([[5.], [7.]])\n", 1499 | "print(np.linalg.solve(a, y))#解线性方程组\n", 1500 | "print(np.linalg.eig(j))#计算特征值\n" 1501 | ] 1502 | }, 1503 | { 1504 | "cell_type": "markdown", 1505 | "metadata": { 1506 | "ExecuteTime": { 1507 | "end_time": "2018-01-06T09:58:07.634662Z", 1508 | "start_time": "2018-01-06T09:58:07.629671Z" 1509 | } 1510 | }, 1511 | "source": [ 1512 | "### 小技巧和小贴士\n", 1513 | "#### 自动更改数组大小\n", 1514 | "在更改数组大小时,你可以省略一个维度的大小,这个维度的大小会自动计算出来" 1515 | ] 1516 | }, 1517 | { 1518 | "cell_type": "code", 1519 | "execution_count": 36, 1520 | "metadata": { 1521 | "ExecuteTime": { 1522 | "end_time": "2018-01-06T10:14:09.901009Z", 1523 | "start_time": "2018-01-06T10:14:09.894993Z" 1524 | } 1525 | }, 1526 | "outputs": [ 1527 | { 1528 | "name": "stdout", 1529 | "output_type": "stream", 1530 | "text": [ 1531 | "(2, 5, 3)\n" 1532 | ] 1533 | } 1534 | ], 1535 | "source": [ 1536 | "a = np.arange(30)\n", 1537 | "a.shape = 2,-1,3 # -1 表示自动计算大小\n", 1538 | "print(a.shape)\n" 1539 | ] 1540 | }, 1541 | { 1542 | "cell_type": "markdown", 1543 | "metadata": { 1544 | "ExecuteTime": { 1545 | "end_time": "2018-01-06T10:00:28.890122Z", 1546 | "start_time": "2018-01-06T10:00:28.885603Z" 1547 | } 1548 | }, 1549 | "source": [ 1550 | "#### 直方图\n" 1551 | ] 1552 | }, 1553 | { 1554 | "cell_type": "code", 1555 | "execution_count": 37, 1556 | "metadata": { 1557 | "ExecuteTime": { 1558 | "end_time": "2018-01-06T10:14:12.007967Z", 1559 | "start_time": "2018-01-06T10:14:11.634193Z" 1560 | } 1561 | }, 1562 | "outputs": [ 1563 | { 1564 | "data": { 1565 | "image/png": "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\n", 1566 | "text/plain": [ 1567 | "" 1568 | ] 1569 | }, 1570 | "metadata": {}, 1571 | "output_type": "display_data" 1572 | }, 1573 | { 1574 | "data": { 1575 | "image/png": "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\n", 1576 | "text/plain": [ 1577 | "" 1578 | ] 1579 | }, 1580 | "metadata": {}, 1581 | "output_type": "display_data" 1582 | } 1583 | ], 1584 | "source": [ 1585 | "import numpy as np\n", 1586 | "import matplotlib.pyplot as plt\n", 1587 | "mu,sigma=2,0.5\n", 1588 | "v=np.random.normal(mu,sigma,10000)\n", 1589 | "#matplotlib版本\n", 1590 | "plt.hist(v,bins=100,normed=1)\n", 1591 | "plt.show()\n", 1592 | "#NumPy版本\n", 1593 | "(n, bins) = np.histogram(v, bins=50, normed=True) # NumPy version (no plot)\n", 1594 | "plt.plot(.5*(bins[1:]+bins[:-1]), n)\n", 1595 | "plt.show()" 1596 | ] 1597 | } 1598 | ], 1599 | "metadata": { 1600 | "kernelspec": { 1601 | "display_name": "Python 3", 1602 | "language": "python", 1603 | "name": "python3" 1604 | }, 1605 | "language_info": { 1606 | "codemirror_mode": { 1607 | "name": "ipython", 1608 | "version": 3 1609 | }, 1610 | "file_extension": ".py", 1611 | "mimetype": "text/x-python", 1612 | "name": "python", 1613 | "nbconvert_exporter": "python", 1614 | "pygments_lexer": "ipython3", 1615 | "version": "3.5.3" 1616 | }, 1617 | "toc": { 1618 | "nav_menu": {}, 1619 | "number_sections": true, 1620 | "sideBar": true, 1621 | "skip_h1_title": false, 1622 | "toc_cell": false, 1623 | "toc_position": {}, 1624 | "toc_section_display": "block", 1625 | "toc_window_display": false 1626 | }, 1627 | "varInspector": { 1628 | "cols": { 1629 | "lenName": 16, 1630 | "lenType": 16, 1631 | "lenVar": 40 1632 | }, 1633 | "kernels_config": { 1634 | "python": { 1635 | "delete_cmd_postfix": "", 1636 | "delete_cmd_prefix": "del ", 1637 | "library": "var_list.py", 1638 | "varRefreshCmd": "print(var_dic_list())" 1639 | }, 1640 | "r": { 1641 | "delete_cmd_postfix": ") ", 1642 | "delete_cmd_prefix": "rm(", 1643 | "library": "var_list.r", 1644 | "varRefreshCmd": "cat(var_dic_list()) " 1645 | } 1646 | }, 1647 | "types_to_exclude": [ 1648 | "module", 1649 | "function", 1650 | "builtin_function_or_method", 1651 | "instance", 1652 | "_Feature" 1653 | ], 1654 | "window_display": false 1655 | } 1656 | }, 1657 | "nbformat": 4, 1658 | "nbformat_minor": 2 1659 | } 1660 | -------------------------------------------------------------------------------- /numpy/quickstart/Quickstart.md: -------------------------------------------------------------------------------- 1 | 2 | ### 基本概念 3 | Numpy 的核心是连续的多维数组。 4 | Numpy中的数组叫做```np.ndarray```,也可以使用别名```np.array```。 5 | 但这里的np.array与Python标准库中的array.array是不同的。 6 | 下列是几个```ndarray```中的重要属性: 7 | 8 | **ndarray.ndim** 9 |   数组的维数。 10 | **ndarray.shape** 11 |   数组的形状。 12 | **ndarray.size** 13 |   数组的元素个数。 14 | **ndarray.dtype** 15 |   数组的元素类型。 16 | 17 | 例子: 18 | 19 | 20 | ```python 21 | import numpy as np 22 | data=np.arange(15).reshape(3,5) 23 | print(data) 24 | print(data.shape) 25 | print(data.ndim) 26 | print(data.size) 27 | print(data.dtype.name) 28 | ``` 29 | 30 | [[ 0 1 2 3 4] 31 | [ 5 6 7 8 9] 32 | [10 11 12 13 14]] 33 | (3, 5) 34 | 2 35 | 15 36 | int32 37 | 38 | 39 | #### 数组的创建 40 | 创建数组有多种方式。你可以使用```np.array```直接用Python的元组和列表来创建。 41 | 42 | 43 | ```python 44 | import numpy as np 45 | a=np.array([1,2,3]) 46 | print(a.dtype) 47 | b=np.array([1.1,2.2,3.3]) 48 | print(b.dtype) 49 | c=np.array([(1,2,3),(4.5,5,6)]) #创建二维数组 50 | print(c) 51 | d=np.array([(1,2),(3,4)],dtype=complex) #数组的类型可以在创建时显式声明 52 | print(d) 53 | ``` 54 | 55 | int32 56 | float64 57 | [[ 1. 2. 3. ] 58 | [ 4.5 5. 6. ]] 59 | [[ 1.+0.j 2.+0.j] 60 | [ 3.+0.j 4.+0.j]] 61 | 62 | 63 | 通常,数组的元素的未知的,但是形状确实已知的。所以NumPy提供了多种创建空数组的方法。 64 | ```np.zeros``` 创建全是0的数组。 65 | ```np.ones``` 创建全是1的数组。 66 | ```np.empty``` 创建初始值是随机数的数组。 67 | 需要注意的是上述方法创建的数组元素的类型是 ```float64``` 68 | 69 | 70 | ```python 71 | e=np.zeros((3,4)) 72 | print(e) 73 | f=np.ones((2,3,4),dtype=np.int16)#可以更改数据类型 74 | print(f) 75 | g=np.empty((2,3)) 76 | print(g) 77 | ``` 78 | 79 | [[ 0. 0. 0. 0.] 80 | [ 0. 0. 0. 0.] 81 | [ 0. 0. 0. 0.]] 82 | [[[1 1 1 1] 83 | [1 1 1 1] 84 | [1 1 1 1]] 85 | 86 | [[1 1 1 1] 87 | [1 1 1 1] 88 | [1 1 1 1]]] 89 | [[ 1. 2. 3. ] 90 | [ 4.5 5. 6. ]] 91 | 92 | 93 | 为了创建列表,NumPy提供了和 ```range``` 类似的函数。 94 | ```np.arange(start,end,step)``` 95 | 96 | 97 | ```python 98 | a=np.arange(10,30,5) 99 | print(a) 100 | b=np.arange(0,2,0.3)#同样可以接收浮点数 101 | print(b) 102 | ``` 103 | 104 | [10 15 20 25] 105 | [ 0. 0.3 0.6 0.9 1.2 1.5 1.8] 106 | 107 | 108 | 在生成浮点数列表时,最好不要使用```np.arange```,而是使用```np.linspace```。 109 | ```np.linspace(start,stop,num)``` 110 | 111 | 112 | ```python 113 | np.linspace(0,2,9) 114 | ``` 115 | 116 | 117 | 118 | 119 | array([ 0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ]) 120 | 121 | 122 | 123 | #### 打印数组 124 | 当你打印一个数组时,NumPy显示数组的方式和嵌套的列表类似,但是会遵循以下布局: 125 | - 最后一维从左到右显示 126 | - 第二维到最后一维从上到下显示 127 | - 剩下的同样从上到下显示,以空行分隔 128 | 129 | 一维数组显示成一行,二维数组显示成矩阵,三维数组显示成矩阵的列表。 130 | 131 | 132 | 133 | ```python 134 | a=np.arange(6) 135 | print(a) 136 | b=np.arange(12).reshape(4,3) 137 | print(b) 138 | c=np.arange(24).reshape(2,3,4) 139 | print(c) 140 | ``` 141 | 142 | [0 1 2 3 4 5] 143 | [[ 0 1 2] 144 | [ 3 4 5] 145 | [ 6 7 8] 146 | [ 9 10 11]] 147 | [[[ 0 1 2 3] 148 | [ 4 5 6 7] 149 | [ 8 9 10 11]] 150 | 151 | [[12 13 14 15] 152 | [16 17 18 19] 153 | [20 21 22 23]]] 154 | 155 | 156 | 当一个数组元素太多,不方便显示时,NumPy会自动数组的中间部分,只显示边角的数据。 157 | 158 | 159 | ```python 160 | print(np.arange(10000)) 161 | ``` 162 | 163 | [ 0 1 2 ..., 9997 9998 9999] 164 | 165 | 166 | #### 基本操作 167 | 数组的算数计算是在元素层级运算的。计算结果会存在一个新创建的数组中。 168 | 169 | 170 | ```python 171 | import numpy as np 172 | a=np.array([20,30,40,50]) 173 | b=np.arange(4) 174 | print(b) 175 | c=a-b 176 | print(c) 177 | print(b**2) 178 | print(10*np.sin(a)) 179 | print(a<35) 180 | ``` 181 | 182 | [0 1 2 3] 183 | [20 29 38 47] 184 | [0 1 4 9] 185 | [ 9.12945251 -9.88031624 7.4511316 -2.62374854] 186 | [ True True False False] 187 | 188 | 189 | 在NumPy中```*```号仍然表示乘法,矩阵乘积用```np.dot```来计算。 190 | 191 | 192 | ```python 193 | A=np.array([(1,1),(0,1)]) 194 | B=np.array([(2,0),(3,4)]) 195 | print(A*B) 196 | print(A.dot(B)) 197 | print(np.dot(A,B)) 198 | ``` 199 | 200 | [[2 0] 201 | [0 4]] 202 | [[5 4] 203 | [3 4]] 204 | [[5 4] 205 | [3 4]] 206 | 207 | 208 | 类似于```+=```和```*=```的运算是直接在现有数组上计算的,没有创建新的数组。Numpy中的计算同样也是向上转型的,可以简单理解成浮点数和整数运算的结果是浮点数。 209 | 210 | 211 | ```python 212 | a = np.ones((2,3), dtype=int) 213 | b = np.random.random((2,3)) 214 | a*=3 215 | print(a) 216 | b += a 217 | print(b) 218 | # a += b # 浮点数不会自动转换成整数 219 | ``` 220 | 221 | [[3 3 3] 222 | [3 3 3]] 223 | [[ 3.36167598 3.63342297 3.22543331] 224 | [ 3.17992397 3.01462584 3.87847828]] 225 | 226 | 227 | ```np.ndarray```提供了许多一元操作。比如数组求和、求最大最小值等。 228 | 229 | 230 | ```python 231 | a=np.random.random((2,3)) 232 | print(a) 233 | print(a.sum()) 234 | print(a.mean()) 235 | print(a.max()) 236 | print(a.min()) 237 | ``` 238 | 239 | [[ 0.06108727 0.21625055 0.066292 ] 240 | [ 0.20271722 0.93946432 0.37747181]] 241 | 1.86328317161 242 | 0.310547195269 243 | 0.939464322779 244 | 0.0610872663968 245 | 246 | 247 | 默认的,这些一元操作是对整个数组进行计算,没有考虑到数组的形状。你可以设置```axis```参数来指定运算方向。```axis```表示第n维(从0开始)。 248 | 249 | 250 | ```python 251 | b=np.arange(12).reshape(3,4) 252 | print(b) 253 | print(b.sum(axis=0)) #对第0维的元素求和 254 | print(b.sum(axis=1)) #对第1维的元素求和 255 | print(b.min(axis=1)) 256 | print(b.cumsum(axis=1)) #对第1维的元素累加求和 257 | ``` 258 | 259 | [[ 0 1 2 3] 260 | [ 4 5 6 7] 261 | [ 8 9 10 11]] 262 | [12 15 18 21] 263 | [ 6 22 38] 264 | [0 4 8] 265 | [[ 0 1 3 6] 266 | [ 4 9 15 22] 267 | [ 8 17 27 38]] 268 | 269 | 270 | #### 广播函数 271 | NumPy提供了熟知的数学方法,如:sin、cos、exp等。在NumPy中,这些方法被称作广播函数。这些函数会对数组中的每个元素进行计算,返回计算后的数组。 272 | 273 | 274 | ```python 275 | B=np.arange(3) 276 | print(B) 277 | print(np.exp(B)) 278 | print(np.sqrt(B)) 279 | C=np.array([2,-1,4]) 280 | print(np.add(B,C)) 281 | print(B+C) 282 | 283 | ``` 284 | 285 | [0 1 2] 286 | [ 1. 2.71828183 7.3890561 ] 287 | [ 0. 1. 1.41421356] 288 | [2 0 6] 289 | [2 0 6] 290 | 291 | 292 | #### 索引、切片和迭代 293 | 一维数组可以被索引、切片和迭代,就和Python中的列表一样。 294 | 295 | 296 | ```python 297 | a=np.arange(10)**3 298 | print(a) 299 | print(a[2]) 300 | print(a[2:5]) 301 | a[:6:2]=-1000 302 | print(a) 303 | print(a[::-1]) 304 | for i in a: 305 | print(i) 306 | ``` 307 | 308 | [ 0 1 8 27 64 125 216 343 512 729] 309 | 8 310 | [ 8 27 64] 311 | [-1000 1 -1000 27 -1000 125 216 343 512 729] 312 | [ 729 512 343 216 125 -1000 27 -1000 1 -1000] 313 | -1000 314 | 1 315 | -1000 316 | 27 317 | -1000 318 | 125 319 | 216 320 | 343 321 | 512 322 | 729 323 | 324 | 325 | 多维数组可以在每一个维度有一个索引,这些索引构成元组来进行访问。 326 | 327 | 328 | ```python 329 | def f(x,y):return 10*x+y 330 | b=np.fromfunction(f,(5,4),dtype=int) 331 | print(b) 332 | print(b[2,3]) 333 | print(b[0:5,1]) 334 | print(b[:,1]) 335 | print(b[1:3,:]) 336 | 337 | ``` 338 | 339 | [[ 0 1 2 3] 340 | [10 11 12 13] 341 | [20 21 22 23] 342 | [30 31 32 33] 343 | [40 41 42 43]] 344 | 23 345 | [ 1 11 21 31 41] 346 | [ 1 11 21 31 41] 347 | [[10 11 12 13] 348 | [20 21 22 23]] 349 | 350 | 351 | ```...```表示对索引的省略。如下所示: 352 | 353 | 354 | ```python 355 | c = np.array( [[[ 0, 1, 2], # 三维数组 356 | [ 10, 12, 13]], 357 | [[100,101,102], 358 | [110,112,113]]]) 359 | print(c.shape) 360 | print(c[1,...]) # 和 c[1,:,:] 、 c[1]效果相同 361 | print(c[...,2]) # 和c[:,:,2]效果相同 362 | 363 | ``` 364 | 365 | (2, 2, 3) 366 | [[100 101 102] 367 | [110 112 113]] 368 | [[ 2 13] 369 | [102 113]] 370 | 371 | 372 | 373 | ```python 374 | 对多维数组的迭代是在第一维进行迭代的。 375 | ``` 376 | 377 | 378 | ```python 379 | for row in b: 380 | print(row) 381 | ``` 382 | 383 | [0 1 2 3] 384 | [10 11 12 13] 385 | [20 21 22 23] 386 | [30 31 32 33] 387 | [40 41 42 43] 388 | 389 | 390 | 如果需要遍历多维数组的所有元素,可以使用```flat```这个属性。 391 | 392 | 393 | ```python 394 | for element in b.flat: 395 | print(element) 396 | ``` 397 | 398 | 0 399 | 1 400 | 2 401 | 3 402 | 10 403 | 11 404 | 12 405 | 13 406 | 20 407 | 21 408 | 22 409 | 23 410 | 30 411 | 31 412 | 32 413 | 33 414 | 40 415 | 41 416 | 42 417 | 43 418 | 419 | 420 | ### 数组形状操作 421 | #### 更改数组的形状 422 | 有很多种方式可以更改数组的形状。下列的函数都没有对原数组进行更改,而是返回了一个更改后的新数组。 423 | 424 | 425 | ```python 426 | a = np.floor(10*np.random.random((3,4))) 427 | print(a.ravel()) #返回铺平后的数组 428 | print(a.reshape(6,2)) #按照指定的形状更改 429 | print(a.T)#返回转置矩阵 430 | ``` 431 | 432 | [ 5. 0. 9. 5. 5. 4. 2. 2. 3. 2. 0. 7.] 433 | [[ 5. 0.] 434 | [ 9. 5.] 435 | [ 5. 4.] 436 | [ 2. 2.] 437 | [ 3. 2.] 438 | [ 0. 7.]] 439 | [[ 5. 5. 3.] 440 | [ 0. 4. 2.] 441 | [ 9. 2. 0.] 442 | [ 5. 2. 7.]] 443 | 444 | 445 | 如果一个维度填的是-1,则该维度的形状会自动进行计算 446 | 447 | 448 | ```python 449 | print(a.reshape(3,-1)) 450 | ``` 451 | 452 | [[ 5. 0. 9. 5.] 453 | [ 5. 4. 2. 2.] 454 | [ 3. 2. 0. 7.]] 455 | 456 | 457 | #### 堆砌不同的数组 458 | 多个数组可以按照不同的轴合在一起 459 | 460 | 461 | ```python 462 | a=np.floor(10*np.random.random((2,2))) 463 | print(a) 464 | b=np.floor(10*np.random.random((2,2))) 465 | print(b) 466 | print(np.vstack((a,b)))#垂直方向堆砌 467 | print(np.hstack((a,b)))#水平方向堆砌 468 | from numpy import newaxis 469 | print(a[:,newaxis]) 470 | ``` 471 | 472 | [[ 5. 1.] 473 | [ 4. 2.]] 474 | [[ 8. 1.] 475 | [ 7. 8.]] 476 | [[ 5. 1.] 477 | [ 4. 2.] 478 | [ 8. 1.] 479 | [ 7. 8.]] 480 | [[ 5. 1. 8. 1.] 481 | [ 4. 2. 7. 8.]] 482 | [[[ 5. 1.]] 483 | 484 | [[ 4. 2.]]] 485 | 486 | 487 | #### 将一个数组划分为多个更小的数组 488 | 使用```hsplit```,```vsplit```可以对数组按照水平方向和垂直方向进行划分。 489 | 490 | 491 | ```python 492 | a=np.floor(10*np.random.random((2,12))) 493 | print(a) 494 | print(np.hsplit(a,3)) 495 | print(np.hsplit(a,(1,2,3)))#在第一列,第二列,第三列进行划分 496 | ``` 497 | 498 | [[ 7. 4. 0. 7. 5. 6. 4. 4. 4. 7. 7. 0.] 499 | [ 0. 1. 7. 7. 4. 9. 7. 0. 0. 2. 7. 5.]] 500 | [array([[ 7., 4., 0., 7.], 501 | [ 0., 1., 7., 7.]]), array([[ 5., 6., 4., 4.], 502 | [ 4., 9., 7., 0.]]), array([[ 4., 7., 7., 0.], 503 | [ 0., 2., 7., 5.]])] 504 | [array([[ 7.], 505 | [ 0.]]), array([[ 4.], 506 | [ 1.]]), array([[ 0.], 507 | [ 7.]]), array([[ 7., 5., 6., 4., 4., 4., 7., 7., 0.], 508 | [ 7., 4., 9., 7., 0., 0., 2., 7., 5.]])] 509 | 510 | 511 | ### 复制和视图 512 | 当操作数组时,数组的数据有时会复制到新数组中,有时又不会。这通常令初学者感到困难。总的来说有下面三种情况: 513 | 514 | #### 不复制 515 | 简单的赋值不会复制数组的数据。 516 | 517 | 518 | ```python 519 | a=np.arange(12) 520 | b=a 521 | print(b is a) 522 | b.shape=3,4 523 | print(a.shape) 524 | ``` 525 | 526 | True 527 | (3, 4) 528 | 529 | 530 | #### 视图和浅复制 531 | 不同的数组可以使用同一份数据,```view```函数在同一份数据上创建了新的数组对象。 532 | 533 | 534 | ```python 535 | c=a.view() 536 | print(c is a) 537 | print(c.base is a) #c是a的数据的视图 538 | print(c.flags.owndata) 539 | c.shape=6,2 540 | print(a.shape) #a的形状没有改变 541 | c[4,1]=1234 #a的数据改变了 542 | print(a) 543 | ``` 544 | 545 | False 546 | True 547 | False 548 | (3, 4) 549 | [[ 0 1 2 3] 550 | [ 4 5 6 7] 551 | [ 8 1234 10 11]] 552 | 553 | 554 | 对数组切片会返回数组的视图 555 | 556 | 557 | ```python 558 | s=a[:,1:3] 559 | s[:]=10 560 | print(a) 561 | ``` 562 | 563 | [[ 0 10 10 3] 564 | [ 4 10 10 7] 565 | [ 8 10 10 11]] 566 | 567 | 568 | #### 深复制 569 | ```copy```函数实现了对数据和数组的完全复制。 570 | 571 | 572 | ```python 573 | d=a.copy() 574 | print(d is a) 575 | print(d.base is a) 576 | d[0,0]=9999 577 | print(a) 578 | ``` 579 | 580 | False 581 | False 582 | [[ 0 10 10 3] 583 | [ 4 10 10 7] 584 | [ 8 10 10 11]] 585 | 586 | 587 | ### 多种多样的索引和索引的小技巧 588 | 相比Python的列表,NumPy提供了更多的索引功能。除了可以用整数和列表来访问数组之外,数组还可以被整型数组和布尔数组访问。 589 | #### 用数组访问数组 590 | 591 | 592 | ```python 593 | a=np.arange(12)**2 594 | i=np.array([1,1,3,8,5]) 595 | print(a[i]) 596 | j=np.array([[3,4],[8,5]]) #用二维数组来访问数组 597 | print(a[j]) #产生和访问的数组相同形状的结果 598 | ``` 599 | 600 | [ 1 1 9 64 25] 601 | [[ 9 16] 602 | [64 25]] 603 | 604 | 605 | 在时间序列的数据上寻找最大值通常会用到数组索引 606 | 607 | 608 | ```python 609 | time=np.linspace(20,145,5) 610 | data=np.sin(np.arange(20)).reshape(5,4) 611 | print(time) 612 | print(data) 613 | ind=data.argmax(axis=0)#返回按照指定轴的方向的最大值的索引 614 | time_max=time[ind] 615 | print(time_max) 616 | data_max=data[ind,range(data.shape[1])] 617 | print(data_max) 618 | ``` 619 | 620 | [ 20. 51.25 82.5 113.75 145. ] 621 | [[ 0. 0.84147098 0.90929743 0.14112001] 622 | [-0.7568025 -0.95892427 -0.2794155 0.6569866 ] 623 | [ 0.98935825 0.41211849 -0.54402111 -0.99999021] 624 | [-0.53657292 0.42016704 0.99060736 0.65028784] 625 | [-0.28790332 -0.96139749 -0.75098725 0.14987721]] 626 | [ 82.5 20. 113.75 51.25] 627 | [ 0.98935825 0.84147098 0.99060736 0.6569866 ] 628 | 629 | 630 | 你也可以使用数组索引来赋值 631 | 632 | 633 | ```python 634 | a=np.arange(5) 635 | a[[1,3,4]]=0 636 | print(a) 637 | ``` 638 | 639 | [0 0 2 0 0] 640 | 641 | 642 | 如果赋值时有重复的索引,则赋值会执行多次,留下最后一次执行的结果 643 | 644 | 645 | ```python 646 | a=np.arange(5) 647 | a[[0,0,0]]=[1,2,3] 648 | print(a) 649 | ``` 650 | 651 | [3 1 2 3 4] 652 | 653 | 654 | 但是赋值时使用```+=```时,并不会重复计算 655 | 656 | 657 | ```python 658 | a=np.arange(5) 659 | a[[0,0,0]]+=1 660 | print(a) 661 | ``` 662 | 663 | [1 1 2 3 4] 664 | 665 | 666 | 这是因为"a+=1"最终是解释成了"a=a+1" 667 | 668 | #### 用布尔数组来访问数组 669 | 通过使用布尔数组索引,我们可以选择哪些数据是需要的,哪些是不需要的。 670 | 在赋值中也非常有用。 671 | 672 | 673 | ```python 674 | a = np.arange(12).reshape(3,4) 675 | b = a > 4 676 | print(b) 677 | print(a[b]) 678 | a[b]=10 679 | print(a) 680 | ``` 681 | 682 | [[False False False False] 683 | [False True True True] 684 | [ True True True True]] 685 | [ 5 6 7 8 9 10 11] 686 | [[ 0 1 2 3] 687 | [ 4 10 10 10] 688 | [10 10 10 10]] 689 | 690 | 691 | 下面的代码用布尔数组索引产生了曼德布洛特集合的图像。 692 | 693 | 694 | ```python 695 | import numpy as np 696 | import matplotlib.pyplot as plt 697 | def mandelbrot( h,w, maxit=20 ): 698 | """Returns an image of the Mandelbrot fractal of size (h,w).""" 699 | y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ] 700 | c = x+y*1j 701 | z = c 702 | divtime = maxit + np.zeros(z.shape, dtype=int) 703 | 704 | for i in range(maxit): 705 | z = z**2 + c 706 | diverge = z*np.conj(z) > 2**2 # who is diverging 707 | div_now = diverge & (divtime==maxit) # who is diverging now 708 | divtime[div_now] = i # note when 709 | z[diverge] = 2 # avoid diverging too much 710 | 711 | return divtime 712 | plt.imshow(mandelbrot(400,400)) 713 | plt.show() 714 | ``` 715 | 716 | 717 | ![png](output_67_0.png) 718 | 719 | 720 | #### ix_()函数 721 | ix_函数被用来计算不同的向量的乘积。 722 | 723 | 724 | ```python 725 | a = np.array([2,3,4,5]) 726 | b = np.array([8,5,4]) 727 | c = np.array([5,4,6,8,3]) 728 | ax,bx,cx = np.ix_(a,b,c) 729 | print(ax) 730 | print(bx) 731 | print(cx) 732 | print(ax.shape, bx.shape, cx.shape) 733 | result = ax*bx*cx + ax 734 | print(result) 735 | print(result[3,2,4]) 736 | print(a[3]*b[2]*c[4]+a[3])#计算的结果是相同的 737 | ``` 738 | 739 | [[[2]] 740 | 741 | [[3]] 742 | 743 | [[4]] 744 | 745 | [[5]]] 746 | [[[8] 747 | [5] 748 | [4]]] 749 | [[[5 4 6 8 3]]] 750 | (4, 1, 1) (1, 3, 1) (1, 1, 5) 751 | [[[ 82 66 98 130 50] 752 | [ 52 42 62 82 32] 753 | [ 42 34 50 66 26]] 754 | 755 | [[123 99 147 195 75] 756 | [ 78 63 93 123 48] 757 | [ 63 51 75 99 39]] 758 | 759 | [[164 132 196 260 100] 760 | [104 84 124 164 64] 761 | [ 84 68 100 132 52]] 762 | 763 | [[205 165 245 325 125] 764 | [130 105 155 205 80] 765 | [105 85 125 165 65]]] 766 | 65 767 | 65 768 | 769 | 770 | ### 线性代数 771 | 提供基本的线性代数操作 772 | #### 简单的数组操作 773 | 774 | 775 | 776 | ```python 777 | import numpy as np 778 | a = np.array([[1.0, 2.0], [3.0, 4.0]]) 779 | print(a) 780 | a.transpose() 781 | np.linalg.inv(a) 782 | u = np.eye(2) # unit 2x2 matrix; "eye" represents "I" 783 | j = np.array([[0.0, -1.0], [1.0, 0.0]]) 784 | np.dot (j, j) # 点积 785 | np.trace(u) # 矩阵的迹 786 | y = np.array([[5.], [7.]]) 787 | print(np.linalg.solve(a, y))#解线性方程组 788 | print(np.linalg.eig(j))#计算特征值 789 | 790 | ``` 791 | 792 | [[ 1. 2.] 793 | [ 3. 4.]] 794 | [[-3.] 795 | [ 4.]] 796 | (array([ 0.+1.j, 0.-1.j]), array([[ 0.70710678+0.j , 0.70710678-0.j ], 797 | [ 0.00000000-0.70710678j, 0.00000000+0.70710678j]])) 798 | 799 | 800 | ### 小技巧和小贴士 801 | #### 自动更改数组大小 802 | 在更改数组大小时,你可以省略一个维度的大小,这个维度的大小会自动计算出来 803 | 804 | 805 | ```python 806 | a = np.arange(30) 807 | a.shape = 2,-1,3 # -1 表示自动计算大小 808 | print(a.shape) 809 | 810 | ``` 811 | 812 | (2, 5, 3) 813 | 814 | 815 | #### 直方图 816 | 817 | 818 | 819 | ```python 820 | import numpy as np 821 | import matplotlib.pyplot as plt 822 | mu,sigma=2,0.5 823 | v=np.random.normal(mu,sigma,10000) 824 | #matplotlib版本 825 | plt.hist(v,bins=100,normed=1) 826 | plt.show() 827 | #NumPy版本 828 | (n, bins) = np.histogram(v, bins=50, normed=True) # NumPy version (no plot) 829 | plt.plot(.5*(bins[1:]+bins[:-1]), n) 830 | plt.show() 831 | ``` 832 | 833 | 834 | ![png](output_75_0.png) 835 | 836 | 837 | 838 | ![png](output_75_1.png) 839 | 840 | -------------------------------------------------------------------------------- /numpy/quickstart/output_67_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxylpy/self_tutorial/9eefcff66d927549b3c053a9c28d30e26e578c88/numpy/quickstart/output_67_0.png -------------------------------------------------------------------------------- /numpy/quickstart/output_75_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxylpy/self_tutorial/9eefcff66d927549b3c053a9c28d30e26e578c88/numpy/quickstart/output_75_0.png -------------------------------------------------------------------------------- /numpy/quickstart/output_75_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxylpy/self_tutorial/9eefcff66d927549b3c053a9c28d30e26e578c88/numpy/quickstart/output_75_1.png -------------------------------------------------------------------------------- /pandas/ten_minutes_to_pandas/output_133_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxylpy/self_tutorial/9eefcff66d927549b3c053a9c28d30e26e578c88/pandas/ten_minutes_to_pandas/output_133_1.png -------------------------------------------------------------------------------- /pandas/ten_minutes_to_pandas/output_135_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxylpy/self_tutorial/9eefcff66d927549b3c053a9c28d30e26e578c88/pandas/ten_minutes_to_pandas/output_135_1.png -------------------------------------------------------------------------------- /pandas/ten_minutes_to_pandas/ten_minutes_to_pandas.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ```python 4 | %matplotlib inline 5 | ``` 6 | 7 | ### 导入 8 | 习惯上,我们这样导入pandas: 9 | 10 | 11 | ```python 12 | import numpy as np 13 | import pandas as pd 14 | import matplotlib.pyplot as plt 15 | ``` 16 | 17 | ### 创建对象 18 | 通过列表可以创建Series,Pandas会自动创建整型索引。 19 | 20 | 21 | ```python 22 | s=pd.Series([1,3,5,np.nan,6,8]) 23 | print(s) 24 | ``` 25 | 26 | 0 1.0 27 | 1 3.0 28 | 2 5.0 29 | 3 NaN 30 | 4 6.0 31 | 5 8.0 32 | dtype: float64 33 | 34 | 35 | 通过NumPy的数组可以创建一个DataFrame。 36 | 37 | 38 | ```python 39 | dates=pd.date_range('20130101',periods=6) 40 | print(dates) 41 | df=pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD')) 42 | print(df) 43 | ``` 44 | 45 | DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', 46 | '2013-01-05', '2013-01-06'], 47 | dtype='datetime64[ns]', freq='D') 48 | A B C D 49 | 2013-01-01 -0.653658 -0.412076 0.289240 -0.813057 50 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 51 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 52 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 53 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 54 | 2013-01-06 -0.305994 -1.372941 -2.900295 0.220700 55 | 56 | 57 | 也可以通过字典来创建DataFrame 58 | 59 | 60 | ```python 61 | df2=pd.DataFrame({'A':1., 62 | 'B':pd.Timestamp('20130102'), 63 | 'C':pd.Series(1,index=list(range(4)),dtype='float32'), 64 | 'D':np.array([3]*4,dtype='int32'), 65 | 'E':pd.Categorical(['test','train','test','train']), 66 | 'F':'foo'}) 67 | print(df2) 68 | ``` 69 | 70 | A B C D E F 71 | 0 1.0 2013-01-02 1.0 3 test foo 72 | 1 1.0 2013-01-02 1.0 3 train foo 73 | 2 1.0 2013-01-02 1.0 3 test foo 74 | 3 1.0 2013-01-02 1.0 3 train foo 75 | 76 | 77 | 设置了特定的dtypes 78 | 79 | 80 | ```python 81 | df2.dtypes 82 | ``` 83 | 84 | 85 | 86 | 87 | A float64 88 | B datetime64[ns] 89 | C float32 90 | D int32 91 | E category 92 | F object 93 | dtype: object 94 | 95 | 96 | 97 | ### 查看数据 98 | 查看数据的顶部和底部 99 | 100 | 101 | ```python 102 | print(df.head()) 103 | print(df.tail(3)) 104 | ``` 105 | 106 | A B C D 107 | 2013-01-01 -0.653658 -0.412076 0.289240 -0.813057 108 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 109 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 110 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 111 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 112 | A B C D 113 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 114 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 115 | 2013-01-06 -0.305994 -1.372941 -2.900295 0.220700 116 | 117 | 118 | 查看索引,列名,以及纯的NumPy数据 119 | 120 | 121 | ```python 122 | print(df.index) 123 | print(df.columns) 124 | print(df.values) 125 | ``` 126 | 127 | DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', 128 | '2013-01-05', '2013-01-06'], 129 | dtype='datetime64[ns]', freq='D') 130 | Index(['A', 'B', 'C', 'D'], dtype='object') 131 | [[ -6.53658042e-01 -4.12076297e-01 2.89239645e-01 -8.13057346e-01] 132 | [ -2.86361403e-04 -1.25775963e+00 -1.23254938e+00 -8.99191307e-01] 133 | [ 4.04229751e-01 -8.80146291e-01 -1.59352637e+00 1.14169486e+00] 134 | [ 1.00815285e-01 1.14370966e+00 4.67192499e-01 1.49516032e-02] 135 | [ 9.44030631e-01 -6.53507646e-01 5.43886068e-03 3.16151200e-01] 136 | [ -3.05994200e-01 -1.37294092e+00 -2.90029481e+00 2.20700202e-01]] 137 | 138 | 139 | ```DataFrame.describe()```提供了便捷的数据统计 140 | 141 | 142 | ```python 143 | print(df.describe()) 144 | ``` 145 | 146 | A B C D 147 | count 6.000000 6.000000 6.000000 6.000000 148 | mean 0.081523 -0.572120 -0.827417 -0.003125 149 | std 0.556019 0.914615 1.316394 0.764447 150 | min -0.653658 -1.372941 -2.900295 -0.899191 151 | 25% -0.229567 -1.163356 -1.503282 -0.606055 152 | 50% 0.050264 -0.766827 -0.613555 0.117826 153 | 75% 0.328376 -0.472434 0.218289 0.292288 154 | max 0.944031 1.143710 0.467192 1.141695 155 | 156 | 157 | 转置矩阵 158 | 159 | 160 | ```python 161 | print(df.T) 162 | ``` 163 | 164 | 2013-01-01 2013-01-02 2013-01-03 2013-01-04 2013-01-05 2013-01-06 165 | A -0.653658 -0.000286 0.404230 0.100815 0.944031 -0.305994 166 | B -0.412076 -1.257760 -0.880146 1.143710 -0.653508 -1.372941 167 | C 0.289240 -1.232549 -1.593526 0.467192 0.005439 -2.900295 168 | D -0.813057 -0.899191 1.141695 0.014952 0.316151 0.220700 169 | 170 | 171 | 沿某一轴排序 172 | 173 | 174 | ```python 175 | print(df.sort_index(axis=1,ascending=False)) 176 | ``` 177 | 178 | D C B A 179 | 2013-01-01 -0.813057 0.289240 -0.412076 -0.653658 180 | 2013-01-02 -0.899191 -1.232549 -1.257760 -0.000286 181 | 2013-01-03 1.141695 -1.593526 -0.880146 0.404230 182 | 2013-01-04 0.014952 0.467192 1.143710 0.100815 183 | 2013-01-05 0.316151 0.005439 -0.653508 0.944031 184 | 2013-01-06 0.220700 -2.900295 -1.372941 -0.305994 185 | 186 | 187 | 按照值进行排序 188 | 189 | 190 | ```python 191 | print(df.sort_values(by='B')) 192 | ``` 193 | 194 | A B C D 195 | 2013-01-06 -0.305994 -1.372941 -2.900295 0.220700 196 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 197 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 198 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 199 | 2013-01-01 -0.653658 -0.412076 0.289240 -0.813057 200 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 201 | 202 | 203 | ### 数据选择 204 | **注意:**尽管Python标准库和NumPy的语句在选择和设置数据时更直观和方便交互。但是在生产环境中,我们更建议使用Pandas的数据访问函数:```.at, .iat, .loc, .iloc, .ix``` 205 | 206 | #### 数据获取 207 | 选择一列,返回Series。等同于df.A 208 | 209 | 210 | ```python 211 | df['A'] 212 | ``` 213 | 214 | 215 | 216 | 217 | 2013-01-01 -0.653658 218 | 2013-01-02 -0.000286 219 | 2013-01-03 0.404230 220 | 2013-01-04 0.100815 221 | 2013-01-05 0.944031 222 | 2013-01-06 -0.305994 223 | Freq: D, Name: A, dtype: float64 224 | 225 | 226 | 227 | 使用```[]```来切分多行数据 228 | 229 | 230 | ```python 231 | print(df[0:3]) 232 | print(df['20130102':'20130104']) 233 | ``` 234 | 235 | A B C D 236 | 2013-01-01 -0.653658 -0.412076 0.289240 -0.813057 237 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 238 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 239 | A B C D 240 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 241 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 242 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 243 | 244 | 245 | #### 根据标签选择 246 | 使用标签来得到特定的一行 247 | 248 | 249 | ```python 250 | df.loc[dates[0]] 251 | ``` 252 | 253 | 254 | 255 | 256 | A -0.653658 257 | B -0.412076 258 | C 0.289240 259 | D -0.813057 260 | Name: 2013-01-01 00:00:00, dtype: float64 261 | 262 | 263 | 264 | 使用标签来得到多个指定的列 265 | 266 | 267 | ```python 268 | print(df.loc[:,['A','B']]) 269 | ``` 270 | 271 | A B 272 | 2013-01-01 -0.653658 -0.412076 273 | 2013-01-02 -0.000286 -1.257760 274 | 2013-01-03 0.404230 -0.880146 275 | 2013-01-04 0.100815 1.143710 276 | 2013-01-05 0.944031 -0.653508 277 | 2013-01-06 -0.305994 -1.372941 278 | 279 | 280 | 用标签来切片时,端点的值都是被包含在内的 281 | 282 | 283 | ```python 284 | print(df.loc['20130102':'20130104',['A','B']]) 285 | ``` 286 | 287 | A B 288 | 2013-01-02 -0.000286 -1.257760 289 | 2013-01-03 0.404230 -0.880146 290 | 2013-01-04 0.100815 1.143710 291 | 292 | 293 | 选择的返回值可以降低维度 294 | 295 | 296 | ```python 297 | df.loc['20130102',['A','B']] 298 | ``` 299 | 300 | 301 | 302 | 303 | A -0.000286 304 | B -1.257760 305 | Name: 2013-01-02 00:00:00, dtype: float64 306 | 307 | 308 | 309 | 选择一个标量 310 | 311 | 312 | ```python 313 | df.loc[dates[0],'A'] 314 | ``` 315 | 316 | 317 | 318 | 319 | -0.65365804231862046 320 | 321 | 322 | 323 | 快速获取一个标量(与上面相同) 324 | 325 | 326 | ```python 327 | df.at[dates[0],'A'] 328 | ``` 329 | 330 | 331 | 332 | 333 | -0.65365804231862046 334 | 335 | 336 | 337 | #### 根据位置进行选择 338 | 根据整数下标来选择数据 339 | 340 | 341 | ```python 342 | df.iloc[3] 343 | ``` 344 | 345 | 346 | 347 | 348 | A 0.100815 349 | B 1.143710 350 | C 0.467192 351 | D 0.014952 352 | Name: 2013-01-04 00:00:00, dtype: float64 353 | 354 | 355 | 356 | 用整数来切片,类似于Python标准库和NumPy 357 | 358 | 359 | ```python 360 | print(df.iloc[3:5,0:2]) 361 | ``` 362 | 363 | A B 364 | 2013-01-04 0.100815 1.143710 365 | 2013-01-05 0.944031 -0.653508 366 | 367 | 368 | 用整数列表来进行选择,与Python标准库和NumPy类似 369 | 370 | 371 | ```python 372 | print(df.iloc[[1,2,4],[0,2]]) 373 | ``` 374 | 375 | A C 376 | 2013-01-02 -0.000286 -1.232549 377 | 2013-01-03 0.404230 -1.593526 378 | 2013-01-05 0.944031 0.005439 379 | 380 | 381 | 对行进行切片选择 382 | 383 | 384 | ```python 385 | print(df.iloc[1:3,:]) 386 | ``` 387 | 388 | A B C D 389 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 390 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 391 | 392 | 393 | 对列进行切片选择 394 | 395 | 396 | ```python 397 | print(df.iloc[:,1:3]) 398 | ``` 399 | 400 | B C 401 | 2013-01-01 -0.412076 0.289240 402 | 2013-01-02 -1.257760 -1.232549 403 | 2013-01-03 -0.880146 -1.593526 404 | 2013-01-04 1.143710 0.467192 405 | 2013-01-05 -0.653508 0.005439 406 | 2013-01-06 -1.372941 -2.900295 407 | 408 | 409 | 获取某个标量 410 | 411 | 412 | ```python 413 | df.iloc[1,1] 414 | ``` 415 | 416 | 417 | 418 | 419 | -1.257759630175423 420 | 421 | 422 | 423 | 快速地获取某个标量(与上面的函数相同) 424 | 425 | 426 | ```python 427 | df.iat[1,1] 428 | ``` 429 | 430 | 431 | 432 | 433 | -1.257759630175423 434 | 435 | 436 | 437 | #### 布尔索引 438 | 使用某列值来选择数据 439 | 440 | 441 | ```python 442 | print(df[df.A>0]) 443 | ``` 444 | 445 | A B C D 446 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 447 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 448 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 449 | 450 | 451 | 从DataFrame中选择满足某条件的数据 452 | 453 | 454 | ```python 455 | print(df[df>0]) 456 | ``` 457 | 458 | A B C D 459 | 2013-01-01 NaN NaN 0.289240 NaN 460 | 2013-01-02 NaN NaN NaN NaN 461 | 2013-01-03 0.404230 NaN NaN 1.141695 462 | 2013-01-04 0.100815 1.14371 0.467192 0.014952 463 | 2013-01-05 0.944031 NaN 0.005439 0.316151 464 | 2013-01-06 NaN NaN NaN 0.220700 465 | 466 | 467 | 使用```isin()```函数来过滤数据 468 | 469 | 470 | ```python 471 | df2=df.copy() 472 | df2['E']=['one','one','two','three','four','three'] 473 | print(df2) 474 | print(df2[df2['E'].isin(['two','four'])]) 475 | ``` 476 | 477 | A B C D E 478 | 2013-01-01 -0.653658 -0.412076 0.289240 -0.813057 one 479 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 one 480 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 two 481 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 three 482 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 four 483 | 2013-01-06 -0.305994 -1.372941 -2.900295 0.220700 three 484 | A B C D E 485 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 two 486 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 four 487 | 488 | 489 | #### 设置数据 490 | 设置一个新列并设置索引 491 | 492 | 493 | ```python 494 | s1=pd.Series([1,2,3,4,5,6],index=pd.date_range('20130102',periods=6)) 495 | df['F']=s1 496 | s1 497 | ``` 498 | 499 | 500 | 501 | 502 | 2013-01-02 1 503 | 2013-01-03 2 504 | 2013-01-04 3 505 | 2013-01-05 4 506 | 2013-01-06 5 507 | 2013-01-07 6 508 | Freq: D, dtype: int64 509 | 510 | 511 | 512 | 根据标签来设置值 513 | 514 | 515 | ```python 516 | df.at[dates[0],'A']=0 517 | print(df) 518 | ``` 519 | 520 | A B C D F 521 | 2013-01-01 0.000000 -0.412076 0.289240 -0.813057 NaN 522 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 1.0 523 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 2.0 524 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 3.0 525 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 4.0 526 | 2013-01-06 -0.305994 -1.372941 -2.900295 0.220700 5.0 527 | 528 | 529 | 根据位置的来设置值 530 | 531 | 532 | ```python 533 | df.iat[0,1]=0 534 | print(df) 535 | ``` 536 | 537 | A B C D F 538 | 2013-01-01 0.000000 0.000000 0.289240 -0.813057 NaN 539 | 2013-01-02 -0.000286 -1.257760 -1.232549 -0.899191 1.0 540 | 2013-01-03 0.404230 -0.880146 -1.593526 1.141695 2.0 541 | 2013-01-04 0.100815 1.143710 0.467192 0.014952 3.0 542 | 2013-01-05 0.944031 -0.653508 0.005439 0.316151 4.0 543 | 2013-01-06 -0.305994 -1.372941 -2.900295 0.220700 5.0 544 | 545 | 546 | 使用NumPy数组来赋值 547 | 548 | 549 | ```python 550 | df.loc[:,'D']=np.array([5]*len(df)) 551 | print(df) 552 | ``` 553 | 554 | A B C D F 555 | 2013-01-01 0.000000 0.000000 0.289240 5 NaN 556 | 2013-01-02 -0.000286 -1.257760 -1.232549 5 1.0 557 | 2013-01-03 0.404230 -0.880146 -1.593526 5 2.0 558 | 2013-01-04 0.100815 1.143710 0.467192 5 3.0 559 | 2013-01-05 0.944031 -0.653508 0.005439 5 4.0 560 | 2013-01-06 -0.305994 -1.372941 -2.900295 5 5.0 561 | 562 | 563 | 在过滤的同时进行赋值 564 | 565 | 566 | ```python 567 | df2=df.copy() 568 | df2[df2>0]=-df2 569 | print(df2) 570 | ``` 571 | 572 | A B C D F 573 | 2013-01-01 0.000000 0.000000 -0.289240 -5 NaN 574 | 2013-01-02 -0.000286 -1.257760 -1.232549 -5 -1.0 575 | 2013-01-03 -0.404230 -0.880146 -1.593526 -5 -2.0 576 | 2013-01-04 -0.100815 -1.143710 -0.467192 -5 -3.0 577 | 2013-01-05 -0.944031 -0.653508 -0.005439 -5 -4.0 578 | 2013-01-06 -0.305994 -1.372941 -2.900295 -5 -5.0 579 | 580 | 581 | ### 处理缺失数据 582 | Pandas主要使用```np.nan```来表示缺失数据。这个值不会加入在计算中。 583 | 重新索引允许你对某一轴的索引进行更改/添加/删除操作。这会返回操作数据的拷贝对象。 584 | 585 | 586 | ```python 587 | df1=df.reindex(index=dates[0:4],columns=list(df.columns)+['E']) 588 | df1.loc[dates[0]:dates[1],'E']=1 589 | print(df1) 590 | ``` 591 | 592 | A B C D F E 593 | 2013-01-01 0.000000 0.000000 0.289240 5 NaN 1.0 594 | 2013-01-02 -0.000286 -1.257760 -1.232549 5 1.0 1.0 595 | 2013-01-03 0.404230 -0.880146 -1.593526 5 2.0 NaN 596 | 2013-01-04 0.100815 1.143710 0.467192 5 3.0 NaN 597 | 598 | 599 | 删除含有缺失数据的行 600 | 601 | 602 | ```python 603 | print(df1.dropna(how='any')) 604 | ``` 605 | 606 | A B C D F E 607 | 2013-01-02 -0.000286 -1.25776 -1.232549 5 1.0 1.0 608 | 609 | 610 | 填充缺失数据 611 | 612 | 613 | ```python 614 | print(df1.fillna(value=5)) 615 | ``` 616 | 617 | A B C D F E 618 | 2013-01-01 0.000000 0.000000 0.289240 5 5.0 1.0 619 | 2013-01-02 -0.000286 -1.257760 -1.232549 5 1.0 1.0 620 | 2013-01-03 0.404230 -0.880146 -1.593526 5 2.0 5.0 621 | 2013-01-04 0.100815 1.143710 0.467192 5 3.0 5.0 622 | 623 | 624 | 获取数据中是```nan```的位置 625 | 626 | 627 | ```python 628 | print(pd.isnull(df1)) 629 | ``` 630 | 631 | A B C D F E 632 | 2013-01-01 False False False False True False 633 | 2013-01-02 False False False False False False 634 | 2013-01-03 False False False False False True 635 | 2013-01-04 False False False False False True 636 | 637 | 638 | ### 基础操作 639 | #### 基本的统计 640 | 操作默认排除了缺失的数据 641 | 执行一个描述性的统计 642 | 643 | 644 | ```python 645 | df.mean() 646 | ``` 647 | 648 | 649 | 650 | 651 | A 0.190466 652 | B -0.503441 653 | C -0.827417 654 | D 5.000000 655 | F 3.000000 656 | dtype: float64 657 | 658 | 659 | 660 | 在另外的轴执行该操作 661 | 662 | 663 | ```python 664 | df.mean(1) 665 | ``` 666 | 667 | 668 | 669 | 670 | 2013-01-01 1.322310 671 | 2013-01-02 0.701881 672 | 2013-01-03 0.986111 673 | 2013-01-04 1.942343 674 | 2013-01-05 1.859192 675 | 2013-01-06 1.084154 676 | Freq: D, dtype: float64 677 | 678 | 679 | 680 | 对不同维度数据的操作需要进行校准。Pandas会自动的在指定的维数上应用广播。 681 | 682 | 683 | ```python 684 | s=pd.Series([1,3,5,np.nan,6,8],index=dates).shift(2) 685 | print(s) 686 | print(df.sub(s,axis='index')) 687 | ``` 688 | 689 | 2013-01-01 NaN 690 | 2013-01-02 NaN 691 | 2013-01-03 1.0 692 | 2013-01-04 3.0 693 | 2013-01-05 5.0 694 | 2013-01-06 NaN 695 | Freq: D, dtype: float64 696 | A B C D F 697 | 2013-01-01 NaN NaN NaN NaN NaN 698 | 2013-01-02 NaN NaN NaN NaN NaN 699 | 2013-01-03 -0.595770 -1.880146 -2.593526 4.0 1.0 700 | 2013-01-04 -2.899185 -1.856290 -2.532808 2.0 0.0 701 | 2013-01-05 -4.055969 -5.653508 -4.994561 0.0 -1.0 702 | 2013-01-06 NaN NaN NaN NaN NaN 703 | 704 | 705 | #### 应用函数 706 | 对数据应用函数 707 | 708 | 709 | ```python 710 | print(df.apply(np.cumsum)) 711 | df.apply(lambda x:x.max()-x.min()) 712 | ``` 713 | 714 | A B C D F 715 | 2013-01-01 0.000000 0.000000 0.289240 5 NaN 716 | 2013-01-02 -0.000286 -1.257760 -0.943310 10 1.0 717 | 2013-01-03 0.403943 -2.137906 -2.536836 15 3.0 718 | 2013-01-04 0.504759 -0.994196 -2.069644 20 6.0 719 | 2013-01-05 1.448789 -1.647704 -2.064205 25 10.0 720 | 2013-01-06 1.142795 -3.020645 -4.964500 30 15.0 721 | 722 | 723 | 724 | 725 | 726 | A 1.250025 727 | B 2.516651 728 | C 3.367487 729 | D 0.000000 730 | F 4.000000 731 | dtype: float64 732 | 733 | 734 | 735 | #### 直方图 736 | 737 | 738 | ```python 739 | s=pd.Series(np.random.randint(0,7,size=10)) 740 | print(s) 741 | print(s.value_counts()) 742 | ``` 743 | 744 | 0 0 745 | 1 0 746 | 2 4 747 | 3 1 748 | 4 6 749 | 5 6 750 | 6 4 751 | 7 3 752 | 8 5 753 | 9 1 754 | dtype: int32 755 | 6 2 756 | 4 2 757 | 1 2 758 | 0 2 759 | 5 1 760 | 3 1 761 | dtype: int64 762 | 763 | 764 | #### 字符串函数 765 | 在下面的代码中,Series可以在```str```属性中应用许多字符处理函数,可以更方便的处理数据中的每个元素。需要注意的是模式识别默认使用正则表达式。 766 | 767 | 768 | ```python 769 | s=pd.Series(['A','B','C','Aaba','Baca',np.nan,'CABA','dog','cat']) 770 | s.str.lower() 771 | ``` 772 | 773 | 774 | 775 | 776 | 0 a 777 | 1 b 778 | 2 c 779 | 3 aaba 780 | 4 baca 781 | 5 NaN 782 | 6 caba 783 | 7 dog 784 | 8 cat 785 | dtype: object 786 | 787 | 788 | 789 | ### 数据合并 790 | #### 数据拼接 791 | Pandas提供了许多工具来根据索引逻辑和线性代数关系组合Series、DataFrame和Panel。 792 | 用```concat()```组合Pandas数据 793 | 794 | 795 | ```python 796 | df=pd.DataFrame(np.random.randn(10,4)) 797 | print(df) 798 | pieces=[df[:3],df[3:7],df[7:]] 799 | print(pd.concat(pieces)) 800 | ``` 801 | 802 | 0 1 2 3 803 | 0 0.868667 -1.127783 -1.339226 -0.018955 804 | 1 2.154827 -0.183290 0.346383 -0.535674 805 | 2 0.539159 0.598349 -0.959137 -1.371542 806 | 3 0.526160 -0.675516 0.329515 2.741801 807 | 4 -0.672261 0.277084 0.246108 -0.058672 808 | 5 1.345204 0.267244 -0.976797 0.258268 809 | 6 -1.134643 0.736464 0.632367 0.355589 810 | 7 -0.388383 0.573309 -0.920222 1.232245 811 | 8 -0.394164 -0.492838 -0.036512 0.965029 812 | 9 -0.219411 1.003898 -0.033570 1.059801 813 | 0 1 2 3 814 | 0 0.868667 -1.127783 -1.339226 -0.018955 815 | 1 2.154827 -0.183290 0.346383 -0.535674 816 | 2 0.539159 0.598349 -0.959137 -1.371542 817 | 3 0.526160 -0.675516 0.329515 2.741801 818 | 4 -0.672261 0.277084 0.246108 -0.058672 819 | 5 1.345204 0.267244 -0.976797 0.258268 820 | 6 -1.134643 0.736464 0.632367 0.355589 821 | 7 -0.388383 0.573309 -0.920222 1.232245 822 | 8 -0.394164 -0.492838 -0.036512 0.965029 823 | 9 -0.219411 1.003898 -0.033570 1.059801 824 | 825 | 826 | #### 数据关联 827 | SQL形式 828 | 829 | 830 | ```python 831 | left=pd.DataFrame({'key':['foo','foo'],'lval':[1,2]}) 832 | right=pd.DataFrame({'key':['foo','foo'],'rval':[4,5]}) 833 | print(left) 834 | print(right) 835 | print(pd.merge(left,right,on='key')) 836 | ``` 837 | 838 | key lval 839 | 0 foo 1 840 | 1 foo 2 841 | key rval 842 | 0 foo 4 843 | 1 foo 5 844 | key lval rval 845 | 0 foo 1 4 846 | 1 foo 1 5 847 | 2 foo 2 4 848 | 3 foo 2 5 849 | 850 | 851 | 852 | ```python 853 | left=pd.DataFrame({'key':['foo','bar'],'lval':[1,2]}) 854 | right=pd.DataFrame({'key':['foo','bar'],'rval':[4,5]}) 855 | print(left) 856 | print(right) 857 | print(pd.merge(left,right,on='key')) 858 | ``` 859 | 860 | key lval 861 | 0 foo 1 862 | 1 bar 2 863 | key rval 864 | 0 foo 4 865 | 1 bar 5 866 | key lval rval 867 | 0 foo 1 4 868 | 1 bar 2 5 869 | 870 | 871 | #### 添加数据(Append) 872 | 给DataFrame添加行 873 | 874 | 875 | ```python 876 | df=pd.DataFrame(np.random.randn(8,4),columns=['A','B','C','D']) 877 | print(df) 878 | s=df.iloc[3] 879 | print(df.append(s,ignore_index=True)) 880 | ``` 881 | 882 | A B C D 883 | 0 -0.379925 -1.017542 -0.189007 -0.428325 884 | 1 -0.276408 -0.715901 -1.319698 -0.222887 885 | 2 1.107723 0.353094 0.815195 -1.440487 886 | 3 -0.033881 0.514738 0.290243 -0.573637 887 | 4 0.425776 -0.074674 -0.002662 0.963586 888 | 5 1.982210 1.058390 -0.605711 0.338158 889 | 6 0.444923 0.802376 1.287365 -0.076757 890 | 7 1.079877 0.937892 1.511644 -1.344911 891 | A B C D 892 | 0 -0.379925 -1.017542 -0.189007 -0.428325 893 | 1 -0.276408 -0.715901 -1.319698 -0.222887 894 | 2 1.107723 0.353094 0.815195 -1.440487 895 | 3 -0.033881 0.514738 0.290243 -0.573637 896 | 4 0.425776 -0.074674 -0.002662 0.963586 897 | 5 1.982210 1.058390 -0.605711 0.338158 898 | 6 0.444923 0.802376 1.287365 -0.076757 899 | 7 1.079877 0.937892 1.511644 -1.344911 900 | 8 -0.033881 0.514738 0.290243 -0.573637 901 | 902 | 903 | ### 分组 904 | 分组包含以下的一个或多个流程: 905 | - 分组 根据某种标准分组数据 906 | - 应用 对每个组应用一个函数 907 | - 组合 把分组的结果组合成一个整体结构 908 | 909 | 910 | ```python 911 | df=pd.DataFrame({'A':['foo','bar','foo','bar','foo','bar','foo','foo'],'B' : ['one', 'one', 'two', 'three', 912 | 'two', 'two', 'one', 'three'], 913 | 'C' : np.random.randn(8), 914 | 'D' : np.random.randn(8)}) 915 | print(df) 916 | ``` 917 | 918 | A B C D 919 | 0 foo one 0.596282 0.822393 920 | 1 bar one -1.426678 0.106148 921 | 2 foo two -0.776830 -0.496158 922 | 3 bar three 0.954765 1.579897 923 | 4 foo two -0.127376 -0.793390 924 | 5 bar two -0.231712 -0.055958 925 | 6 foo one 0.576690 0.757426 926 | 7 foo three -1.365990 -1.358562 927 | 928 | 929 | 分组并对分组后的结果求和 930 | 931 | 932 | ```python 933 | print(df.groupby('A').sum()) 934 | ``` 935 | 936 | C D 937 | A 938 | bar -0.703626 1.630087 939 | foo -1.097224 -1.068291 940 | 941 | 942 | 根据多个列进行分组可以如下操作 943 | 944 | 945 | ```python 946 | print(df.groupby(['A','B']).sum()) 947 | ``` 948 | 949 | C D 950 | A B 951 | bar one -1.426678 0.106148 952 | three 0.954765 1.579897 953 | two -0.231712 -0.055958 954 | foo one 1.172971 1.579818 955 | three -1.365990 -1.358562 956 | two -0.904206 -1.289548 957 | 958 | 959 | ### 改变数据形状 960 | #### 压缩 961 | 962 | 963 | ```python 964 | tuples = list(zip(*[['bar', 'bar', 'baz', 'baz', 965 | 'foo', 'foo', 'qux', 'qux'], 966 | ['one', 'two', 'one', 'two', 967 | 'one', 'two', 'one', 'two']])) 968 | print(tuples) 969 | index=pd.MultiIndex.from_tuples(tuples,names=['first','second']) 970 | df=pd.DataFrame(np.random.randn(8,2),index=index,columns=['A','B']) 971 | df2 = df[:4] 972 | print(df2) 973 | ``` 974 | 975 | [('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')] 976 | A B 977 | first second 978 | bar one -0.482216 -1.720165 979 | two -1.788449 -0.475704 980 | baz one -0.757266 -0.026047 981 | two -1.799689 -0.641557 982 | 983 | 984 | ```stack()```函数压缩了这个DataFrame中的一列 985 | 986 | 987 | ```python 988 | stacked=df2.stack() 989 | stacked 990 | ``` 991 | 992 | 993 | 994 | 995 | first second 996 | bar one A -0.482216 997 | B -1.720165 998 | two A -1.788449 999 | B -0.475704 1000 | baz one A -0.757266 1001 | B -0.026047 1002 | two A -1.799689 1003 | B -0.641557 1004 | dtype: float64 1005 | 1006 | 1007 | 1008 | 对于压缩之后的DataFrame,能够使用和```stack()```函数相反的```unstack()```函数,默认会解压缩最后一列 1009 | 1010 | 1011 | ```python 1012 | print(stacked.unstack()) 1013 | print(stacked.unstack(1)) 1014 | print(stacked.unstack(0)) 1015 | ``` 1016 | 1017 | A B 1018 | first second 1019 | bar one -0.482216 -1.720165 1020 | two -1.788449 -0.475704 1021 | baz one -0.757266 -0.026047 1022 | two -1.799689 -0.641557 1023 | second one two 1024 | first 1025 | bar A -0.482216 -1.788449 1026 | B -1.720165 -0.475704 1027 | baz A -0.757266 -1.799689 1028 | B -0.026047 -0.641557 1029 | first bar baz 1030 | second 1031 | one A -0.482216 -0.757266 1032 | B -1.720165 -0.026047 1033 | two A -1.788449 -1.799689 1034 | B -0.475704 -0.641557 1035 | 1036 | 1037 | #### 数据透视表 1038 | 1039 | 1040 | ```python 1041 | df=pd.DataFrame({'A':['one','one','two','three']*3, 1042 | 'B':['A','B','C']*4, 1043 | 'C':['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2, 1044 | 'D':np.random.randn(12), 1045 | 'E':np.random.randn(12)}) 1046 | print(df) 1047 | ``` 1048 | 1049 | A B C D E 1050 | 0 one A foo -0.652781 -0.720116 1051 | 1 one B foo -0.515266 1.109243 1052 | 2 two C foo 0.724732 -0.012487 1053 | 3 three A bar 1.591435 -0.949670 1054 | 4 one B bar 0.596480 -0.403556 1055 | 5 one C bar -2.191866 0.291499 1056 | 6 two A foo -0.835479 -0.749321 1057 | 7 three B foo 0.147051 -0.299110 1058 | 8 one C foo 0.519447 -0.016910 1059 | 9 one A bar 0.482567 -2.322476 1060 | 10 two B bar 0.350926 0.135206 1061 | 11 three C bar 0.731305 -1.064031 1062 | 1063 | 1064 | 我们可以非常简单的用上面的数据生成一张数据透视表: 1065 | 1066 | 1067 | ```python 1068 | print(pd.pivot_table(df,values='D',index=['A','B'],columns=['C'])) 1069 | ``` 1070 | 1071 | C bar foo 1072 | A B 1073 | one A 0.482567 -0.652781 1074 | B 0.596480 -0.515266 1075 | C -2.191866 0.519447 1076 | three A 1.591435 NaN 1077 | B NaN 0.147051 1078 | C 0.731305 NaN 1079 | two A NaN -0.835479 1080 | B 0.350926 NaN 1081 | C NaN 0.724732 1082 | 1083 | 1084 | ### 时间序列 1085 | Pandas拥有易用、强大且高效的方法来在频率变换中执行重采样操作(例如:把秒级别的数据转换成5分钟级别的数据)。这通常在金融应用中使用,但不仅限于金融应用。 1086 | 1087 | 1088 | ```python 1089 | rng=pd.date_range('1/1/2012',periods=100,freq='S') 1090 | ts=pd.Series(np.random.randint(0,500,len(rng)),index=rng) 1091 | ts.resample('5Min').sum() 1092 | 1093 | ``` 1094 | 1095 | 1096 | 1097 | 1098 | 2012-01-01 25308 1099 | Freq: 5T, dtype: int32 1100 | 1101 | 1102 | 1103 | 表现时区 1104 | 1105 | 1106 | ```python 1107 | rng=pd.date_range('3/6/2012 00:00',periods=5,freq='D') 1108 | ts=pd.Series(np.random.randn(len(rng)),rng) 1109 | print(ts) 1110 | ts_utc=ts.tz_localize('UTC') 1111 | ts_utc 1112 | ``` 1113 | 1114 | 2012-03-06 1.228351 1115 | 2012-03-07 -0.699147 1116 | 2012-03-08 -0.094176 1117 | 2012-03-09 1.070865 1118 | 2012-03-10 2.647150 1119 | Freq: D, dtype: float64 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 2012-03-06 00:00:00+00:00 1.228351 1126 | 2012-03-07 00:00:00+00:00 -0.699147 1127 | 2012-03-08 00:00:00+00:00 -0.094176 1128 | 2012-03-09 00:00:00+00:00 1.070865 1129 | 2012-03-10 00:00:00+00:00 2.647150 1130 | Freq: D, dtype: float64 1131 | 1132 | 1133 | 1134 | 转换到其他时区 1135 | 1136 | 1137 | ```python 1138 | ts_utc.tz_convert('US/Eastern') 1139 | ``` 1140 | 1141 | 1142 | 1143 | 1144 | 2012-03-05 19:00:00-05:00 1.228351 1145 | 2012-03-06 19:00:00-05:00 -0.699147 1146 | 2012-03-07 19:00:00-05:00 -0.094176 1147 | 2012-03-08 19:00:00-05:00 1.070865 1148 | 2012-03-09 19:00:00-05:00 2.647150 1149 | Freq: D, dtype: float64 1150 | 1151 | 1152 | 1153 | 转换时间间隔的表现形式 1154 | 1155 | 1156 | ```python 1157 | rng=pd.date_range('1/1/2012',periods=5,freq='M') 1158 | ts=pd.Series(np.random.randn(len(rng)),index=rng) 1159 | print(ts) 1160 | ps=ts.to_period() 1161 | print(ps) 1162 | ps.to_timestamp() 1163 | ``` 1164 | 1165 | 2012-01-31 -0.046642 1166 | 2012-02-29 0.164101 1167 | 2012-03-31 0.249671 1168 | 2012-04-30 0.499200 1169 | 2012-05-31 0.008723 1170 | Freq: M, dtype: float64 1171 | 2012-01 -0.046642 1172 | 2012-02 0.164101 1173 | 2012-03 0.249671 1174 | 2012-04 0.499200 1175 | 2012-05 0.008723 1176 | Freq: M, dtype: float64 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 2012-01-01 -0.046642 1183 | 2012-02-01 0.164101 1184 | 2012-03-01 0.249671 1185 | 2012-04-01 0.499200 1186 | 2012-05-01 0.008723 1187 | Freq: MS, dtype: float64 1188 | 1189 | 1190 | 1191 | ### 标签数据 1192 | Pandas可以在DataFrame中包含标签数据。 1193 | 1194 | 1195 | ```python 1196 | df=pd.DataFrame({'id':[1,2,3,4,5,6],'raw_grade':['a','b','b','a','a','e']}) 1197 | ``` 1198 | 1199 | 将原始数据转换成标签数据 1200 | 1201 | 1202 | ```python 1203 | df['grade']=df['raw_grade'].astype('category') 1204 | df['grade'] 1205 | ``` 1206 | 1207 | 1208 | 1209 | 1210 | 0 a 1211 | 1 b 1212 | 2 b 1213 | 3 a 1214 | 4 a 1215 | 5 e 1216 | Name: grade, dtype: category 1217 | Categories (3, object): [a, b, e] 1218 | 1219 | 1220 | 1221 | 将标签重命名成更有意义的名字(对```Series.cat.categories```的赋值是没有申请新内存的) 1222 | 1223 | 1224 | ```python 1225 | df['grade'].cat.categories=['very good','good','very bad'] 1226 | df['grade'] 1227 | ``` 1228 | 1229 | 1230 | 1231 | 1232 | 0 very good 1233 | 1 good 1234 | 2 good 1235 | 3 very good 1236 | 4 very good 1237 | 5 very bad 1238 | Name: grade, dtype: category 1239 | Categories (3, object): [very good, good, very bad] 1240 | 1241 | 1242 | 1243 | 重排序标签并且同时增加缺失的标签(在```Series.cat```包下的函数默认返回新的```Series```) 1244 | 1245 | 1246 | ```python 1247 | df['grade']=df['grade'].cat.set_categories(['very bad','bad','medium','good','very good']) 1248 | df['grade'] 1249 | ``` 1250 | 1251 | 1252 | 1253 | 1254 | 0 very good 1255 | 1 good 1256 | 2 good 1257 | 3 very good 1258 | 4 very good 1259 | 5 very bad 1260 | Name: grade, dtype: category 1261 | Categories (5, object): [very bad, bad, medium, good, very good] 1262 | 1263 | 1264 | 1265 | 排序是根据标签排序的,而不是字典序 1266 | 1267 | 1268 | ```python 1269 | print(df.sort_values(by='grade')) 1270 | ``` 1271 | 1272 | id raw_grade grade 1273 | 5 6 e very bad 1274 | 1 2 b good 1275 | 2 3 b good 1276 | 0 1 a very good 1277 | 3 4 a very good 1278 | 4 5 a very good 1279 | 1280 | 1281 | 对标签数据分组时同样会显示空标签 1282 | 1283 | 1284 | ```python 1285 | df.groupby('grade').size() 1286 | ``` 1287 | 1288 | 1289 | 1290 | 1291 | grade 1292 | very bad 1 1293 | bad 0 1294 | medium 0 1295 | good 2 1296 | very good 3 1297 | dtype: int64 1298 | 1299 | 1300 | 1301 | ### 绘图 1302 | 1303 | 1304 | ```python 1305 | ts=pd.Series(np.random.randn(1000),index=pd.date_range('1/1/2000',periods=1000)) 1306 | ts=ts.cumsum() 1307 | ts.plot() 1308 | ``` 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | ![png](output_133_1.png) 1319 | 1320 | 1321 | 在DataFrame上,```plot()```是一个函数可以方便地对数据的每个列进行绘图 1322 | 1323 | 1324 | ```python 1325 | df=pd.DataFrame(np.random.randn(1000,4),index=ts.index,columns=['A','B','C','D']) 1326 | df=df.cumsum() 1327 | df.plot() 1328 | 1329 | ``` 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | ![png](output_135_1.png) 1340 | 1341 | 1342 | ### 数据获取与导出 1343 | #### CSV 1344 | 保存数据到csv文件中 1345 | 1346 | 1347 | ```python 1348 | df.to_csv('foo.csv') 1349 | ``` 1350 | 1351 | 从csv中读取数据 1352 | 1353 | 1354 | ```python 1355 | df=pd.read_csv('foo.csv') 1356 | print(df[:10]) 1357 | ``` 1358 | 1359 | Unnamed: 0 A B C D 1360 | 0 2000-01-01 0.573685 0.254583 -1.007374 0.475982 1361 | 1 2000-01-02 0.027795 2.640388 -0.866092 -1.642860 1362 | 2 2000-01-03 -1.298852 2.205553 -1.189777 -1.829773 1363 | 3 2000-01-04 -0.350564 0.717657 -1.497301 -3.179510 1364 | 4 2000-01-05 1.732001 1.939669 -2.658425 -4.195840 1365 | 5 2000-01-06 0.457319 2.281939 -1.612770 -4.582275 1366 | 6 2000-01-07 0.571856 2.053347 -3.937807 -5.300862 1367 | 7 2000-01-08 3.242640 2.280455 -4.378306 -5.054595 1368 | 8 2000-01-09 2.884421 2.906835 -3.156276 -5.133953 1369 | 9 2000-01-10 2.486527 3.205170 -3.407170 -5.450735 1370 | 1371 | 1372 | #### HDF5 1373 | 生成HDF5存储(需要安装tables库 ```pip3 install tables```) 1374 | 1375 | 1376 | ```python 1377 | df.to_hdf('foo.h5','df') 1378 | ``` 1379 | 1380 | 从HDF5存储中读取数据 1381 | 1382 | 1383 | ```python 1384 | df=pd.read_hdf('foo.h5','df') 1385 | print(df[:10]) 1386 | ``` 1387 | 1388 | Unnamed: 0 A B C D 1389 | 0 2000-01-01 0.573685 0.254583 -1.007374 0.475982 1390 | 1 2000-01-02 0.027795 2.640388 -0.866092 -1.642860 1391 | 2 2000-01-03 -1.298852 2.205553 -1.189777 -1.829773 1392 | 3 2000-01-04 -0.350564 0.717657 -1.497301 -3.179510 1393 | 4 2000-01-05 1.732001 1.939669 -2.658425 -4.195840 1394 | 5 2000-01-06 0.457319 2.281939 -1.612770 -4.582275 1395 | 6 2000-01-07 0.571856 2.053347 -3.937807 -5.300862 1396 | 7 2000-01-08 3.242640 2.280455 -4.378306 -5.054595 1397 | 8 2000-01-09 2.884421 2.906835 -3.156276 -5.133953 1398 | 9 2000-01-10 2.486527 3.205170 -3.407170 -5.450735 1399 | 1400 | 1401 | #### Excel 1402 | 生成Excel文件(需要安装openpyxl库```pip3 install openpyxl```) 1403 | 1404 | 1405 | ```python 1406 | df.to_excel('foo.xlsx',sheet_name='Sheet01') 1407 | ``` 1408 | 1409 | 从Excel中读取数据 1410 | 1411 | 1412 | ```python 1413 | print(pd.read_excel('foo.xlsx', 'Sheet01', 1414 | index_col=None, na_values=['NA'])[:10]) 1415 | ``` 1416 | 1417 | Unnamed: 0 A B C D 1418 | 0 2000-01-01 0.573685 0.254583 -1.007374 0.475982 1419 | 1 2000-01-02 0.027795 2.640388 -0.866092 -1.642860 1420 | 2 2000-01-03 -1.298852 2.205553 -1.189777 -1.829773 1421 | 3 2000-01-04 -0.350564 0.717657 -1.497301 -3.179510 1422 | 4 2000-01-05 1.732001 1.939669 -2.658425 -4.195840 1423 | 5 2000-01-06 0.457319 2.281939 -1.612770 -4.582275 1424 | 6 2000-01-07 0.571856 2.053347 -3.937807 -5.300862 1425 | 7 2000-01-08 3.242640 2.280455 -4.378306 -5.054595 1426 | 8 2000-01-09 2.884421 2.906835 -3.156276 -5.133953 1427 | 9 2000-01-10 2.486527 3.205170 -3.407170 -5.450735 1428 | 1429 | --------------------------------------------------------------------------------