{
"cells": [
{
"attachments": {
"logpypan.png": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAhkAAABoCAYAAABc++LGAAAAAXNSR0IArs4c6QAAQABJREFUeAHsvXdwXdedJvg95JwzCQJgJkVSJEWJClS2oq3gKFvutt3r6m73TPeWd2erZqZqumr/2K2t3Z3e7Z6uHU9PW227naMsy7KsnChKpJjFHAGCyDkDDw94+33n3XNx38MD8EABoEjdQz7cc8896f5u+H33l04gzAQ/+RTwKeBTwKeATwGfAj4FFpgCSQvcn9+dTwGfAj4FfAr4FPAp4FPAUCDlWqHD8Ng4egZG0c1fV/8o+obGMDAcxJmmbhy/2InmzkEMjgaRnBRAUU46Vi8rwpZVJSgvyEZ+TgaKczNRlJeBotwM5GVnIBC4Vs7cn6dPAZ8CPgV8CvgUuDYpEPg4qktCE5NoaB/AsfouHLvYgXNNvWjuGkDP4ChGxkIIJKeS2kQJQgrhSf4P8Tdp8uYysDwQSEIgKZm71AapzsQEUii3yc9OQ2VxLuoq87F5ZSk215UTkBQiI+2awVvX5p3mz9qngE8BnwI+BT5xFPhYgYxTjT14+eAlvHO0Eedb+kBYELkgBBDhMIEEwQL/8L81I3G2ZmPL1IR5d9fNmL4IPwBKOwwAUbWJEdSWF+L2G5bjgR0rsX1tBZKSfC1ShPD+X58CPgV8CvgU8Clw5RT4WICMfada8cPXTuPdEy0EFskRycTEuAEUkVOLAIUItrCgwdmajS1TbebdXZsROLFEcjJmoz8RwBFITsbkeBDb1lTgqw9swgM3rURysg82LNX8rU8BnwI+BXwK+BSYLwWuKsiQfcXf/+Ywnnu/nrw+CZMTYw6wIPN3sIDNLA7AsOSaGi/JqGImceuGKvxPX7wVG2pLbSV/61PAp4BPAZ8CPgV8CsyDAlcNZJxr7sW/f2YPzrWNUIIw7IALzXyK4S8twHBRjZlDUnI6sjMC+A9P34Endm2YB0n9qj4FfAr4FPAp4FPAp4AocFVAxuXOAfz537+B5p5RAoxRz5XwAAx5f2jXiDAsAHC2ZmPL1Jx5d9dmZlOR2CFtO9smuq8AbTMoYMF/JND4yqdutI38rU8BnwI+BXwK+BTwKZAABZbc6ECeI//bT/YSYIxPBxi0j0hKSZeZBNLlCkLkoP2A8Td1gIDZxAcFLtIwBqL27OdqN3Nf4ckJGoZO4v/6yR68c6TBduhvfQr4FPAp4FPAp4BPgQQosOR+m3uON2PPyU4ybxp2ukmMPolOHwF87vYafPqWlSgryETXwAhePtCAn795GuMhQgi5qU6JLCJ5FyNYMKE6Ntky7bsVI3mzG6/MU5eH5dESojjj//jRm4y78SXG3MhUBT/5FPAp4FPAp4BPAZ8Cc1BgyUHGix80GPfR8ETQmZo4eQApqSn426/chM/dudad8oryPGxbXc5fKf7jM7sxFoxRgbgYwWYWFmBYYBKeHMflrhE8984JfO2Rm9z5+RmfAj4FfAr4FPAp4FNgZgosKciQIOJ8S69xUY1MSQCDMoyUNNx/Y0UUwPBO+cGb6rDvRDN+sfsCJkMCJ5F2bh8mEwNAVGawh/kTqeq2i1fmNohuF3DqMpjXC3vO4OkHtyKF7q5+8ingU2DxKSCbrIGBAfT29hq1aUR1uvjjXisjiD4TfDdlZmaisLAQaWlp06auOv39/YaGigHk03AaiRAKhQwNi4qKkJqqYI/RSTTs6+szP5+G0bTRnr0Ps7KyIBqmpExBi6nc9HYLXjJJGwc9EJFE5u3wb6kkHr65dtbxHr5lFX7+1lnWmWrndoBFBhjsfjIphAstXWjrHsSy0vxZ5+of9CngU2BhKKCX1549e/DSSy+ZDuMx0YUZ6drtZWhoCGvWrMETTzyB2traaSciBrp79268/PLLJtCgT8NpJIJouGHDBjz++OOorq6eVmF8fNzQ8NVXXzU0jAdEpjX6hBUMDg5iy5YtePLJJ1FeXu6e/ZKCDCFo14jTARgCCgoLXpKf5U4qXkZrjiQFCFKoWomAC9vB4gMM+uCYIUeCIXT2DfkgI94F8st8CiwCBQQyzp49i/3795sXWElJySKMcu12OUnx8MmTJ42U4q677ooLMkTDU6dO4eDBg9i2bRvy8vKu3RNehJmLhsePHzfSHtEwHsgQDUVnS8Pi4uJFmMm126Xoc+zYMYyOjuLee++9miAj4jFiJRhWEqG1SC53DGDrqrIZqdzcPYDJMNuHJQlZYoBhZyWsYYe2Zf7Wp4BPgUWjgD5KJHpdu3YtvvzlL2Pr1q2OW/uiDXlNdSzJ8L/8y78YIJY8gxpX4n1JL/Sl/vTTT+OGG25IiIZ61emT7npPkvSkp6fj4sWLM6qSRENJL0TDr371q2YrxuqnCAUE1PScNjY2TiPJkkoyNDplGc4kIhdI1ynACT67+yw+vXMVL/K0OZqCZ98+Q4PRJI89xxJJMNzpRMZL5hz85FPAp8DSUUBAQ0wyOzsbubm5SzfwNTCSQEZGRgaXQJjdTswyyURp2N43giP1PSjISsWWuiKGFJi9/2uAVDNO0dpjzGVrYWmYk5Pj34cx1BTI0H0Y0VREH1xijklGbdIUwJBUYpKeJvvOduC//PYAbTZsnamJfu+PR83CaRGjT5VfHYAxNSM/51PAp8BSUsD/aoxPbUsXu41fK1KaSB3VHA9N4oMzHfj//nAMvz/QiN5B6wk4W+/X7jHRJVHa6CxVN8QQDEPBQQS1FIafDE1mouFVkGREA4zI9eFFngjhuy8ex+Gz7ZRo1KGiOAedvUN46YN67GZsjbBRk6j21QQYkbn795RPAZ8CPgWuVwo0dg7h5SPN2He+C4WMC9Q7FEQ54xb5aYoCI6FhNA80Iic9H8typxuKTtX0c0sOMsSmI6osy7CdrdAk0eGBcx04cJ7BuuiJElBMb8cw1FwqRfJ0k22nAtuXkze78co8db11rJuqurd5VY0HaEy5/8enwOwUkBj76NGjxlBsbGwMcu3asWMHNm7caKzTZ2/tH72aFNAXmRhrR/8oXRv5UvCocJP5TirJT4cM0T3FV3O6Czq2jNvfPdWGo/VdSOUq1MNjIQyMeAMnLuhw8+psku//tsFmtA+1oYDMvSy3CpkpszsMxBtggh+sQ2MD6BzuoBooHcUZpR41frwW08vUx4Xus8jPKEBV7vJ5t5/e4/VbsqQgw6wFYowuLFhwgICH4U+aSKAsiPwn5W0d20YXw5Z58sq6jZzjUWXOcXfj1LGgYkaA4ekrgo5Mr/4fnwKzUUA6yrfffhv/8A//YNzj5BXx7W9/G+vXr/dBxmyE+xgc0xN/5GI3fsnVoXuGxpDiGIrJ5Dw7PQWf3VmDB29chuSk6w9mnGvpx1vHWlCQk45b89KpOgmhj4Dr45BGKT14s/4NvHz+RRRmFmFd0TqsKlyFFQW1qMhdhpy0XHogxrcAGAuNome0Gy39l9HQW48LvRfR2N+AbRXb8OjqJ5wP2sTPkvGp0TrYivbBTmyp2GHGTrz1J6vmkoKMCGkt03a2ZmPLVIN5d9fJXDUJhjuRT9Zd4Z/tR6aAvoblN97a2oqRkRETH0b7M+ktP/KAfgcLRgF9S1yit9ubx5rR3D2CVAdMjPNAUU4attUWOdfx+gIZ/cNBvPlhKxo6B/HEzSsoTQ7jVapNuj8mNhndw1042noIFwkSggzK2NrfiLcuvobi7DKsLFqF1YVrUEvAUZVXjVxKOgRK2ggEmvovob67Huf7zqOZbQaDAwSOKShhu5zUPAITGbXO710vA8eB0SG0DTUTbDRhddH6Bbv/rreOlhZk8DpGPZbmunovLvPurs18fCQYdkbX203gn8/iUEAvIlmkKykfz/J6cUb2e/2oFNA6Sum8dhkpAVdikcwXQDpVCNehAMOApmOXerH7VCvqSnNw35ZlONnYgxA/8HqHuFo2AUfSVT7xjuF2dFHFsbPyZnxm3RMGLJylyuJC9zl8cPl97L20G/mUcKwooE1fdjn6x/pRT4lFF9tN0OYvi5KOSgKQ1QQkNQQj1XkrUJ5bifRAJsMjePlMIndPgMp0qkx6zqO+5yJWUaoy5TmZSPtPTp2lBRmk63hogmHEUx0s4WHbUaoIp9xsbJ14ZezQbRc5btQtFFVPpTjtrkBFEulFf53+pgbwcz4FfAr4FLimKdDZP4bXjzajdyCIJ2+pwaqKXFymRCOFQKt7YAyj4xPIoqroaiVJADtpiyFbipsIMm5ZfjttRtJwV2gILQPNaOxtwPmeczjbfQZnOk7iaMsBHk9FcVYZ6+9EXWGtARaSchRmFiMtmat9O0nRPK8k6aOhdaAV5wh0bl9xJ7JSc66km+u+zRLfNWFsX1OO4oIhGnl6g2p56ewBCC6A0HEydzfap63vZfiR/KlL7ejjgxIRSzvHzcbJXzHAsGP6W58CPgWuFgUmxWzIEDsYx8F8fDqiUT3d6ckBlBVmoSB7+vodV2u+18K4IYYNkLH9vjPt2FRThNvXlyM9NRn5WekGWPRSjSLjz6sJMibCIXQMtlPiMIEySilksCm5eHZqLiUT68zv9tBd6BhuQ2PXWXT3NyGLUo3q4rUoz6lAdlqOoxZZuCsix4Q+ql7OdJ4xapm6wtUL1/l11NOSggwhv//0J7cvKvn+zX9+Hru5mFrYLKTGoRYEYDgAxdks6gn4nfsU8CkwIwUmKLbfQ++H3+5rwBg9P6wEP8TyirwsfPH2WuzaOLVuwowd+QdcCjR3DeM1SjFIQty/pRLLSrLNMYG17MxUY/w6MDqOclw9N9bh8WE0DbYhLTWDKo4Kzi9K8W7mm56SgeVUgSzv4yKcnScRqGC9vBqAbRYjaQYTXBJDEpSGnguUlqxiyfR5LcbY11KfSwoyloIwRthhVRoGFDjI4IolGE57b19LcSL+GD4FfApMo4CMES+09uPVo00YCU4g2XmpB1m+siwHu9bPvDTBtM78AoxRDfLemTZ82NCN29aVYceaUqpIIoxSIKMgMw3NvcMYHL4ylYJIHKaHCqiSCGh1U8/qnPMhf+9IN11XW9A3mIrWzlT0Fo9TYjV9tVRGdkT40kHgrf+OcOUGBLILgZqbZRQVNVyYbuXjjZcZRZqWFJWV045HVZ5lR9IMqWsENHaGdl2RS+0s3V8XhxYEZEjcphR9Ga8OfWSgZJIXFCwSwAj37SaUPckHyBnTe8qyC5HRX5iWy+m8ibNoGJS+kjWWnkpyp1TcBv2UbHhca4ioOA7t7e3mp9UIVV/hh8vKysxCNwoXeyVJ/cijoquryyzgpL6l/9T4dmlqrdanUNF2LomMM9f5aAyNKc8OLXGt89Z4ciOt5AtF53alSX1p2fHmZuqvubXrHmjBJPW9UItPySOlp6cH3d3dZqnzYDBorovCa+fn56O0tNQsqfxRVoPUYkaiU0dHhxnDXhv1qbgeOhedl7bWgPVK6baQ7WSAKAPMSVpiWklGEh+3NO7IYNNPiVPgfNsgXqVHSS4BxafolluaN/WsS4pRlJuOC20D6LtCkCG1dfDkaYwcOoy0jRuQddO2K2LonVSDtA914mxjAL8f7MWynD7sXBtnsbwg1Wi9rQgP9SJw8QPg4G8RyOP7tyg6YFbw7Hl0/egXSC0rQf5Xv3hFcxKVdb/1jQ3idOdpqkxa6N0iaYafvBS4IpDR2NGPvRRZHmbgrEvMD9CXPEBGHgmepe49TNdkPXYW5rDnuJ1NlHVvTH1Tx2kz7ZCnL/ZxmfOZDAl1O+ULCjA8Y2lO/W8jkPkKwsNk3lH2I1PDm3n0c380gHDORqDws0D+/UTQcVC4+lyE1NTUZGI2nD9/3jBzLQt9zz33oKCgAKdPnzZLGGsFvcuXL5uYDhZkLFu2DJs2bcKuXbvMgkBi1HMlMSoBljNnzuDcuXO4dOkSNL6Y2fDwsAEZAhTqS4yytrbWjHHzzTeb1Q/nWoNB42ueb731lrug0bp168z5FBUVmTItDX748GHU19cbkCEgIKYpQKMFju644w7ceOON81p/QC9LAYv333/frAiqcxMAsOseCMBoHrfccgtuuukmAwTmopX3uPoXaNE1Ut9arEnnKQAgoCQgqOsiwCeQoWuj8XbcvAMb1m+YF3DSOAoUduDAAXOdBMYGBgYgIGMBqIBYYWGhAU4rVqww10j3gu4ZP13bFAgTwIb5LI6MBHHwg0Z01rfQm6QKG/P4jurppukbP46I1dK4IGVRRjJCvO96+Y6/osR7amDPXnQ8868o+PRDyKitQVLJ/FYw1bPROdJBV9o+9PVX4mDXEM5s6MVNq4tdqYs7t5E+oLcJgZJqvpvzED73LvN1wC1PARmR1Wcn+dz2vfQq+t58F8Wf/QwCkq7Evr/dDmfPyKNE9iIy/mygJ4sPMqbTa14g48OLHfjX185g94eNGA7xLhTP5Q3I1UdMz5HrZFGAw5DNxsucmY8ti7rATt2oOraNhrH9MxunnTEoteULCjDMKTpzd/IECuEBAgz93OSdqyevuYx9CLTy1/08RXn/MwJZS4N6tTLeT3/6U7zxxhtmlp/+9KexfPly9PX14Uc/+pEBGWI0YpjepFX1BARuv/12PPXUU7j//vvN17O3Tmxe4OIXv/gF3nzzTVy4cMEwYjFIK0Xx1hegENgQ0Lj77rvxhS98wTBpAYLZksDDj3/8Y7zzzjum2uOPP46VK1cawKTy119/3YAbjetNGk+MU3T4yle+AtEhkaXDRZcPP/zQnNcf/vAHAwQEmPTys0l9a+EkrXD52c9+Fk888cS8vv4ltXj++efx7LPPmmW5dT0k+RHdvONoPAEBXRtJmhRFVOf/8MMPG0Bg5zPTVuDl97//PX73u98ZoCHwF+/aqL3OSVINgbc777wTf/3X/5aA886ZuvbLP+4UCPCdzTR67AQGX3kd/e09SOMiaPdSHbK9qxQjJ/Mwogq8v/g1guSsDKRPlGJypAA9g2Pmdet0oVoJpcnOLoyeOovBUxeRUrAfBffdhcw770iora0UmhxHx1C7MT5NnyziR+0E6hnHpJ9BwiRpiUoD7fz440+qko2fQvjgbxA+9BwCZQQaa+8xxsJDe/ej75U3kLF+FfIfuY92GwQfnmc5qr8EdgQ0WhmJ9ELXOXq93EGVydwfYwl0e91USQhkKNTsd54/ih+/cZZ+0/QPlqSA4CKSIi/ayDWyL11naza2TLWZd3edTJQEw5Y5dSMDeNq5jT1lnrreG2VBAYZ3Xu6kIhnvmN587LmKXKMOzZIOARf/GuHqv6Uob3ENYTVJMUmJ38UYlfQlK0ariJS7d+82x8Ug9YUsBqZ6qiMm3dLSYpifpBHqQ8xT9WZKZ8+eNQxMkgQlMUOBBv20nLKkGOpXDFTjSJ0iKUpDQwMEHv7mb/4G9957r1l1c6YxxBTt+ag/9SHphaQbL7/8sulXX/wCSDofqQU0nujQ2dmJ1157zWzFQJ988kkzt5nGkvTgyJEj+M53voPnnnvOtLPnFY9mknSIVgJwAg6JqoEkFRE4EgDQ+WneopckBzoXMXyV6zx0vpI6SNIhMCKaSxIhIChpzUxJ8xLYfOaZZwytdW4WHEllpXE0ruika6OxRDtJcCT5aGpqnqlrv/waosAkJWNdx8/izKl6pEwGcEdxJgrbKNlo0+uZ7yj+D1MiOdHRhWTGnMCG+9A9EqKhLVd8pdfJfFLwUiOGCGz7MycQunwOBR8cQsa2GxHg+ybRNDTOoFdURQwMEvuECjAaDKCeKpzW3pHpIKO/DYHhHoIMBsdady9XieBH8Bv/BHzwKwQKqzHel4Se515EODiOosceRtr6dYj+tEp0VlP1pDLpHR3A6a7TBEOtWJFPml0naZI2LmNcBC45KTnK7Xc+pzcnyOggyv0Pz+zBgYs9mBhneFmBApfXRzKfHIDhnrhDY8/+bADDU800JBJHGh+ES/8J4RX/J4EGDZMWMcUyOonkxTgkaRAT27lzJ6SuqKqqMkxHAOPkyZNGUiDJhBja/v37DXPSl/+DDz5owEO8KUtdoi9vMbu1a9cakb6kJmonqYWYmACCVCoa44MPPjBSBzFJMVnp/ytoFS51xmzJe046n7a2NiPJELO8h6ogifY1B9kwiOGfOnXKABF9yYuJimn+8pe/NHOUNGCmJOAj6chvf/tbo/LRuOr31ltvNVIXzVWMWjQ7ceKEAW2imZi5mPZMUoLY8VRPPwGXmpoao9apra010grRRGBNtBVw0XWTqkP0ExDQ9nvf+56pKymKwElsUltJfjQvtbfnIfXO1q1bDc01tso1D9FMNBW9BAIFEnWeflo6Cug50mtlMvb9wSnwMrlBwhKekfOOStt8Ay4/+jm8kH0GG5bn45abq1GcmWzGUYgp84ofYRju536Pgr0nkdvZYtZyGRoNzQtkSKo8Xn8JfZ2NOLUhGbkj/Sjbtx95996JdAKNRJOMPtsYI2M0mI6MpAJkZqfThXmUqvEhbKz2qO9k9DnQwa+qUQRyaQCcW4IAARLaziJ87CWE3/kp+i5kYuTDE8h/4D7k3Hk7Anw/yCj1oyRJMoJUmSgw2KXe+usKZCgU+77LewzL31l9B++TOHYwcxBvVpDRPTCC//E7b+PE5QFMjkuQxrvdveEjmch9awudrdnYMs2AeXfXyehOdpMtU4FbMZI3u/HKPHWdh0cl7gJn6t5KM8wBC448fTntIiVOudnYOt4y08kMf2x9HWbe3fXmnaZ2rkEeS6Fk4dL/ivCaf6JR6PIZ+l74YtlJKAlUfPGLXzSqA9kqWDWFGJIkGGJA3//+9/Hee+8ZBidA8Jvf/AarV682zDnezGT8+Nhjjxm1hJiX6sp40H6Nq42YmICGpBeSqPzkJz8xIEZlUrPIzkDtEjHQ1ItYIEPgZdWqVUbl8uijj0J2J2KaKtf56JwlifjBD35gmLLK9u3bZ2wsNm/eHJcxaz6SekiNIbWCGLDsE770pS8ZqUE8mr3yyiuGZgJlAjOSFiSSBMAEXOrq6rBt2zazxoloqXOwxp06VwE+ATSBDIGkP/7xj0Yldfz4cbzwwgsGnGlesUkSHEl7BICUBPo+//nP4xvf+IYBgpZWtp3mLomJwKj6lqRF9PXT0lGgn8aWil9xtqUvoqpwhp4k6lhWkkPDx1IU58zftqs9JQevJ5WhviYVn3pgHcp2LKfRbPR5hXnfhnjNSw+fQElHE4b7htDPWBnFseqJ6GZRe+HBIYydq0fHSBcO3ZyEgr4A1l84haL9h5C2YT0CGdPBcFQHzo4x+hzopAQ9D8tzS1FeVUTQM4wL7f0ML16JtBRn8hP8CO6jqoRf3SigRC+J7I1Gn4Htn0W46xIGX3sBvcfSkb5yIwqeeBjJVDcuVJKXUwvDi8s2Y8eyWxkp9tpXmYTJo892ncIvjv8UXSM0dmfskQfXPGrchGdaIyYePWcEGeP0GPnb77+3OADDa1dhObJhzC535lwtg45XplNxyi3TVpEFFQsOMLxz0ECepEPuYWa8eU81k/XOVQVBTjSrC2j8v4HV/w8LluZLUQxEKg/p8v/qr/5qGvMQUxMzlY2EGKu+avXlL6YrlYQMJ8UMLfMz5+b80SqjtfwClx7fghbvceWtiF72C5JyiMHKuFGSADHQve/vxUMPPmTsG2LbxtsX49WYTz/9NP7sz/5smm2CxpNU5U/+5E+MukNqBp2TxhIDlXGl5hGbBF4EMvQ1rySaCUB961vfMjYg3vqWZgIgAjbqXxIAAYNEkpi+pBCihWgXL+laSEpRXV1tAKJAiNQZAkECTQIeUu3IIFRz8CaBRgEt0Ur9iPaaqyRY8ZIkJ5Jy6adF3Wy7eHX9ssWhQA9tDv5wsBG//+CSea1QeGHSKOODKGBWNeNZFOfkJzw4L7tJx+mueuJiF3bUFuCO1UXTAIYqaTHL9LoaFNJIs7SpFb00CO0f9dqeRfqa7W+IAHWYXhxtaWO4wJAV+SXpaLnYj6q9B5Fzzy6krlk9W3NzTM9PB0OJdw33Y3y0GkUF+bh5bTHeOx3CRapMumkrUmGXoafKItzXTOkEGXyeYmk4ifYZoeX3oeenRzHe04WSr29DxoZ19uiCbI3KhJKaM/Qy6aDUpTq/dkH6vZqdKCz7gZb9ON5xAr00qB0Y4zuTXj6PrX0S60o3Jqw+iX4Tec7oh69S9Huqa+ElGEbhZwdyXsBm430ZMz9jmdo6db0v8KUAGN7xPNOInI2ds+eAM01zPLatlYEOE2iM7iXSfiXSzRL8FQPasmWLsa+Y7etUqoeHHnoIDzzwgCtVEKPSV7oYdLwkBimGPRPAiG0jxi2DUgEXMWpJOfS1LTuDRJNUInfddRc+97nPTQMY3j7ElGXEKiNRJYEtSVNkqxCbJIGQXcnBgwfNnEQzqXBkw2Hbx7bRvmgmI0zRLRFJjO1D9JLHyEwAw9azWwEnSTxEO2uHofOQZ4qAR2yyNha2XLSQqieRpHOXJCqeGiaR9n6dK6OAJBYjY3SZZiCsPkoRJEnQr5c/LcE+4YQOSLR3+wrKp7vqfZur8OntK1BROPMXdxqBe97qOlSPdSOtq9XMIfGxwhhvaMRAEyUZJVzvpaQII8vz0FSTicGzpzF08IgewDm7G58Mckn2NtIhhFQafeZmZmELo5JWFWWhsXuYC9hF7MxMR1wRFbTJACN9SlVi06Qill6gTVpXCnLKqJLMbOQ7lx93C5ikMhk3KpMzuNRXv4A9X52ujISYIdoPNH+APoK3ZMUD6W/Bb089i+8e/Ce8e+ltAzoSmV1ckNHQ2od/fvEEQ39T/CSG7jLLSCZys9pCZ2s2tkxDM+/u2gwZqs3ajNl3Cz3t4pU5/ZqN5/hSAAw7X409LXEu7nScjLvPyvbptu0kabFJ9Sb4p/l7pLdUUoufxDBkhzGX3YNmIkakurV84Sjpi1b2DdLrL1QSc5V6xAITARh9eSeqapAUQHOcDTDZucreQT99zStJiiFVQmySjYjOU+oCJUkYrpRmsX0v1L7AlegmqZOS7DMkpZF9SGwSgLOSJ71AdF6qm6ikJbY/f39pKCBvUsk3GTHdxARRXBCu2Wb2eRNf0STEpL96z2psW1kya1yRpLJSemCswbI0MuYWurcPehj6XCPzPTF2oQFdfTTYrGbo72qqKEqWoWV9PgYnafj9PsF7W/wPFW/Xw0GtTdKG4ZFkZASKqa6hN1p5Dur46+eaKo3ttAa1SQBjiLZu+YyLkR2RBkrtM3r4KHpefgupVZUovnMzkpveBWijAa6DspBJzLS5n4G56GWipeWv5TQ0PohDzQdwuuMU4ZPCU0QWe+wf7cebF9/Ad/d/B3848ztjkEvLoVlPNa665JmXjmN4nF0zZOpU+0hHn1iA4dLRzTiE5b5b5GTcfVaJCzC89ZiXfUZ6PfWJuxk05gE2Wtykr2XZLMhWYq6km0uMTOoGqRbElOQSa+065mqvL2gZENqAT/rKlgQhNnlBi5ilGKUAjQDRXEkgpba21mWis9WX5ERurPo6l9REY+kXmwR0dJ5SESmJVqJDIpIGSzPRWCqgRMGSdw46d9lBaB4y9tQ8VOYFBRpHcU5EYyWdj9qIdrK38SZ52lgjVdWTS+4Pf/hD06ekWpKGSEXySUiioXC9l5b2vMXE+Uq1u9flNpMLnek3Vwqk0X6Bkoyy4nzkN13GBO+rCaxISKk72dWN0bMX0DI5gLHltdiyfAcNIy+go4bP3Mo0jB07iZGjx5BDxj8bWOqmxKFzuBXB0QykhvNQkptBoJGBFSW55rUrV1ZFfs1MTTJGn4EgQUc+JXSZETXSBD2ien73IkLtnSj9sy8zGFgFwrsZDfQQg3SV1gFr7pqLDAkfl51CL1UKp7tPc87tWMYQ59dqusgIpvta3qctRg8oh3JPQ+c4RuHDodbD6B7tYSiLYTy+7nMoSI+v4lXDaXeaAm39cX89jWyof3N4oc34AMMliEv0KfMS55i3SiIAw+2JDTueWxKQofgKYjhitIkk1a+srHA9HGRvIGYmZhXP40BMVa6VUjXIlkMifAENSQfELGNBhpilpAkyNFTScdWTnUEiIEOMPxHmr771NS+phAUZGit2Pqqn8xMwsgBB0pL506zS0Mf2oX7nSqKtwJxoJ7WRVCACGQIS8UCGyq20RX2LbhZ0eMfS3KVekWGqJBg6P3nMCKRs377d2HEIqAmcCLQJVElScj2mQXpJHGAgQS1l7n1cpX1YXpyNW2hQqXvyE59IgrS6WhTSNqPkSD1SO9oQJDrLlFhljmRcV89fQHPuGC3Mi3FD6Q18zibwft4l9G8uw2RDPQbeO4CsnTuQNIMNkobo4HolXcNdSJrMR3oSQUYe11PJSDHXqSAnzUQj7egf4fLuNIBlfAxdz6QCGn1yHRMFHOt/4y0MvL8fOTsZIO9T9yFQTmZIm4nw2/8M7P8F3VqXMUBi3Rxnk9hhqUzGGNPjbFdEZeIFGQK0o5RUdw93YyjYj6KsEpRwhdiPYxqmy/ChVnqvtZ8kPUnRmGdB9icqF2h8v/E93Lr8tvmBjD/srSehiD1IrEiKPIY+wJC4MkAmFc8403lVORtDt/kADNUd42/8EMJjjKe/yJ4m+pqXQV+iSbYF+fkFLsiQNEKGmmJ6YtjepGOHDh0yQaXkkirjSYELAZJEk5iyGH+izFm2AonaC8QyDz388b5oBXg0b5usEaTdn2sr2wxJTATCBJbmSpqDDEwVJ+PFF1809iDyaBEd4s1vpv5UPx6tpYqS/YYkKwqWJpAhQKO4HjIY1fnJlkYAQ+ok2Z3I4FMGogIeVtUy07jXUrlWFH3lSDN+/d5F3mN87hyeKYNKeWwsp0FlzHv1Wjq9BZ1rMiUNWRtWo/TQcSS3NtHeJ0QXUjL0WZJcV4MXGzDQ1YT2ZalIKS5BVU41evO68S6/ytpXFmBjXTWGDx/BKEOOZ91xW9ze5N3QRaPP/uFBxu2oQF5GDorz0o3r7jKCweVF2SZehhZ4W5HFwIi9LYzeSY8VGX1KTXLsOHpeeJnj56Po8UeQUk3jbumfGKQr0HEO4Q//CBz5PXDb1yPlcWcRv1D3RxJvnFi4Je7QPNBkDEDXlWzEICUrHYOtdMFtQRPLG3obIbfQmyp34NNrH+cKsZTkfMzSpd4L+OAyo7QOd1JqFf9D1Jw5Tz5EO5QQXYdnS1GSDHmUvHzgIm0DrDibDyBThF9G8laqIYDj5pVVga1iM9ecm6p7AtPPh3dVRmoK8rj8cXRy2kQ19e6wNr+QXOKYQ57jEeJGDqeTGfXtA8r4MCxiknQgEQmBnYIYjJi4lVqI+SugVqwEQMx07969+Md//Ee8+irD9pKJKWksSUP0dayYDwImEs17Gb5UE5J4xEbptHOYbat+vH3NVjfRYwJQ+tk0HyCjNpICqE2i0qL6+np8//vfNxFYZYwqGotGktCIbgKGAnvq156vtpJyiG5eu5KZQIm8Tv7iL/7C9PXSSy8ZACgwpesmqY1+MnbVddZ4snGRlEPB0RTxU8ai10MSfcbGua4OGeYE85ZRDBNkDFH0btdiuh7O9aOeQ0D3HFUmhVwoLUgQHNIznV0ya7fGdfX8JXQGufZOZSZqCitQRGPMytxlyKJr5+WcCUzetBb4xSsY2HcAmTduYXCu7Gl9Bvmh206pg65VYKKQS81nUF0Sef8WUopRV5GDDy91c2mLQdwizW8f1yzJymfcoVKEKDnt/d1LGL/cgtI/fQqZ27a6QCJQQOnF9s9R7NdvPqYDE3zv2ptg2iziF6TxFV7IRpSJYupTRB+iSTTOld3C6ya2Rzfdd2Wn0cYgXT1UPUhKECR/PUdpR3pyKh5d9yQKM2ZWNcQfffFKR0MjONxyGMfbjzNuCoP1CZTNkESy6TBreuUokHGuuQfnW/oJMsQVI4xw8QCGw2jNxsmb+THv7joZy4h1fKmMPGPmIGIW5WehMM/zMFAfZebq1hXZvDvcTwRg6LzUTl9VfXsJMvgALHKaiRHFG1Z1Y5l47L7aiVEq2JMYmJiXmKxiNohB6atYen+BDIGOWJAh0f0///M/XxHIiDfnhSiLd46J9iuaJUpj0UrxLhT0S9IMMXkZc8oTRuugSJIgSYOkEQIZFrhoflKtfPe7340CGTPNUf0qdokAn4xY5SUkyYaum9RbsuWw4FFSFP3kEqv4GgrD/uUvfxm1tbUzdX9NlZN0xpDSPL8Og+Gaa8be4KNc92uKCAlMVrRIqqlFelk5DSYbkdpJY82q2UFGiEbbo+cuoD09iNGKPH6tVyA3LR9VuctRml2BpmAnhjZuRSGlZsN0Zw3edzfSb9w8bTZDNMxsYbjuYCgVXA8WedmMTJoTARlplCjXluZRqpGEC52MTtvZh+whxrLhQmjhlFwMvrUH/bv3IGv7jchj4K1AbkyE0QqGHb/nL8lPkhHOYFhxgvr5pDSqjWpot1g5mQSam7pJfEJf9wdaDuBw6yFjvzDOL33Z+ugYqWnmfIkSjd+c/DXy0/Nx70p6oqXFzM/tcWkzl/vpPdi81wAkry3GR5lFFMg4eJY6rSTqYR0vhwi/tEzT2ZqNLdPQzLu7TmZOCYat57R3zyBeX27n8wYYUy3jjRevTKcz1co9MTFZvoHW1ZbRYMojKhynV4IsyGyKasvC+QAM9RFiX8OnCPIYsS55boNHO+x8t9Lbx3NznKkffdFLz2/F8GJWFijYNjomKYaCa4lpqo4YpL6c5QIrgKGyeEnMWCL7mY7Ha7PYZQJIXpsE0Uy/RJOYtWiciMrHxuOQBENJKgvF9FDcDxmbai4zJUmT5uMqK6ah/hUeXhIKgRrrxitjXhngyhZEeUmidB6yq9E1VcCur33tawYozjQfv/z6o0AK1WhJq+pow3CQMX0agS0bZzxJPcvBhksYJSCR6yrKilBO24O05DRjh1CbV4t3Lr+FjuWpWHbzVvT89nkMHWBwrvVrqSaOvs+7RzqpLulEaDwbybTJUCAwud8qCRdKrVVE9Ul9G8OO517GKsZ1QEElxppp/PzCS0jKzqKa5FGk1q4wbaL+pPL9WuGcRwLqzKi2ZmeSrr0hrKQQ5BhtVMQFNCebximFkT2/VCqpCg4WlVifH8unGFPjlyd+iVwCjdtW3Jlw3ImorhZwJzjBZ73lEI62HaE0j/Z2CdrszTWFKJBxmCDDMtYIv7QM1NmajS1T18y7u07mOgQYESIGcM/21ZGszpxAAMEWZux5u4SI1JkvwFArimsRbI38Mmsj/SzCX4nY9Us0WW8Pa1sgpiebAy/zk/2CwlvLqFBJ9ghagEwBpiS9mC0JxIihzQf4zNbfQhzT+Xnnra98/RJNoodoHKtSitderrKSKAioScKjyJ+SHMgeYq6kMeYzL9ufpCGSjsgYVD/NU3PW9VOMEtnVSCIlSYauT319vdlXFFj9/PQJogADYAXrajHw1tsInjuP8ChX3Z4pWicZ9tiFegxx/ZB2epEk8z0gkKGkhcNqClbg7QbGpwl14OYdm5D0+jvo37MfuXczONeqlaae/aOgVr1jXUidKCJYz0ZpbhrV1RGQoTqVjJWxoiwXxy50oilwDqsoQQAZ9sD7tPW4cBFFTz6G7Ju3UzwVy+TtCB9tW8bnYh2BRn5WMmgGH+V1Y6QWXtQRM5SOT9B78yClHbnHf06gkYcbK7aTsUex5JhWi7vbPHAZHzTvo/SodVY1yXxn4SpcpIc830Jra8V/N/zSMk3LRNW1LXPy7q6tYzirMwdb5m0Xr2ymvtzOr6oEQ7NT9Lvi3FTct2OddiMp2ERQQEGZpA8WaNhjVwIwRFvZz9AnHaMRRm27W+it3CLlkZAIA9TYEqXLy8FKMmQnIG8LK7ZXHTE71bNAQZILub16GbXqxUuyJ1D/tm28OktdJjsIuX1a6YrsFVooBrY0mGs+qiuGPVd9fflZewj1KeAm1VJtbe1cQ5i+NY7o/lGTwI2AoUKsK6jZt7/9bfz5n/+5mYukH5LIzDdI2kedk9/+40GBJNpkjVUtR39SFldqPTdrfIsJqthGz9JzJHUS/ZXZyMkupj1GxFU+QP2+VCY5VJ009DVgpK4U2bSVGDt7DkOHGJyLINsm2QN0DnVgaGyYniWF9CzJomdJOu0ypgBDPo09V5XlYXxkCM3nz9GjJB3B7iAG9x5AagVVs3ffgQAB0qIkPhPpnO8qBkurnCBguIJBZL8RDI3h3cvv4dcnf47zDH4lr42rkSR5Od56BEfomhoMzd9GZbY5uyCjZ2AUbT1cvlqxMdwTdU7YbLwnz7y762SuWwkGQUZyCv6Hx+mmk5s1Rcv+/YTmRBMuHZxDiQKMqIbsxOIzXZGBo1PjLEJOgEBfz2JucyUxSTEX/cQQxXBsQCtvW33tSp1g1QNSp+iXSJIbpWwLEgU9ifT5UesIYNTV1bkBwmSfoHnOh2aSCIhmcyWrWlE9MXtrGDtXO7kFK3S51+hzrjaJHhfIkjeKVF4WTMqjSBIne40T7cuvd21TgCEoMFZSgc6CcvSdr2ckz4YZT2icqhKzKFphMgZLuRJydhmNRiMgQ41k/FmZW4XWvstoSxlBzm3bEKBBvdxZvcG5xhmLQSGsx0Nccl4gIzWNIIOrBPP9Y1MKVdjVjJdRRoP5UA+NPgMZGD7XjHGq+rJ3bEPaujW26qJsA7Shq2Y01lpKoJM5r7mf9OnTkGHlMD1QXrvwBqNp/gaX+y5Nq6R3iFZDHeH6YTLMTOSdMq2TOQraafuyj1KMy/SA8dJ4jmYJHXZBhla1k2uXIqRFkkMys/GSj3l318l8TADG1BnbeanETjZemQ7b4566nrIk3ty3bajCUw/cpApOIo16X50uxfACDFPT07enTzMn9xAzluRqM8Kd5h864yzORkxNrota8GyuL215fWg5eBt8S8BBxpyxobXFHOWF4mVIiYjxJVXRkvM20NfinPH8e5X9gSQKNpqmpCwygJSx5FxMVjR79913XZrNNbqlneoJrAkEzmX/oXpauE7j6HrOla7kxSRDU+/CacYIcIH0tHPN1z/+8aGAmEQ4n4uSVS5HV0cnFz07z3efPkZjEj9Ixrjqaqi3i1KMLAQZ06KCqhLZHNgkwFFTUItBBq263N+IjM03IPOGjRj98DhGjp1w38eDQRp9DkgdTQ8tLu+ewXdLEUFGbNJCcVtKafqROozJAS7qd/QiArxvcxV/Yw41bWxfV7JfxiXj145OgiaoUa/x+fQloNHDlWb/ePYFvHDmObq5MogZVRenO4+ZFVBfO/8ifsVFyr534L/jhdO/RSsXYlvINEEAc7z9GGNjHKQnD+0BPUBuIcZxFUDtvUNEgrqdxPEcDmg2LjeMlLu7to6XQ9oyTc1WjFfmHLdVbF0vI14KLxLveHHmIIBxQ20J/vd/+wSRtEsqRpY7xJgWfCDG3RNwgIJn39u3N69x3GrMeMnnkm1upqGqV5rEcGQDoBVV9bWuZdHj3Vj6etfKnlokzDI9gQvp5PWl601Si0iFImNJMWSJ8BVQSsaFMjSMlxSrQXEhtDqq8h+nJHrIE0PLwEuKI3sU0ezXv/41aqnKkL3ETDTTgmVems12XurDBhMTuBBgkD2EInLu2rXLBW3ePgQwBBB/9rOfmTklAiBk3Kmf3FAlifLa03j7tnn1KaNQucdaICobDhst1dbzt58MCmTkZWGoqhpt+wIYOXUOuXxeY1cxDXNl1NHzFzHOl1oPQYYkvZX0JpHRp01pyVzgL7+a4uEA1/ggIKm5H7m3bmfMjMMmaFYWbSiSqLbrYsRMRc1MDudifCIbuTT4LKLbamwqzc/EjvIwirOCGLpE4+yGYeTcdS8yNm6Irbrg+2GeQybB1ppgEr1MUtFDIcuUMmd+w0l10jLQiue4Nkh9bz3VQ2noHO3kOjU9XJiuD/1B/riGSFXecqO+f3TN4wu20uvlvnq82/AWGnk9NI+FTi7n7BkkgqHRSVg+w0qGEbrcMFLg7jqZj5EEIzIjOy/3BOyJxD8fVTPJtotsA7QGDtDn6IGbVuFvv/kw3Van1CRGndT6XT4kRAcWPBig4PSh/mx5bD4hgMF+PF2Z6S3wHwEBMU25TYrZaDVOrWOi2AiSRAgkyNBP0SHlVinvByUZQ95333247bbbjFjfOy0xINlgSM2gL3nrlikGKk8GgRmrPpGnivpUsC4FhpLqRlIQMbOPk8pEYEKeMZJeSNJiz0n0e+qpp8wic7E0k7GkaCaGLtrqfCyT9tLLm5cHiUKQi6lLSqLxnnnmGdNWIb/tGLpmAm8CGD//+c8N/VRf48wlzdD8tcy9roFWXtVquQIbsp1RmZVAab6SQEkNozGs5Ea2KZLs6Br76ZNHgQIaXI6XV+JyagGGzjJexqXGaSBDrqvBs1SnFGSjqywd/EZDmWP0aSkmUL0stxp5mYX8Yr+IzrEelNMuI40fL1o0bfTUGWTdtpMrmbZzAa4epITpkjqRRZu4NHqWpNtu3G1uehgb86WmHUHPiQEgdR2je9KAsnR2N1u3g4+YCfD5WzHKVaDHM3AqnSoTvvunFDqJd642Ai31PQ1k9o1kAVxgzthHMkYI/0mFMcHtOdLs1QuvYG3xemwquzHxAWaoKTD3MiUl7zS8TXXM2IKrSjSsCzLazGp2DnczGy+nY97ddTLXMsDwggBzYryMvIgBWSHzWF1VIb752E48ftfm6V+r7T+jBOMwlZSOCGKhAYauiktr7Sx8EsMXYJCNgZi8ttK9S+IgZq8vanmKyCVVahIxSTFWfVnLKFBLjccmtVPsBcV2ePbZZ43YXxIAxXDQV7lULPoK1kMoGwL1LwYmA1QxWIEUzePjJNHQOd9zzz1GkiGpjhi8fqKZzk1SDkkGLM0k6RDNZMQqZizmrTIrBYqlmd0X89YqsgqEpf5F/9/97neG9jZOhsaQTYTAn0CGxpc6Q4BBcxM9Z0vyEBLQUDsFSlOgLf28MTh0bVRP10ReJbpumoueDQEhrS7rg4zZqHz9HivMZPC84lJczi9DV9MFlFJikb59G300nS9f3jtjjPIpoDGyuhA9eePIZ+yHYobPjk0VtMmQAWh9L5eBpy3A8tptlGbchM4f/hyDDAGevnkj7TFoQEqXyrTJAi5xkc4gXPIs8YQPcDpNDQdROEFvOS6UNtRJtcV9G5G1dcvUvGIHX+D9MNFB+ZhUJhPYk67AXNFeJvMZLgI0FBVhQoiDC+GRto5kYZJMIZcxPWQGeIpupm/Vv8G1Uao/UiAvqaTern8Tz595Hs0M3y5328VILsjYf7qZiJF6NsPgvFyOeXfXySwCwJAHh6yPLVEpJ3PON874OsKb2mw4OZc0Tpk5IHWLAIBVu1i9hGkWaWv6YJswLWsrCvOwZW0VHrp1Pe7ctopWzNNFc+GeNxhM/5+mYmMsKMAws/bQ2tlfhI1Ahr7QZWshaYVsImSjoXgLVpIhxmi/wMXMBB7kbSBVifW4iJ2amKVcL+XxIGarr2t90cvLQsaMYrr68pakRD+NJUb39a9/3TA3fckridnZX+wYdl/HvSl233vMm7f92vp231vHmxfwUhAqSTEELsSA9aX/1ltvGZuIWJqJIYsRf+Mb3zBgQ1IapdnGEfj6zGc+Y2j1q1/9yoAGjaHrIrsL0V92G6KZjVcidZUkRAIhUjdZkDHTONbuQ9dU10c/9a1yXRdJQ3RtdM00jnVXFrgRCPzTP/1TPPLII/OKyeGl40LmdelDjE8T4nytkdo4jfDkAW6v62zjqb1CVquPSe04L5CQ+jDHeJwdqH+VKa+kkDgqi7n1IgcX4a9GnjTnFZmBfc+Zc1WRndgijB3bZTYXVMvIz0FnWRU6CFTrTtOomS7PAUo/lcKUso3WN/ADjN4d1VwhNa0ddRklKNCy64ZgnKzDMPPSC1CXX8u1MY4alcn2qp3IuWUH+t98FwNv70HqTTegLbOV1yaJkowivsJTUJKfgcy06coILYgW6uJS8JeGMZ5ejdQdW5GyPHpxwNhzWej97PEQVjNSbBntR7SE3PRZJj5i5Brzr73Yoq0uNGm3OZSEG6ma2T3Rj9cb3sSm0k3YVXPPFbm9BmlYe6hlvzE2Pd99jsNFj5n4jOeu6YKMswxgIvfV6DuXJ2duZPMn0ttCAgz2mJSSZsbVTbRqWSFWlBaguCDL3FAGdAgceIafOqV4hTFlMbuxHaWnpaKkIAfLy/JRXVZAvd90wyI7XrjreRpk/h2BC9VJfPAjmMUzgPfN481r8m412872yq33mDfvqbLQWSt10Je4Fs5SAC2pOOQ5YIGFAICYm5js3XffjS9+8YsGaKhspiRmdQ+//MVoFflThpLygBDDEpPWT/1qfLtg12OPPWbiabz55pumTG01hlURxBtL40gtIymC6ovhSuqQSBJTFVPXF7xUA5rHXMGsBJ4UVEyRMmVDIumEpApiyPrpnAS8ZJOimBNPPvmkYciyzVD/AmxSG8mIUvONl6S++Na3vmXmprVLBLgkVbBjqJ3GkO2LpAoCibomOgeBBUsLzUH0iU0KKa6YJaKbpFPykhFgUXudi2XOdhzNVX0KxDz00ENmvJlsa2LHWsx9zU+ui9WlORgNhiIvRw44wWdyWWEWsjJSuSpnCD2DXGp8XALmSNKjpba5mTROZmFRTgZqSrMNMHGqMNzzJKqo409PS4KY6jKujZGawtUbnGumxzovS0sL0KWTiKazf9SsAGrHsP1kcw75XN9jmO6NvUO0r3Kf60g2NSWJ46cbmvcOMXw9+7J92HnqHBUMSauO1tC4Ua8cW0fzrOD7Ml1uH0uUNOcCznmUSx60XcjF6JkLGG9sQpoDMrTq6sip87TDyMFAZS6GA5dRnk03Uhl9drK8+RhXR13OCFqbSNOIXUYyBemNvQ0m1Hb22tUoePA+dP7Lj9H8y1+h+bYRJGdwDRkafeoalHKJd3sdok55sAtjje3oYzSBhtIVmKyqQzn1NJZWUXUXYUfXK4k8sZYqk5rxVJxP48hR7/+PPugE778arif2aH8Qtw2FMFaQhmc7z+KVi6+grmg1VhCwzSfJPfhM50k8e/KXJirphAesx/YjSY3uTgEdfa/rjpsvbV2Q0TvAdRpiAYQoGPWEmE93Zx7moHPYydu6se1Ubqs4mSTGbU+jtOJTO1biM7etw5bVvCFnYfLOoEu+CY82AO0/oDfJHyLnoM+ZBZdgTKfPYp6o1eOLIWpRLKlBxDgFNCQe13GpL6QWEfOTGkQGn2LQcyWBAzGl2tpaIx2RCkRf/wr0ZF7yVNOIedl1MWRAKdWNAM+/+3f/zjBWgRDZIsQuvmbHVt+SFHzqU1zoiA9gXV2d6dMen20rJv3oo4+a+dnz1FizJY0hJv3Nb37TrOUhg1bZlIhRywhTIEW2DWL+Og/FmhCTFl0FmFRHW60DMpMUSOUyNBVIkApEUTalGtH1EBBQex2r5bmrf/UlAKM5KDLoHXcwJgDnKTsLXdPYpPn/5V/+pXFLFciQJEMAUO0tYBLQ0DgCbQJhuuay1ZEkIx5wiR1jKfaTiRBuW1eGAurnJYkIOJJKvddzyNxvWFGAi22DeGH/JWgZcBu1UMfVdteGMty5sRIPba/G2qr8CLgKRGYuqUZZXibdInNQwDWK/s0jGw1gIVkjiX2I4WmMtp4R/OHAJZxq6iPIjFTgYZNuWlWCB25chqMXu/DyYcaX0eBOEhiqJBh6bAdtDVj2+wONaOkecucpMJHCCJL3bqrkeZbjMztWYHNNoW1utppnBcFQFRcJW6qUmpxEV1SCq6JidBQROPP+GbtwEWmbNpopaNVVua6isgTdRQRyQRp9cqGyNHKp8NndwJv/hHBxDZJu+xoCa3cZA8bCrCI0MIx1J4Nu5RSupqrjLoydOIPGt15FEoMdltx/O/pC2cigBKM4jmeJBg73UIrBIJKdY7nYR/fYTtZfT6lCVhypx2LRStexQl4mVKHvJUBlbGTDjBdiPIbgMJ4r9w9PYlffCFoFJXIAAEAASURBVCpGxnALgdtuGrq+07gHW8o2czXXUmSlJn4vKHT486d/g90N79IlNmjcb+PNVWPnh5OxlgBH99z5ZILmJEryyB9otRivSdwyl2voOZEcI5JINlFuChkwe4UAw/OARfqjEQvjTty2sQrf/tKt2FBT5oz5cdkQs413m/De6Hudywe/xbfTcERWKposBcAwtF98eoixiZGIcQkEyJ3UftWK8evLfTaJwkwzlOhdjFsApbeXkf/aGVSHX+X64hdD1te0+vWCFkkLxAhtEsOcKQmkKJqoTbPVtXXsVkxUqh/9lObTVkxeEgSBBzFn2Y9ISiMwpGOSVnglKmLQFsAkOo5dCVXjaAwL+kRTMX+No7xNoqVsJWyaaRzRWqBEP4EJSawkWVL/uuYCQkoCE5L06CdazdSfHW+pt2LoG6oLzW+msd/4sAWvf9iMg+cZLZJf4Ep6pFJ4T+VkJOOuTVW4aVWx+ZmDnj+qpzuvlExtZUWu50h09oOzHXj7eBvePtFqQIGOqq1+UrHsXF2Kk5d78du99RFJhXM/j/MFva4yH9vrIt5ZLx++jFOX+/jBFZmndO/KS4Jx9w2VZtl5LT0/UxIAXYqk6ecRZASycimpqMYYgerI2fPIoTRM4cDHLl5EuJ/BHHduQGvmCFJpR1GWxdVQB7isegNt2Ab4Tg2OIvzmfwMGO1C+9lYsL6ijyuQIvSqaUEuQoVVS8598GAPnz2Lz0YNoW5+H3chANqVH8TxLRO1gM9dBudiDYMVqNC1fjcHOEB6khCmLIceXLOm+CtLLhHYZJZT2XCAnTUyuOvsMdS+kkJ3vDAbwSN8wKiktCZAPb6R07ObsFPyGdhSvnI8Ygd5YeRPv25nfmXYkGdT+8ezv8dL5l9FPN+KZFkATwMji2PeOBfA4w1ukUMtxhNfhA94Dp1LDaCfYCNG8Qvf7XMkFGaUFmUTUDMYlMGFaepovIMCQ7cU3HtqMv/nCrearIN4EwyGGbw5epH6PyDhIOdjkEKtxXobBe1rEztMccubtmX6khafAk3V7kxqEui4E22nU2Uy5EPOppLQUvQpCr2TG9zT2AihvXgR0qzETd97qMKaeU+RprJJFT2L+Yvr6LWQSYyspKTW/RPqdD0ObT93YsT9KW/UlUKH4GTaGRmz/3v0rGUttBPL0SyTNdwzV17WRtEq/6zFJImAeQftcakfKclM48xnP/ZqObWsHinStR92qnjSUO5wzDx2zZWZrK9l52qO2UuxwV3FfaqJMSpuHCTJGOwowduosDT0Jsgh0R87Vk76UdKwoQtfkKapJqPaW0SeXVEfbGQTWUNK28mZMnngVeOcZ5AzQZiMTOMQAU5cY/fMWBoFUSO2UGzdh4v6bUPrMCQTeIkBZ3Y3izfwocdYs8Z5+eIw2SudaEewJouyem1FUswGNXJG1qWuI0qilAxm6VMlkwnU0AJXK5KL4hr2O3gk7ecbUNkclDZjpflONSdphrJ9Ixmf6xrBuQEG4eHfx2S2hivb2oXTspeRuf9thvNXwGpbnr6BEY/YP9kGu7fJOw+s09HwOrXSXnWkBNAEMRifBnWNJ+BIxwZY+fiDy/tw4mILbKeE7QE+jfQQbR6iWEkiRV8xsyQUZG2tK0NJ7OcJUvQRaMIBBvq3ImQ9vwbefinxFeicWnuSX1MheolzehMMf8hr1EiE7k3eeRvc5tPPzMn2njunTm1fBVMOYa8+KLgBQnj99GOic5clLkZ+bvGOpMKpPM6Bb1U7PFHi6MPtuVWa8eR00+26hqe7/8SngU+DKKGDeHvb9x23U/pV1Gb+VHYNHlfW+c82+Wtk63HqP61Ckkcm5f6bVcY9cvUwhGX1ORhKGissQWl6NUNNFfgvWIxyi0ee5i0gtY1TQ8hz0cN0SGXYWcD2OcMvbCIzwXb7tCWDnl5FUsQ7hPT9AyoHfUpKRQ7uSAdQzKNdAsB8FXPI8mJmM4+sYI2J5CFXHjqJqohQ1t29ErmfNEkuBiZY2DBw6w0/uXCy/cxvWpVfh9L4GXGofoASozNje2LqLvdVbu1JeJvwg/YAqk1F6iERkU1MjSzIhO8MiGrKm8QJ3MgxCkOCKfjvu7WFrh3i8nKqKRwYncEv/MFIJYpQ0TgqlkBuGx3BTTip+nTSIN+rfxIaSTbh35YNcjG26B47ajYZGcYCrqz7HlV8vdF/g3HQj6kh0MpI0ovFbCTC+0j2KTQMCGBEmlk2V0EZKbuuGU7CTEs/9XLMlPBpGXiyPi+5yyoV1y8pSvH60hSch7uqkBQUYqbjzhiojwbDd2214iOCi7wdk7KfpRipfYxKUZt5hdyokrXsiDhM2G2/ezllbp1xZAQc3Me/uzpR3KntBhClyG7KPGfKq5z0WNbaOmY4iGW9exWbfKXTP1db3tz4FfApccxTg46xXgF7cNikXeUUoF+ctbyt+DLeSJuTx67k9LQuhujqE6xmlkyqTML2RQi3NyLh5B7rzaZPQO0Cjz0rk0dMk3EyJRCYlchVrqYujpHTNLqpcKD17/0eoOv0aSlJ6cJnBp9q5KJdAxuBIP44mt6J7RwFWDgRw++VjqBq9B+mO2sslCxntyPGTGGaU0KyVFchbtwI1Q7kEFlz6Xe6sDPctI98lSwQFuWTAa7hgWjGDhjXEqEx0D0xSYlxDycSjw7SpoVHy/owUHCA9W6V6oBpNX/y6IyTpyOTenaPAA1STFBK8TN1BvH8EQKg6uWU4hA/Y/nQ3Yw5dfA2ri9diZeEac8ohghdJLjoYB6NtqMUY2L5Jt9cjbR8am7t40k/NMYlustvpxfJ07xi29g8R0EwxIxmBKmXK/oQeNdWDFPpXDCGLqqLZkivJKKIO0MMFmZ3q3C03Z2pP19lGlakLe1zDRvI6oWxKJf79n9xFwzcvvqNOp/MZSi9+ERFl0nAm0oJ/3W6YcafiFJqNN6+xbHLKtRvF5FnuHorJ26Z2G3UOMf3EHrNttPUeixpbx2xFNzNVaIqccnOu3jq2nb/1KeBT4JqhAF/IMuCU22WK+QiNvKFTaayaSa8QE1zpGnvM5TVTxK/nhs4kLphWjaTcfAqdTyLU2kYvkHEkrapGewrt18g7KnLLkdbViMl2urqWrEKgdFXk0in6Z/VWAzhKGXOjhqL7Q+1n0HppL9ZmVZpInx3DrUjduAnDo8XI+81uVH2wB+Fdm0FXN/fyT3T3YGDvQRp+NiJ3/SaklJVg+UA2DUTTUU+Q0d47uqQgQ5dSDLmO4KY6SBp5vEwMVyP4WUkDyi8w9PlnqM4pJGO+mdKZveS7b9PW4ShjbHRJjE4eImmH3FU/TduS6mHasUwxD3P+GiuV9hCbaZuxlbYZ9YEJ7L38PuoYrn3nMq4WPdqDlqFWhm2/bNZCaWEsknbab/SM9tI+iHYd5MexSXMMEGBsJgj6cs84dhBgpCmkRZxk1SOZDNyZRdVNgFKWiJwlTmUWuSCjkC5CERdWli4gwDBEo5vq5+/ZiBUVU/pfEzmz4/+lIctLlFiQs1JbEkkkofvwMTMfgDEjk4/p09u/BnX3lffucN8LFmKPefe9eW+bqP6dvs0mTl51NZmU6TeBOeT/8SngU+DjTwE+wvqivpVeMPJoUawLm2SlX5STidX0bDlDz5RrKUmaUEzDxvEQjYaLy5FSyzVIDhzGCM8xvZjxMGor0Tp2AGkpWSjLLEG4kfEXpCqpeoRWo+VTp0raoIyxiG79GmqykrDvxC/RuP9nXE2VKxJTCjA02k+3zG04s4LAIvciSna/h4Ib1yPv80+adUn0jh47dRpDHxxEOr0sslbTwDS7EJUpqZGl3+u7cZmMfBVdaZcyCQxUUZKxlvzsIFUm40YmwWtP5r2aAONL/eN4uGuQNhVidpNYORiiiiWIGzMz8B7BxjsMePYhbboLJ5PwCL09t9CbJIkSjnhJjL5ylJ4mQ1Rb0N26iQadvzv9HN7niq49jJTaNdRJw84BuloHycLohMr6ssGYDWCsm0zGl3pDuL13EJmUVMyVCEt4blL1zM6vXJBhXITCsR07D4fZ2AclXpmmY4978mK8nAQDRuPzd90QPeeen0YAxgAxkNuUGW/epa9TaDbevKfLGZk86ztNTMab90zV9OTtQwWel8M08OGt681PDWa6nNr1zjtO3o4ngJFWF2m7QH+NsVnUHEmJmP0FGsrvxqfAJ54CerQksN1BD5PtdGd1XzkOZfRKlmutARmxBz8m1Asy2mYvF+1KoeShkAG1xEhsfI9Jqir6qALJWL8GvS+/jrHuXuQ8tQVDZTlob25HfkYhigNkLc2MQkvVCirX88NpyiPKnmJSPiN/1t6O9Nb30XBqH+P0fA9dpSWYzBxFdlIxLgSKEdi6E4Pn3kDvCy8jja7UmVz4bFIxdz44zNDmp5C/IRNpFfS+oQtnPkMirCzNxf7T7ZRm9OOOSQIhAqAlSxwq33FlLaGRLFdmMVE715N5f5kA41MEGIX88o9c8si8Mqli2SjVAwHDjVmZ2MPIpjnkO3f1cg0WAoSZbg+VpxPsbaFtxpacFDRTEXGethbnuqi+4j+BCQMrBC4IcmZKkmBMEPSt5hy/2DeOe3sGkUM110ImF2SU5GeZADSDIxZoOKdnNvZU45VpOiy3VWzGYWJJtBi+cVUZQ3UT6TopPHaWLk0/ocEQUYS3nTd/1QGGnS237rzsCXgKopg1y915e9s59c0mTl7dWkAjMduyrzkDLcxGro+KdSH3St18CrAkF0U/+RS4HikgAC3h6Bi/AsP8KjRJjx2z9jFbivOWFGM+8QSWYk6JjDE8PoSDzR+YkNMri1bioTWfZvjqYqPiyc3kO4S07B4n81pZixTGzQjS+yBt9Uo0Z06gh1/UtUXrUDDQh3DbafoCr0SAUouZUiUXSyuhmL+puBFNA6NobzyMNKo/uBwa+oa4LsiO7SjbkIExLubY87sXkbpiOUKM7zK4bz+jgXYjeyVVMYX0quB7TeopBVhLp4pKKpP+4aAJejbT2Atdri/7VAKwOtpLVIZScCk1on74CqUD99JOJc9IMDhVh6GovpEGcCK5tLvYTrCxdiSNLITGlFSnOJxixmmGeSGW0x7mluEMHKI0o5mGpHLTTjTJi0QushsoZfkcAcaDPQMGJCXaPtF6LsiQuqSEgWiGRrkaqwwvlcxZ2lN1tlFlTiVbxZLFy3j5oO28odp05/7p/hk9R2jMYl1D1c7bh8uonUKz8ebdntjObRjzBmG5eygm70zb7cXbhwrN+E5js3E7ih4vqh3ruPNmH24TJ2M2cfJmPLdyZE2UrJUqXbCkAE3f+MY3TBhqgQwb8XLBBvA78inwMaJAVnoqo2RmY2AkyJgTkZeunrBU3vulfMct6dftx4guiUylj/r8dy+9g9+e/BWOth7GmuI1qOYaGbevuMd8oCgSqexMFMk0xPd65sbV7DaMjFU16JroY/CyQZRT8pHX2YTAIGNjrL+Pn/eVMw5dTLXKCrpfvl9UjhPFhWjpPEUpRgaSxzIYKZfLPayrwLJ1D6H30kX073nfjDM5PEKvljNGA5NeyY/XnKk4IssJMsoYjqGhY8gETFNk1aVNVJmMhrBBIIyeHl+ih8ZdBGE5Thwa3Y2DyYzgSulBzsQgAVvk3S+jSuXzKNEg9phiH7NMXgAlg9KMrUOj2JidhRZ5Y0bxpPiNBWIm+SwU0MtlJ4UWn+4fwS1UzeTPYcAZv7e5S12QkU7UVVtegEud9McVszTnbpmfs40qU+cssFVsxnuSRFpaD2XTqil9XHiccSiG3mdty5Fj+rDFbn/OOJ6NsiZ5x4r6RInpc9ocbQfcevtQsRnfaWA2buPoulHtWMedt/pUR0pOxmzi5FXFO28j1aLdSmYMKFO9j5AUfdIb6OojdOU39SnwsafAyooc/Nl9axhanOvj2C87PX7M15XnQgaMfppOgXYaC752/iW8wAWztDz7vSvvx7nOMwQdu7Gu9AYTh0EroWbTa6N3cAwjBAeFjz+K3FvakLJhLdr736S0iMueB9KQ2kZpdVo67TGkKpFTQfyUkZKJWoEMxlzYT1Vxfx5D/nMtkkDoPN+NG1BKG43suhUIPPlpaG2Uzp/9mq9sSi1Sx5G3ugDJtA1BdiSwmUYoZyTUOoac332ijeqoXtpl5NFGxJFmxZ/CgpYKLOQzQNqDtKm4bzCATX2DyKZKRElyiwlK9g8kr0d/IBe7cAiFjAllpRmqYz04lE8kSTWygsBk53A6jnKZjHa6ZM5m0ifPFalPVlI98sDwBB6mgeyqIQZPowRmsZILMjTAxtpiE8GO82BymKLdRpU5x20Vt45bIFhmKJZMPVlVsccAZ/QoAhnUS9GNx4zhNmHGZdROodl48xrXSV4m72XUmovTZFr/auoeU967w/2rCTA0Fd0d6RT/pU2plljqJ58CPgXmQYEyMhr9/JQYBaReamKsiufPPItXGUGyMqcCn9/4FAM8LcePj/wrjrQewoeUatxd9ymGc0/l8g8pBHBjGOACZtX33U1AMIF+Mv2W5hbabWShNMiv8fZzXCCmhgaeknTMnGQgW8Vw4LkpuTjcc552BmPYQW+Vgp63UEEAUZTLqLPJXH10+1YUPPwAWv/rdzFOz4fyXcuQUUXwQC8WZE+9LwUg11cX4K3jrfj1e/XmG+629WUoZyh3vl0XPQkwpJFh39jHZRT4Tk+O8tCYRE9SHl6b3IQTXMI+mzEu7k46aAJ5eYHGfCapdllUs2wfHsd6XpdmqtsVtMsaY+qc9RMYkfQimwqS7eM0LKWNyJ2kYxmlfTq2mCkKZGxbU0k7iSNmSpFBncHNxjORKOZs63iOi7pMOtEcoqs8LkbkptFTpLz2WMdtwswnHWCIJKJL4S38sxSPgwb0k08BnwKfZApMMJ7ChZ5zXCzrF5RY7MGG0nX4wsavYHPFVkZzZITHFbtwuuME3m3cjQ1lm+gWWoJCRn1s7hqhzQPdVldEbLt6ey+gnWuQ5KfmoKS3E4GhbgRW38HP+qo5yVvJZd8r8pbhLXpGVLB9GT1R1ncRIGRc4HLmVLcwJXHNobwH7sVYwyWM85e/mQvIBahu4PooyMhzx5AdzI5VpWjdOYpXDl3Gd185jcP0Nnlg6zJsqaEah+qexU5Se6TSpTcKOLBMquqLgUocCVbhg/FlXKV2O1YmtaI23OjhhfOfnUBCDV1d76U0oy89g+uLUOtOk4dxXttxjjtBmoQI5komA7h7ZBKPUjVyw8AwMilxcVnw/IdNuEUUyFDUz6LcZHTT42PKnVV9eaaSIMAwoIFgI4UhVrW4jpvGmoi02J/bJTM+wIjgCgZfQeGdLqn8jE8BnwI+BRaLAmOUGpzg2iG/OvFzHGs/hluW7TQSjDXF6+j9EmENW8q3YWP5FhxvO0ppxiGCjgfoxpqBEC1rzQqzzuQ6CDB66I1Sk1qAwq4WBOhOimUbaAgzt0SpMLOYdhk1SE9isC+Chqyqm1A08D7uCh9FDlo4AoEEU1ptDUq/9jQmutuR1vQKApeokmGsDS7lbY7bP8tpj/PUrjougJeHl7g2zPtn2nCyscesBXPvFi7OWJHHSKPmS9c2mfc2AiD4MTjD92AUwGDvqjaWnIlj4Ro0TJYw0mcS3hxfjY0Zm/HFpC7aZ3BJj5k6m2N2aieVzL29Q6hhEMseggpFHB3hUhkj5L0jVEWNySiWxqW3MbjXMkovtAaKy4Ln6P+jHo66Ovm8eW5ZvwwvHbwcARlmFp6pzBNgxL0CkwMEFbZPbn2AEbmGAtjpG2nERB2mnwwFghQDatXKNK58GR3EzSeQTwGfAh+FAkM00NzPMNO/JsBo6m/CA6sewuPrPotqenpYUbv6L80px64Vd+Jk5zHspm3GhtLN/BDVCrgU/Q9QLcKkj8bO4Q4Mh4ZRMZGBXK6MGi6splfJGnN8rj/pyemUWCxDMW0rinNKMFx8B+NFDOOGrjeQf/ldBu9iP+k5lPQmI23DOlpOFiPc9BzCtPUI5E/Z+3nHKaTB591cyXYN45G8e7IVrx5pxrP76nGkgVKNLctwO1fjrSzKpn2Ct1Xi+TH6vwymFCItKRs5YdoxWtufGboI0POjmW65BydqaSCbjUwG0GoN5eKP41uxIfUydk4eEyFnaG2LdXzmCVfQILacq7SqiiCEak/Q/mI8JWikGRl8n6ZTfWM+8m2XS7D1iBgioz2yc80CAQw7e55qFO0sqmChzdoKpl5UZdtJ9AVwQYoOs763iTfvHHY7ib2IZnyngdl4GnvrevMazJ13ZPhI/3H6ie3TO2/PUKa9rOArGGwmBpW7c79OM3pZDdNwaYhuXxOewDMKWnSqsQ17jl9AB42n/ORTwKfAQlCAX7ojXXjt4iv4wZHvM+x0F57Y8Hl8adNXsIKronoBhkZLJpPaVMHVhCu2E2gcx9H2Q1SZRII69QwFGZiLIbFpbNgx1MH34gQqh3qROtwXiY1RMLeqRGNIjVDDse+ovg3bym7EcLgKfxxeh+P9lIKceBNoOaFqU4mruIb7WxFmAC6vZ8lUhUhOqhMtlPbkzlp8+/FNePyWGnTTGPhfXjuD//rHk3j7WAv3aR8Y+y6O7SjOPk0lcRQrcSapxniKxKniFkl9Msn3+hlU43ioyiyJJaggNnJovAovTm5Ha0op6eBlLG5zk1EfYtYCRWobL0XYDfvgezSJvCaZv3RG5cwZpecIV8tNkwpnniersYyjrWMCEW/cucqiJBmqfNumatQUZ9EFaJBgw4mZETUx54p4y+wERCObNyOzbtwLyEKXnrY/NfBU9mSj7gIvo1Z9b72onZhj3vlqKDO+09hsPB1563rz6t+dt3e6cfqJ7dM7b89QmoqJuzrJB7LsUbP7Sfijm72Prlcd9B8fo+vUCIPYZKWnoaaiCDmZ6QQeQXx4oYmqu2GsXU6RqJ98CvgU+EgUEDOXaP1k60H84eD3GI2zG1/Z9DTuWvMYCrKm3EBjBynOLMWu6l1UmRzB3sZ3cUNWFTJSUwyDHmKEy6TkEYaxbkM63TTL+weRlEq30SpKZdMSXwm1mguqPb3pT8lIU7D7KHCOKpKuZXcg3PcOAlq5VVKRrIj9B/rpfTLYEwEyHqPP2Hnb/Qy63G6i7Uh1cTa21hbhlSNN2H+uE6epQnnytpV4eGvllBeSbTTXlu+vU+MVBFg3oCblPIqNl8i0b3bTS4A8sT8pB0cnGQ9kspBnGGEAXF4MAxMpeH18PdUmjXg80IfMsMKIe2GE9gRSGKo8pRID9EqpnmyiVwrjkETViz9hU8fbXfxqcUulUhlLzkBbShnSw2MoDxHcxfKuuC2jC6dRJTMtBU8/sJkWvQ7+iOrVGcFbZkHFNIDBgrgTYqFbbvvTpNzCqGz0WXnqxDQxjdzDzLj56BM2e4kCjKhO2OEVAwzPHGLnJVrKq6TmL6jH9HjheJpcb1mRQOChoa0bQwxQk5mRhiAXDDp8vgnnmtrN6XbR8rmfIKSqKB8l+RSVLmFSGGhJVby3+RIO7w41yTl4pTvuAT/jU+AKKBC5n7l2CqUNO7j2x9fbh3D/qcMoOPA8cOE9qiE6+Y6b7sooD5CNVJNsq7wJZ7pP4mwfA2al6SMhiEGu1dEz2oW2kU7kjgyguJ9SjMKaOb1KYqefxYidcpOtyl2FLrp/hqkeKdj+IKW7XLX1zDvApUN8p/PNoR+XiccYjT6lKsmcWqoits/YfS3wtmtjBb718AZ88/51WFacg0EG7IqEfddbKfEkgNA3kYZ3J9bgOOqoLpnGSp3OIv1eDFTg8EQ1BidksDo1Vgrz9eOFeCG4DaeTa9lmChEwIL2RXvSmFOCNlO34L5OP4u9Cj2JPYBOCSXQPjuJPic890ZoCR01JZfhx+G78GPeYfJJn7on2M02SoYZP7FqPn73+IS62UrziuuA4hPG+ee2AMwIMtZkiqJmUu2v7U6lbGJWNfsuzThST97RRe3fXmzcj8ph70OnDsz/VMLpebJ/esZ1u3UFNdzP0adp5j7mNI+Mxdj8ybqeD92OeA9d3dpCW0I0dPZSUhbFqWSktvjOMGPDw+cto6uxjhNjl6GD0uVTaYqzm8UwGV1rK1MPljfsZrrc4L5vueh7PqKWcBMfqYBCfEYKw8sJc0oALS/nJp8BHokDk23dD5Q6suvkvkHHhINJaT9G+geqI3CKEq25AUvUWSggohShZyfeSwH2E6ck483YjzTiKY13vY3A8C1kjXLuEEaIHA+2RSJ+D/ShkECpUcsXVwuVXNFOtntpG74csOgyUrOI8Cu9H+I3/Bhx/GQHNK4fz7KP3iphBAQ1CU+f3fCpuyjLaYjx2ywqGfC+mmUcy8umW6xU0JzpxqTBOBUvxbtJG3JDcQGlGN7kG3+eeJOqNExCcoMHnGYY5N+qKKRxhqCsfj/3jNXiZQGJZSgfKxikx4DzV7lzyCrwavhEvjW/Ch8FyeoskIY2RVVckd2LL5Bkv9/KMGi8rHuQZOF4VT5noq/EPB1bhd8HNGOXCaUkZk/hS0ttYNtlOeiXeV1yQkc3Qsf/Ll+/AX//9ixGDFhOdizPwMuuEAIZmHW8yDtM1Gw8D9mSnUc/L5L3zUEW3nTfvUMxbN5bhe49587F9esdWt2Y8Z1Bv3j3mjD1tPKfc1GNDE6GNqoC1f/uJscWQrUUrAcQYjZBWV0UAhsjRPTCCcUozpCoJ0k6jlwFiivNyUF0+5QPvod6iZrv6h3G5s8eAnKsKMqhK6qQ9Si5p4oOMRb3kn6DOGSWyuA4ZBcv43rkXaD0DXP4QYDjvwAUGSTy7m0abyxBYtgWBFQQcy7eS0XOfTG89JQ3bq3bg+ZMvo2X4KDKTy0xU1e5AF8a4IFfFQD+f3xURNYYMNa8gddFGopvhxfMZhKsgL5chw6kyOcd5cW6Bi/vMUvHob4kYfXoXXZvnWPIuWUkvE6VxJ1jWPLsgnKB9y2Qa3sEa3J58GncFej28KNKbmHVbUhEOT9aiPZQdJcWw40l90kupyMvBDdiYfgkPpw6hO5CN93AD/hDahvdCNBZlW6kvxE53j9WhNvNmlKV0o3xCKox4PNb2riaOYoXVEgVTatOUTAA1uR7NwTwECW5+PrYTSelhfDH5bVRx3Fi2ODVidC4uyFCVu26sxdcf2owfvHISk+P0rfQy4YQBBjvytjNjJ8CcYxm3lzJR/bGi053JuHkzUPTY0xi+p/JsfcZS0jRz2nq6mDo1p3DaeM6ctNF4AhjJZKDr/o7ByRIzkPL0MGdWiHmAX+OtPf0G5pUX0c+cEgMZWnbxS12IXl/qbkTEOXtcmAqjdKMaoBokNyODly6ME/UtGObX+pnGDpQzaNsa2l8EaZ+RQbVdEedXwBUrbZowFu3D6KQqJYkWUIU8Ns7AN7005sqj7355YZ4BBrb+lW4n+DCHaNDmXT1zrr5kWyLpx//f3pXFxnWd5/9yOENyhsPhziHFRaRIUbIky5YtWZRcx3GaNE1RoEkNx+1Di64PRfuQBkVfirYGAhQtij4FCFAUSFoEMdo0sZsEaWs7jutISqwotiVblLWSoiTuO8VlNk6/78y9wzNXw+GIHC6yzgGHc+69557lv3fO/51/O/WV5RK06Txp95PjWA+dlboE43O/Zrn6sgj6jkMvPouwzwFIgOqrg8rWJdc95tpDSAFuuV4JaQM+Vsdxkek7AByXJTlwXiyCjg+wwOx9HUDkpFhPfFHZWHDjsx5IM94dfFcuF/XKXPwgAEFExrxQsyAuRhjvnq+pHVJZ2E+sM00AYDD+xr5mv4SwFboEWqXowKclOXRRkpfgtloBScbsKOwzQmIFt99Wqwis9jKkGac8j8hBTz+kGeP4vaakGWTUVKNcK2qSC4iLsYQomz54lWRLVENcj9fK9zxHJeL1y+XlOnkDoON6DHvDgMF7eR9YBmsmIPmf6EHZ4xuRX7dOSYDeLWqWv7dmgpyoVYJ9VJqlCG6tbfE7+KatJSpbJaWkGD7EI+1EPI/diLnB9pdlIBaUl+UpbAmyLM8XnZLGZbgq5zE7rQoy2P6fPd8jw9g57rV3b0kiupjq0v0ADHQs6wSpTmpXtGzqBu3EjgcYdl/Vl53PBTA4wABelaIWoPK/w4/m0CqPemOn6a0xODED9cOUkhx0Qe1wtHs3GPKivHOxHyLCUjl5cA9czFd/2dw9mIIdxSi2AY5Bhea2QneXJWOthy2F2/V0BhIK2hkEMYHMAhxcuzMmo5BszC0uydH97RIGUIgiSEznrgbskVCcZs5k+CNg5CMTs2oD5SGoVQhYGmoqZGB0Cj8+S559vAvRZUPurtz3McfGlRv+8koEPx/0DWHfhWl55rG9CmRM312Qn/X2KZDUQzrbe2jkVaFWyFpV16sVQpa4dRSAsndgWBbgBx8oLZHlUEBqEutbUWbWbo4+1hTgTqk0rMTH2vuMyHgfVCgXRS6/JfLha1BPjIr19O9BsnFEOmv2yfGW43L+9newiLkkw3cPyoh3VLxzUxKGeF2aEBtjnaoSvsN0i12EMSn3mAn6wZ6gzpCOp0Ta8bnxDuzXoDolIKpuheqkZtsfC6UQs8teORPvlJO+DvmEBYNUDkSlpCx4gjD4bJebiWrMUYoxZO0zpSJRSCRORXfLxUSjTMEVeHq5RDyoiwxeT44dx6tFT0ibb0yein2gAEQm0OBRUhaLyuSs54D8Z/yE1Htm5Hc9P5LWBGNV6TVm5nnfEKQYpyDFGIhXwo8mVTOB0EAsJC9bxwVex/KFojelCdfWSjlBBuMTfOWPf1n8//p/8srpq8rbRG2exjE7YEO1gBOqLa1BjGJl0Nr5THrZ99nddNex4wCG3k/m7XHp/Vbj08brZBn7hTusxvBd8TkYen4JEozNQ+JcRVMl4S8pgX3DIHYjxESC/g5PzsiV2yMIIR9W0gCWSWC1XILIrNx+OleixIGSETL3Vf3LOV5w52LURUmJO+QNwU8RrlVgW2OqTvbvblQ2B+9dvSWTUA0QYJSiL+FqTCZaYtujABleAI8uqFBuA1hchZFoc0OV1AHMkKk7KYYwxzHU4y0uXlOywT5QYkAQQ3DBvxhAA6UZlJLQIFVhDV7Chzpcdew0hu+7cMG9OTyBsux76ic1BDB0Bf070NYIuqbuiKO+CPpG2pTAOl9PbJ9t0k7F6Uc8kYTkCWNBH/hxEqU4bvA2CenU6Q+vg4bz8nh3q7TUVYsfIZYdexZ68HCcPvRvrefstGO+H0IKMHpm82HsOXIAjP2oJM++LHIBUo03vqqARkVnjxxrPiHvtJyTD/qvyMDcBzLhGZTgwl3MMYiNAUNNKV2fATsXH45LaV2oVErAf1SCWsQ68BlZxtbxyff/Gz9CLCk6ela8Tbb5MdEI9AqkEG8X0zajT+rohaGWPSI3rXrExmiF9KEE9v1u5pfZcdYzC2AxDYBB0KHKuycb3MJTlG+eizbLK55j0uiZkN2JW2l2xAyBwhwAztuex+Sb0ZMAL+3S4JmTltIxeR5qnfIkNkK9ZyZD3ZgP45Byva+kGO2QviBMut1vtluE/M1opXxLjmOBGpEvAG2Es/RRH1nmTKdfsfOcDF/6w0/JgY56+dp/nZOJWfgVg1Mm8UKkgAa+dSbL+xTASBFDG7lWu815HQas7kn/S5VbL8AgI9cHrdqwT6Bf6YsZYADndb2WKpfqhup/Rj+dyu260vXgvCpnn3fy5NssE4PYP4gfRvhF6BmByjc5lUJUXocf6UWssMnAqC5hotSA/aRqgcxqcGQaK5IlaW+sxcZHJWo1DB6rGH+xHqkV91YCqHS31AOUrMTGV5Vq/+zRq7rc93MSWYIqhBFg/WiL31XYm2AaIOECPEvujE2reBkEGdkSwQRtNthvgo5K3NtaXyVevKPL6FMNVu5MZLhDk3OQigQBViqUm+wimCzvd5iuU/8MJDv9AAhUddhYABKgadhCwOgSRmh3IJ0gvah+qsH9bQA47IOe6Akzh0A4zbVVkBCVqbJUnxAwKDrbIhG67N4anVT1tNTZ7nh2Rexz/8gExg8AZ58bgPfNDOol6KGqy0n1lUFpRT+csRAoXR4YlXc+uinNdZV4PkkYjc5KE6zSnb5yTLSkb2+qAfjwyQjoQ9ARhuTHAUFO/eZ7ayjA5xbDO8It6RWwRLOc9rhiZBC6bU2M10PJxsnfl2RZSJLnvgsDzK9KUWRWOjuOQW1yXPonXpXemR8DHMMIEe9oZWMXJo5OdNuZI+9vBBFEER3Bhl0+SFdrK1bedxisibQ+BinLCahz3geBvGLR6PM+XGTvryf3V5qAYA7bpZ+J75ETvj3ynDUJyQIWKqDhR8lWAJBwyhYiD7Kwrnw8OAhI5rGL6huRbukoG5EXPbNSCbdWJ40X18jr1lH5VhRSp0gYzwjaMKmQH8SOSJd3RHqS57NIP/Dk8O4NFdXJTyDFuBnH3MrJT0scAoFGP4HG8gm4thbL51FvLvnxmiDDqf+F5w4pO43vvt0r/3v2ivQPwTsgSaTpUM7uDH44zPEsRc5cKeOUlnBApqufU3nthP4Dy7gZZdLF9LxdPa/5joAKeEH1Ong5fZ9TVqED+0D7yiiHg3SxjAvZb1BlMfIilMVKWuBjjF18AC4gQgzhR1KyPotrrbG8s5QizAI8kLnQcJBMLYLVMJlnaUkxbAdSqw0fGDSlHVwZRwAAPgKzKsauhfRoyJYIWPhIUk85WwlcAwm4SY87LUEMyhW1AzCc63cRpY59LS/DFs+rSFPIGMlUKQUZBOOn5KI6GFAfR3rA942pGNIG2iNQEkdw0Dc0oZh1ZaA9zZidtpV0AnVy/OqdxQULAYjotkfmy291AWNW9dttOPfze2wKEhhMkLWgKdskHWmwSUlCHWw0SC/eRgmGH2qMEkhY3Il1p9rU+wGJBSAHacJxO0l1ITVUdSoO6QjBSxITPdVNCeheI9gESWdUJV6vJMoQoAf1UBJ1GWoVSoUIMkxaBwXwTBN4sHH8HpxXAqfUdOGeelarvQIqwy7sEspnkt6SHnV6wWQbsF35jgB/UH1Yx34LNmRBSDX+XZI//mcJLM1Ld0UHooE2I0DXL6R6OSJNHr8Ew5jnuCnaOtMcpJyj8Czh/MTQ5RkJ8TCs7k/CCBQqE9pkhAAy8lQlZtSzSQdUm1yD/cTbxfvlUHGfNMaGZMxTqww+hxKwFbuHAW28I2xzBNFDvw/g0A6V1XPWWcQhTchtT1helR75TvRJuRatVRJjqlgINBj86/ueJ6TZMyptidsZfJFSjARCV7xvwRYDkg9diqH3Vk09ABrXYtXyE3i8HE9WFwZksJEwDPP+5PNPyR/82hNwb52Sm0NceUbSMEPvSKr3FsTwHjAVGPCslvjL1B+A/gvl7JxOyKcP9Xy6AF46rIDb4Knhwwv4kCdOXLSh4Oq5uRb7CWDVPwGDQJ6jRCKElTEBB1ULtWCENAi9DvH+lYERqasqV8Gw3J4VZOzX7oyDgUVTXHMVGpNZtqBN2gUUOSJPlJ2eX1A2Ifr7QBBwG6CBjG9/axgSkOzvClURfNfILEexCqfdwd7mBqWemII0IgFDzcpgmSyAwVMyQylHqc+npBSXwFDRYWX34UhCnK6HAn451EHpg3NGALRGlIvtPkhtWuo17xYFBFbKMUfpzOg0jGvxyyMdmRgDhNKNStTNC1RdeWHNPgX6haAmciQuqrD9j7tN8hmtvOOQBsNtdRwSiUfh0lsbWgF9BCRsz0lcEVOtQpBD99+2MKUk2DMItOdznUZ/qIaqDZYrFdBVqMsYTZVSHqp6+C6YdH8U8AAIVJSBGSLEtsd+GHyF+CkHk6S0ba3UvSskf/TpbuUGmi6OCsg727AlvQOe16pn06/DwNI68nksmABIf/pvkjz9dQm3PCd189VyOgID8uUZCcNA06dUJSmJ6Xr6RCNSqksqATAq4V2SmUBPqHCsE78jFqJ9Mn7GTkqUQCxAmvGzeAekGR1SXzQuN6RRLsSbZRHun8pws8Ad5hvGz8VIvbxSdFSafJPiT0blP5Z75LuIuzEUq1DqD0cyoqQfMD79UbRbukoH5QWoTYJJBN20ObgjxaAtRn8WKYbefbZLlc0CBA1R1Jkr3bukylXavlaCFdC+1jr1yaN4ZhE1mat/9oRq51lqvQCDHMKZdZXlbGaTD+sRGQxF9ozOx9Q/PKlUCRT5x0GzYRiGUkRPKcduqEtSRp0JMEfYS2QhWgDSBBpW0laBL9lqiY8iBCDjnmjnIbEYg+EopRKUcHHVT7XGVXiWNNaG5NCeXVChZH9hbwyNy4dQ/XQ11UI6A7sQ3E8vDkpBqFagi2dJiUcmsEkQGSjHQLuTcbij3gUgCcPLgjYa7o6nXptMps1+c3yUHrjH4B7zPOoenpxVEUu9kABRUnN9cFx5wDQikNgMgMU0Xk8a2hLsBAB8AmVtkNpkTqIKOLByjbBoHq91SoqRqx8cF+lHlcsioi76YBxHtdQiVoakE+1DBkYnoEpJPeexqXkl5QjBO0cHV+6xmePVKcBYC1882SFP72+ABGrloXE2a2+oUPt7rH536gqlFfw8EAnRNq1Dn5WkH26lp78h9b0/kCOJWjlfFpCWIo801O9J7VWi0eJ+x0VV/BxUeozMqTxL3BXALdaCp4kwEvU6XWTdVRbymMz8eqxWzhQjgqd3CAacbXIDm6HRW2OzEsENtjuTn0Ly4C8CbXD8o6U9MgaX12w2HZSoDMXL5YfYM2Vv8ZCcxCZ0ytsELy6lGOetDjmLmB2LOTxhnLGoORL1rZXWBTLWqjSv66pvWgc3AjBUg3Zd2HkuuYyVdqGS00VSFHnLA2mJzgkK1c4m1EMbhI5d2HAIDOfDvkE5j2BXXNHSrZHCd+r6Gb6bDJ9Mj1ICis8PtDdmXd1SAsLPehJX/FFITSoCJWr133tzCOoDj4zAkDQE99N92GFxF6QfqyVKOghQaMdBsLMLthiUDFy5Dct3gAKqhwgN+Lg4Jh/AShkYug+Mn9ceaWuENCA/V1JKV/JNlFhMQFJAi3iCuCXYVJDBN1RWKCNPnq+t8Ks+cgw6Hl6rDacba/WGYnVKgaiOGoRdCwELyA1pTqlShcWgPqEomuqycqprsEhoghTj4O6mrM95rX6Z6zA9ADj4lSPwEMuWMFeswI5sBR7QcyX4je39hGLwwdPfkE99cEbKYTNUikiau2v2bkhVwt8cpRiL0QQ8S7DJWhnn2SxpB4ILp5cpaYZH3om1S6N3US4kG2UyXgpmv9Yv2Klhfd9Um9Ab5QeLjyg4s5RAcHaoM7Ilvpe8klKbPImgXmNQmwyo93WkqFZ5lPTHa6DeyX5/tjrXOrf1IMNm1rYYI9U/HWAoNuF0Gw8n/Xz0vH3dmYV5yHLQDcrVL2EJihdUv2YXV1/u81RUpZMrr4xB9XOotvvvxQrsLFFduvtahlIM2ga0QtzPPFe4DNNNhtsEt88AGDvBBVUbPLcA5kjmXI7zVGdQ/E5xe6ESGSxBTVu4Rnm6MFYH+xXGar++MqBE/fqK0N1uByQYpZBWEKxUwRZjb0sY48GmPwBG9bAfYcwM2osQyNAeJAQXODJbGnZS7FwJRs/2KClZa7FFd1Marebqj9M/erzwXdvfFgaYwOoBUiMCGvaXdia1CChGNQqlCewf1SUESvkk2onk2w+qPo7uQ8AfgLY4aFQKqQ7VVfTiuQ43YdZTG/LL3UjEfs6lKpx7oZ9zPuP6uJRZ6z36uIwzYxzFMHrefUyW4fYaWC6TZ959VSo8VVLaAHsMf/ZFAgEEPaW4GCjGJ1uibcsE1CWcx+sA4Lg4eBATQ4bfjFfLt5eOwFPEd1+Lio2Ml1xqAZ4gFniWox5ZrT6qTRYgqXgzulf2lg5BbYKt5q0FteHbz2MdUO+k4mKsdv/9nt96kKF4tsa43QAjfQkZPe8emRssOPUgQEgKhKVvVkwgfbt+n3OPczF9i51RX+mTKIV8fNEpvaO/aXtxCjuYlmPVf/Jgp3L3pASgu60BQa6gm4cNwwyYtPrhA0xwRU7ReshXgmBZ2F3RR2a+PqlFNsKQ4dIrpRLSFYr26e1C41GCnHwma2VHQs8NFHamn2SStgdUKaQmLqoXpgFe+FhpXElJB6UKtE+JAuTMWIgiCmlGShmSrZepcwQGPtzvtklx30HQQqZeAvXEsX2t0olAYuyJ0x++as7YaA9D5u+DjRLdeGlwu1aqg40FbUj8MGJdK7HNOoI1AIlUuxglOkMvHMYmoTmpD+LQCUiDKM3ifjG0XYmhH4V8zmv101z/GFAA7xEjgl7pfFGuXI7ApbVSupsRIdR52e0hRjHHDE8tQH05Lbcm5pUhK7eJr8Y27DWQstHuIgDjaD9+Eyw7hqi/Xi/AsO5Z8oCRS0kz4HFxNVKZYQ+x2cNQ8w4byVNqQrXJsFKbHJZu7y3psoblVGKf3EA8D0pGCpnWnukK2Zq7rgwmj4Glx+bK8770Neb1Axzr9cDKPyPpZfU8K9SLpqu0M+rLleeTXAWJZ7S5Aw7IAKOwD5jCj/fa4JhyxWQ0zcMdzWCgNAik6gL+2LQ7IAPCD53RKgkEIgizS4lGIRPjTfhg/FhuGxmmbAxI0PwTJzH9DvekxmO64dLWgCshqhEopWFE0AgYaxCBadz3ZGtdGWGiDouoJUei5Id1hzBhchM3t+RDn3MJFKqgalLGfPogctRPzxS+prnsMdy3Kxpp9fOVr8BYuIKkYI62KzQiZZg8SrocF1d3PebYUCAXBThvzPhb5IeBz8p8ZbW0hXaLY11ydzEmfSNzcqF/Un5xY1yuD89iLsKCAj8nLmoIKgJQh1RBdVoXQqReSBl9ABfv35hSv48agJAHPSk7DO13uNPGw66Ru12INsqrnhMAGiPy86XdsqCMVHXGuPGebx/I0IEBh8sRq+TK81z6GvP6AY51erguZZTNuA8Fs95nV6C+suTZl4x+88TOTFyd9hxslxmsDiim74BhJ20enDDdpVAz7G1pUF4dlBLQOJSun9xynWUoai9kYp3lcNmjNGUzUzvVMVCnkHnSMJQqnzmE2GbbQagO8vndpxj12iUJItqhFikD7SogZcmV2qC2YgwNuuFShZFPUqBl7W7krKoMMUfoJUPbED4DPmfHQJXGuat58+Ss1Fw0FAAFgn64RcPj5FYkKDMR7L+xtIgAdNPyXt+EnMdneGpRSSoOt9fI3saQAhmTs1ElsRibXZLhmQWAEaj3uCCiez12X3320XBeRrPmAWycApS6LMI75I1ol5yNQ9WawGIkg9luvA3WsD0gw+bfqSHgIH3syrNA+hrz+gGOFVCwz6kv7bpeVs+zQjfAUBM5zvN2VYX6l5nHpYy+8HgHJ66Y2+prJFKNEOAYDiM96ittro5rwIxlxTMyq2tloYZI6cJWJAILfpxExs7PZiR6yRzpalbqGHfgMXd7lLDws9WJz5mgS3/OlLqYZCiwUQpUQhIRghtvH2ImfedMnwxCNdIL1QgNkJuq/fK5J1vk8Q4AjKZKqEDgzg5Uzngyc7D/moUXyTT2KJkA2JiCNHB8JiLzWOA8BkDyIKtLNkrTrb6f9hkT8TIZTyIuC/gg3VgLnbYeZLgZfnpMyOh5jjR9zLx+gONCAAxuUsYUgRwPFvhShuMoKub+Mao5rU1KMJT0XDunbt65/8hguJI1aXMoQFsPxrIwyVDgYaRAFbxK+Dnz0YgMAWBUIb5FFyQWR/ZUy6NtUKEg1kcAMUP0RLVIjZc2GZmAmwbbjPhJNSd3SDVp6yhAiUZeIt51dinzDVhnJeu7DQNL82tXnhWmrzGvH+C4EACjFIDC+yiCurwAcNEJJ2G4vc6eRezVl0HwsRTYYD+YHhAVSaqz5r+hgKGAocDmUyAEgPFkZ63MRxKIDVIuT3TUwgC0Ehsj0oPKXsDl2Q3aifFj0sePAtsDMgga0rjBlSeN09eY1w9wXCiAEfiMSOffwhBJQ9QVByRZ/axI758CgNxBIAm07QYY7v6gSyYZChgKbC4FUoHRchvibm4PdmbtDl3yMWh2yhZqJGUw4Hzu0C55sqtO6hBttwI2Gg9i4qaH/OSTSOcUHXEPQJHFPV74Wt4fpsqnqR1fhn5+jBtFepAuq9FwG0CGQgk2AbcBYPBdQhQ26fjLTIBh98jyt0uy/c9Frn35XoDBMg/hy2STxnwZCmw5BVSMBXgG3blzR86cOSMjIyNb3oed3CDpc/HiRZmfh+s2I7BlSSwTg8cYaXj69Gm5fft2llIbO3VtY7dv692kT29vrywu0kg+Nw1JO9Kw7sZN+ei9WzIzcBOu/9jg7iHkC9wbabD4tpypHpWhuoBcunQJ3omMU5QpGNhikIHGEzB4cKQR6b7YmfQx3jlXR9P38HVU5bTCelk9z4L6O8NbuEtr+QmxsEPlqinUg0vYhr0YE1ocN2lN3dOvVSsxFwwFDAUKQYGysjKZm5uTN998U86dO3fPJFaINh7EOrh65IQ+MDAgXV1d2Ngw+3TOMqWlpTI9PS2vv/66BIPY7CxjnnwQR1+YPpOGBBa3bt2S/fv3I05HdmkM6RUIYNPJ2Vl57bXXpMwfkOHpBWnkvkluaXdhurbzawFfTNz0yVtzF+Qsgv/xPTx8+DCcDDLt1LK/lZs6PIgSuEupzrjZnn7s/gE4oCRdTiusl9Xz2QAG7yfi9AFA5EhWMYI+KRACkBHLUdBcMhQwFNhUClAU29PTI+XljOGSWFUku6md2OGVU0rR2NgoTU3Y8TlLohj76aeflqqqKkPDLPThqSgiIre0NEs4nH1zTQK4kydPZtCQAEUJMB5CKUaajOC5DsYiDdva2qS2FpoCLWF31wzOrF3anGyy/6/AuN8SmYc3h0ouwOHuTiEBBoGHHwo0/6+Ktfcrdvv3fiXjCBV97jcA02AASk8TJ1HVcuBfxKo65pwx34YChgKGAoYChgKGAqtQYOstqYJPal1xAQztisrmCzAyxSD3qkhUZbb0YxHf02ckGc2h2534MSQe45kAg21wn5PilRgM7u6aY0MBQwFDAUMBQwFDgRUKbD3IqPglxKWoSIUBA8/OSLoUQwcYqpBWWC9H5p++hIy6L6NWHNgF+EXDnqJpGHa+JMnYlLugJGfex57o/5SyxXCusj26ZBXXiJS2OmfNt6GAoYChgKGAoYChQA4KbLm6hH1JjnwTMSm+JnLXUZnwpA0EWMANMPRren4tgKGqtOt15xmIywPAUP+bMATtRpvYAXD6pyIjr6AvCyu2GE575cBjFV+AmuVv2EOTDAUMBQwFDAUMBQwF1qDA9oCMZQS+6vsLMPafi8xpQIOd3TSAwcpdgMNLoIEPo3zS3gIRMiWCvNMlB2CwnIUdPx//llhlu1iRSYYChgKGAoYChgKGAmtQYOvVJeiQVQQXl9a/BqB4BFIEcnc7bSXAYJPY1AfbzqVUIyq/CsBgf7tfMgDDeU7m21DAUMBQwFDAUCAPCmwLyGC/LC/sG/b8I9xJn03tGaLC0NqSBhZwpAju/LpUJC4JBuu8B9DwpJ2ctumJ4kU8ja5/EKvmWeeq+TYUMBQwFDAUMBQwFMiDAtuiLsnsV1KS46/CFuLrUFeMQnUBQED1hZMchq+Occ3GCyqjFXMupwvo5XhRHdsncwEMFiwFuGAQrqpnRNq+LFagXVVv/hkKGAoYChgKGAoYCuRPgR0AMlKdTcYmRCa+h8/3YROBfUOUrYStynAAgo0RVgcYrAuF9HL2qfTJbAADJhfCQG/FyCwBYFQdxcZpvy1W7bO82yRDAUMBQwFDAUMBQ4F1UGDHgAyn78n4PIxBsRvq7Fvw9ngPUo1BqFPA+AkOGFqMEgZ+U8KhAAPOI5tKPK/lmVXH+EcgwcRvx8jTwnkaecYQ+yKwR6T6pEjNJ8Uqh62ISYYChgKGAoYgBScCAAAA6UlEQVQChgKGAhuiwI4DGfpokgkAjqU+uLpegoHmZeT7AToQRCsyA3CwCLAAhEDpA4GDAyKAG9JIgwBCgRGc5I6qgh1XveWwA4E9iA8heMs78dmPCKDdMOpsxnWnEmRNMhQwFDAUMBQwFDAU2BAFdjTIyDayJMFFYhagAUAjju9lAJEE4lokEOciiRjgSVu8wS14BV4h2IdEigIAF0GAEgYBq4DRKYCGEmdka8GcMxQwFDAUMBQwFDAUKAQFHjiQUYhBmzoMBQwFDAUMBQwFDAU2nwIwdjDJUMBQwFDAUMBQwFDAUKDwFPh/KpI6vTxhunkAAAAASUVORK5CYII="
}
},
"cell_type": "markdown",
"metadata": {},
"source": [
"# *Introducción a Pandas en los cuadernos de Jupyter*\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### La estructura de Datos `Serie`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`Arreglo` unidimensional con etiquetas en los ejes (incluidas series de tiempo). Los parámetros de una `Serie` son: `data` (matriz, diccionario o escalar), `index` (arreglo de índices), `dtype` (`numpy.dtype` o `None`) y `copy` (booleano o por defecto `False`)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Importamos la biblioteca `Pandas`"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"pd.Series?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos convertir una `lista` en una `serie` y pandas asigna de manera inmediata una lista de índices que empieza en 0."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 Tigre\n",
"1 Oso\n",
"2 Camello\n",
"dtype: object"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"animales = ['Tigre', 'Oso', 'Camello']\n",
"pd.Series(animales)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 1\n",
"1 2\n",
"2 3\n",
"dtype: int64"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"numeros = [1, 2, 3]\n",
"pd.Series(numeros)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 Tigre\n",
"1 Oso\n",
"2 None\n",
"dtype: object"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"animales = ['Tigre', 'Oso', None]\n",
"pd.Series(animales)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Es importante saber como `NumPy` y `Pandas` manejan los datos faltantes. En Python tenemos el tipo `None` para indicar un dato faltante. Si tenemos una lista de números, `Pandas` automáticamente convierte este valor `None` en un valor designado como `NaN`, que significa `Not a Number`."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 1.0\n",
"1 2.0\n",
"2 NaN\n",
"dtype: float64"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"numeros = [1, 2, None]\n",
"pd.Series(numeros)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Importamos la biblioteca `NumPy`. También es importante saber que `NaN` no es `None`. Cuando hacemos un test para saber si `NaN` es `NaN` tambien obtendremos `False`."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"np.nan == None"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.nan == np.nan"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Se necesita la función especial `isnan` de `NumPy` para chequear la presencia de un `no número` en nuestros datos."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n",
"True\n",
"True\n"
]
}
],
"source": [
"print(np.isnan(np.nan))\n",
"print(None is None)\n",
"print(np.nan is np.nan)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"¿Cómo creamos una `serie` en `Pandas`? Podemos utilizar una estructura de datos `diccionario` con sus `claves` y convertirlo en una `serie`, donde los índices de la `serie` son las claves del diccionario."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Béisbol Cuba\n",
"Capoeira Brasil\n",
"Corrida de Toros España\n",
"Golf Escocia\n",
"Pelota Vasca País Vasco\n",
"Rayuela Chile\n",
"Rugby Gales\n",
"Sumo Japón\n",
"dtype: object"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"deportes = {'Capoeira': 'Brasil',\n",
" 'Rayuela': 'Chile',\n",
" 'Pelota Vasca': 'País Vasco',\n",
" 'Béisbol': 'Cuba',\n",
" 'Rugby': 'Gales',\n",
" 'Golf': 'Escocia',\n",
" 'Corrida de Toros': 'España',\n",
" 'Sumo': 'Japón'}\n",
"s = pd.Series(deportes)\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Luego, podemos chequear la lista de índices con el atributo `.index`"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Index(['Béisbol', 'Capoeira', 'Corrida de Toros', 'Golf', 'Pelota Vasca',\n",
" 'Rayuela', 'Rugby', 'Sumo'],\n",
" dtype='object')"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s.index"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"En este otro ejemplo, pasamos directamente una lista con su conjunto de índices para crear la `Serie`."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"India Tigre\n",
"America Oso\n",
"Africa Camello\n",
"dtype: object"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s = pd.Series(['Tigre', 'Oso', 'Camello'], index=['India', 'America', 'Africa'])\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Aquí tenemos un ejemplo de un elemento nuevo en la lista de índices que no tiene un valor asignado, no existe un país asociado al índice `Natación` y `Pandas` representa este valor faltante con `NaN`. "
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Capoeira Brasil\n",
"Sumo Japón\n",
"Pelota Vasca País Vasco\n",
"Natación NaN\n",
"dtype: object"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"deportes = {'Capoeira': 'Brasil',\n",
" 'Rayuela': 'Chile',\n",
" 'Pelota Vasca': 'País Vasco',\n",
" 'Béisbol': 'Cuba',\n",
" 'Rugby': 'Gales',\n",
" 'Golf': 'Escocia',\n",
" 'Corrida de Toros': 'España',\n",
" 'Sumo': 'Japón'}\n",
"s = pd.Series(deportes, index=['Capoeira', 'Sumo', 'Pelota Vasca', 'Natación'])\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Búsqueda en una `Serie`"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Béisbol Cuba\n",
"Capoeira Brasil\n",
"Corrida de Toros España\n",
"Golf Escocia\n",
"Pelota Vasca País Vasco\n",
"Rayuela Chile\n",
"Rugby Gales\n",
"Sumo Japón\n",
"dtype: object"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"deportes = {'Capoeira': 'Brasil',\n",
" 'Rayuela': 'Chile',\n",
" 'Pelota Vasca': 'País Vasco',\n",
" 'Béisbol': 'Cuba',\n",
" 'Rugby': 'Gales',\n",
" 'Golf': 'Escocia',\n",
" 'Corrida de Toros': 'España',\n",
" 'Sumo': 'Japón'}\n",
"s = pd.Series(deportes)\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos hacer búsquedas en las `series` por posición de índices o por etiqueta de índices. Si queremos hacer búsqueda por ubicación numérica (empezando desde 0) utilizamos el atributo `iloc`. Si por otra parte, hacemos búqueda por etiqueta de índice entonces usamos el atributo `loc`."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'País Vasco'"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s.iloc[4]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'País Vasco'"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s.loc['Pelota Vasca']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"`Pandas` trata de que el código sea más legible. Si le pasamos por parámetro un valor numérico a la `Serie` esta se comportará como si la búsqueda se hace con el atributo `iloc`, si en cambio le pasamos un objeto, hará la búsqueda por etiqueta como con el atributo `loc`."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'País Vasco'"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s[4]"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'País Vasco'"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s['Pelota Vasca']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"¿Qué pasa cuando tenemos una lista de índices que son enteros?"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"99 Brasil\n",
"100 Chile\n",
"101 País Vasco\n",
"102 Cuba\n",
"103 Gales\n",
"104 Escocia\n",
"105 España\n",
"106 Japón\n",
"dtype: object"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"deportes = {99: 'Brasil',\n",
" 100: 'Chile',\n",
" 101: 'País Vasco',\n",
" 102: 'Cuba',\n",
" 103: 'Gales',\n",
" 104: 'Escocia',\n",
" 105: 'España',\n",
" 106: 'Japón'}\n",
"s = pd.Series(deportes)\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Cuando tenemos un caso como este es más seguro utilizar los atributos `iloc` o `loc` según sea el caso. "
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "KeyError",
"evalue": "0",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m#Esta instrucción no llamará s.iloc[0] como esperaríamos y va a generar un error\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m/anaconda3/lib/python3.6/site-packages/pandas/core/series.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 621\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_apply_if_callable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 623\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_value\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 624\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 625\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mis_scalar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/anaconda3/lib/python3.6/site-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36mget_value\u001b[0;34m(self, series, key)\u001b[0m\n\u001b[1;32m 2558\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2559\u001b[0m return self._engine.get_value(s, k,\n\u001b[0;32m-> 2560\u001b[0;31m tz=getattr(series.dtype, 'tz', None))\n\u001b[0m\u001b[1;32m 2561\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2562\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minferred_type\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'integer'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'boolean'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32mpandas/_libs/index.pyx\u001b[0m in \u001b[0;36mpandas._libs.index.IndexEngine.get_value\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mpandas/_libs/index.pyx\u001b[0m in \u001b[0;36mpandas._libs.index.IndexEngine.get_value\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mpandas/_libs/index.pyx\u001b[0m in \u001b[0;36mpandas._libs.index.IndexEngine.get_loc\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mpandas/_libs/hashtable_class_helper.pxi\u001b[0m in \u001b[0;36mpandas._libs.hashtable.Int64HashTable.get_item\u001b[0;34m()\u001b[0m\n",
"\u001b[0;32mpandas/_libs/hashtable_class_helper.pxi\u001b[0m in \u001b[0;36mpandas._libs.hashtable.Int64HashTable.get_item\u001b[0;34m()\u001b[0m\n",
"\u001b[0;31mKeyError\u001b[0m: 0"
]
}
],
"source": [
"s[0] #Esta instrucción no llamará s.iloc[0] como esperaríamos y va a generar un error"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"s.iloc[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"s.loc[99]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Ya que sabemos hacer búsquedas en las `Series`, ahora vamos a trabajar con los datos (encontrar valores, resumir los datos o transformarlos)."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 105.0\n",
"1 223.0\n",
"2 5.0\n",
"3 102.0\n",
"4 27.0\n",
"5 -126.0\n",
"dtype: float64"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s = pd.Series([105.00, 223.00, 5, 102.00, 27, -126])\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Una forma de trabajar es iterar sobre un conjunto de datos e invocar una operación de interés"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"336.0\n"
]
}
],
"source": [
"total = 0\n",
"for elemento in s:\n",
" total+=elemento\n",
"print(total)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Con `NumPy` podemos tener acceso a las funciones universales binarias o unarias (vectorizadas, cálculos más rápidos). En este ejemplo, `np.sum` hará la suma de todos los elementos en la `serie`."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"336.0\n"
]
}
],
"source": [
"import numpy as np\n",
"\n",
"total = np.sum(s)\n",
"print(total)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"También podemos generar una `serie` grande de números aleatorios y con el método `.head()` podemos desplegar un encabezado con los 5 primeros elementos de la `serie` y con `len` chequear el tamaño de la misma."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 42\n",
"1 872\n",
"2 956\n",
"3 330\n",
"4 9\n",
"dtype: int64\n",
"10000\n"
]
}
],
"source": [
"s = pd.Series(np.random.randint(0,1000,10000))\n",
"print(s.head())\n",
"print(len(s))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Los cuadernos de `Jupyter` tienen **funciones mágicas** que pueden ser útiles. Una de ellas es `%%timeit` que nos servirá para ver cuál de los dos métodos para sumar elementos de una `serie` es más rápido.\n",
"Basta con tipear el símbolo `%` y la tecla `Tab` para obtener una lista de las **funciones mágicas** de `Jupyter`."
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"803 µs ± 52.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
"source": [
"%%timeit -n 100\n",
"sumar = 0\n",
"for elemento in s:\n",
" sumar+=elemento"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"128 µs ± 21.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
"source": [
"%%timeit -n 100\n",
"sumar = np.sum(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"`NumPy` y `Pandas` tienen el `broadcasting`, se puede aplicar una operación a cada valor de la `serie` y modificarla."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 44\n",
"1 874\n",
"2 958\n",
"3 332\n",
"4 11\n",
"dtype: int64"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s+=2 #Suma 2 a cada elemento de la serie usando broadcasting\n",
"s.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Una manera poco eficiente de hacer esto es iterar sobre cada elemento de la `serie` para hacer la suma. El método `.iteritems()` devuelve un iterador sobre los pares `(key, value)` (clave, valor) de un diccionario, en este caso de nuestra `serie` s."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:2: FutureWarning: set_value is deprecated and will be removed in a future release. Please use .at[] or .iat[] accessors instead\n",
" \n"
]
},
{
"data": {
"text/plain": [
"0 46\n",
"1 876\n",
"2 960\n",
"3 334\n",
"4 13\n",
"dtype: int64"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"for etiqueta, valor in s.iteritems():\n",
" s.set_value(etiqueta, valor+2)\n",
"s.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%timeit -n 10\n",
"s = pd.Series(np.random.randint(0,1000,10000))\n",
"for etiqueta, valor in s.iteritems():\n",
" s.loc[etiqueta]= valor+2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%timeit -n 10\n",
"s = pd.Series(np.random.randint(0,1000,10000))\n",
"s+=2\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos agregar elementos a una `serie` de la siguiente forma:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 1\n",
"1 2\n",
"2 3\n",
"Animal Oso\n",
"dtype: object"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"s = pd.Series([1, 2, 3])\n",
"s.loc['Animal'] = 'Oso'\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Este es un ejemplo de una `serie` donde los valores del conjunto de índices no son únicos. Esto hace que las tablas de datos funcionen diferente y es por ello que agregar nuevos elementos debe hacerse con el método `append`, que en primera instancia, no modificará la `serie` sino que devuelve una nueva `serie` con los elementos que se agregaron."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"deportes_originales = pd.Series({'Capoeira': 'Brasil',\n",
" 'Rayuela': 'Chile',\n",
" 'Pelota Vasca': 'País Vasco',\n",
" 'Béisbol': 'Cuba',\n",
" 'Rugby': 'Gales',\n",
" 'Golf': 'Escocia',\n",
" 'Corrida de Toros': 'España',\n",
" 'Sumo': 'Japón'})\n",
"paises_que_aman_el_beisbol = pd.Series(['Venezuela',\n",
" 'USA',\n",
" 'Cuba',\n",
" 'Puerto Rico',\n",
" 'Dominicana'], \n",
" index=['Béisbol',\n",
" 'Béisbol',\n",
" 'Béisbol',\n",
" 'Béisbol',\n",
" 'Béisbol'])\n",
"todos_los_paises = deportes_originales.append(paises_que_aman_el_beisbol)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Béisbol Cuba\n",
"Capoeira Brasil\n",
"Corrida de Toros España\n",
"Golf Escocia\n",
"Pelota Vasca País Vasco\n",
"Rayuela Chile\n",
"Rugby Gales\n",
"Sumo Japón\n",
"dtype: object"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"deportes_originales"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Béisbol Venezuela\n",
"Béisbol USA\n",
"Béisbol Cuba\n",
"Béisbol Puerto Rico\n",
"Béisbol Dominicana\n",
"dtype: object"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"paises_que_aman_el_beisbol"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Béisbol Cuba\n",
"Capoeira Brasil\n",
"Corrida de Toros España\n",
"Golf Escocia\n",
"Pelota Vasca País Vasco\n",
"Rayuela Chile\n",
"Rugby Gales\n",
"Sumo Japón\n",
"Béisbol Venezuela\n",
"Béisbol USA\n",
"Béisbol Cuba\n",
"Béisbol Puerto Rico\n",
"Béisbol Dominicana\n",
"dtype: object"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"todos_los_paises"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Béisbol Cuba\n",
"Béisbol Venezuela\n",
"Béisbol USA\n",
"Béisbol Cuba\n",
"Béisbol Puerto Rico\n",
"Béisbol Dominicana\n",
"dtype: object"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"todos_los_paises.loc['Béisbol']"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"### La estructura de datos `DataFrame`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"El `DataFrame` o Tabla de Datos es el corazón de la biblioteca `Pandas`. Es el objeto primario para el análisis de datos. Es una especie de **arreglo bidimensional** con etiquetas en los ejes. En este ejemplo, crearemos tres diccionarios que serán luego las filas de nuestro `DataFrame`."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Artículo comprado | \n",
" Costo | \n",
" Nombre | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 1 | \n",
" Libro | \n",
" 1200 | \n",
" Adelis | \n",
"
\n",
" \n",
" Tienda 1 | \n",
" Raspberry pi 3 | \n",
" 15000 | \n",
" Miguel | \n",
"
\n",
" \n",
" Tienda 2 | \n",
" Balón | \n",
" 5000 | \n",
" Jaime | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Artículo comprado Costo Nombre\n",
"Tienda 1 Libro 1200 Adelis\n",
"Tienda 1 Raspberry pi 3 15000 Miguel\n",
"Tienda 2 Balón 5000 Jaime"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"compra_1 = pd.Series({'Nombre': 'Adelis',\n",
" 'Artículo comprado': 'Libro',\n",
" 'Costo': 1200})\n",
"compra_2 = pd.Series({'Nombre': 'Miguel',\n",
" 'Artículo comprado': 'Raspberry pi 3',\n",
" 'Costo': 15000})\n",
"compra_3 = pd.Series({'Nombre': 'Jaime',\n",
" 'Artículo comprado': 'Balón',\n",
" 'Costo': 5000})\n",
"df = pd.DataFrame([compra_1, compra_2, compra_3], index=['Tienda 1', 'Tienda 1', 'Tienda 2'])\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"En un `DataFrame` también se puede extraer información usando los atributos `loc` y `iloc`."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Artículo comprado Balón\n",
"Costo 5000\n",
"Nombre Jaime\n",
"Name: Tienda 2, dtype: object"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.loc['Tienda 2']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"También podemos chequear el tipo de dato usando la función `type` de Python."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"pandas.core.series.Series"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(df.loc['Tienda 2'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"En los `DataFrame` también se pueden tener listas de índices no únicos. En el ejemplo, hay dos índices con el mismo nombre `Tienda 1`."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Artículo comprado | \n",
" Costo | \n",
" Nombre | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 1 | \n",
" Libro | \n",
" 1200 | \n",
" Adelis | \n",
"
\n",
" \n",
" Tienda 1 | \n",
" Raspberry pi 3 | \n",
" 15000 | \n",
" Miguel | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Artículo comprado Costo Nombre\n",
"Tienda 1 Libro 1200 Adelis\n",
"Tienda 1 Raspberry pi 3 15000 Miguel"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.loc['Tienda 1']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"También podemos seleccionar columnas agregando un parámetro extra al atributo `loc`."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"Tienda 1 1200\n",
"Tienda 1 15000\n",
"Name: Costo, dtype: int64"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.loc['Tienda 1', 'Costo']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Usar el atributo `.T` para obtener la transpuesta del `DataFrame` o Tabla de Datos."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Tienda 1 | \n",
" Tienda 1 | \n",
" Tienda 2 | \n",
"
\n",
" \n",
" \n",
" \n",
" Artículo comprado | \n",
" Libro | \n",
" Raspberry pi 3 | \n",
" Balón | \n",
"
\n",
" \n",
" Costo | \n",
" 1200 | \n",
" 15000 | \n",
" 5000 | \n",
"
\n",
" \n",
" Nombre | \n",
" Adelis | \n",
" Miguel | \n",
" Jaime | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Tienda 1 Tienda 1 Tienda 2\n",
"Artículo comprado Libro Raspberry pi 3 Balón\n",
"Costo 1200 15000 5000\n",
"Nombre Adelis Miguel Jaime"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Usando `.T.loc[]` se puede seleccionar una columna usando como parámetro la etiqueta de su nombre. "
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Tienda 1 1200\n",
"Tienda 1 15000\n",
"Tienda 2 5000\n",
"Name: Costo, dtype: object"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.T.loc['Costo']"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Tienda 1 1200\n",
"Tienda 1 15000\n",
"Tienda 2 5000\n",
"Name: Costo, dtype: int64"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df['Costo']"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Tienda 1 1200\n",
"Tienda 1 15000\n",
"Name: Costo, dtype: int64"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.loc['Tienda 1']['Costo']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"`loc` también tiene soporte para rebanar o seleccionar del `DataFrame` con la notación `[]`"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Nombre | \n",
" Costo | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 1 | \n",
" Adelis | \n",
" 1200 | \n",
"
\n",
" \n",
" Tienda 1 | \n",
" Miguel | \n",
" 15000 | \n",
"
\n",
" \n",
" Tienda 2 | \n",
" Jaime | \n",
" 5000 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Nombre Costo\n",
"Tienda 1 Adelis 1200\n",
"Tienda 1 Miguel 15000\n",
"Tienda 2 Jaime 5000"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.loc[:,['Nombre', 'Costo']]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"También podemos eliminar datos del `DataFrame` con la función `drop()`. Esta función toma un solo parámetro que es el índice del conjunto de datos que deseamos eliminar. "
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Artículo comprado | \n",
" Costo | \n",
" Nombre | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 2 | \n",
" Balón | \n",
" 5000 | \n",
" Jaime | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Artículo comprado Costo Nombre\n",
"Tienda 2 Balón 5000 Jaime"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.drop('Tienda 1')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos ver que nuestro `DataFrame` original sigue intacto. Solo hicimos una **extracción** de información."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Artículo comprado | \n",
" Costo | \n",
" Nombre | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 1 | \n",
" Libro | \n",
" 1200 | \n",
" Adelis | \n",
"
\n",
" \n",
" Tienda 1 | \n",
" Raspberry pi 3 | \n",
" 15000 | \n",
" Miguel | \n",
"
\n",
" \n",
" Tienda 2 | \n",
" Balón | \n",
" 5000 | \n",
" Jaime | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Artículo comprado Costo Nombre\n",
"Tienda 1 Libro 1200 Adelis\n",
"Tienda 1 Raspberry pi 3 15000 Miguel\n",
"Tienda 2 Balón 5000 Jaime"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"También podemos hacer una copia del `DataFrame` con la función `copy()` para guardar la extracción de información. "
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Artículo comprado | \n",
" Costo | \n",
" Nombre | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 2 | \n",
" Balón | \n",
" 5000 | \n",
" Jaime | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Artículo comprado Costo Nombre\n",
"Tienda 2 Balón 5000 Jaime"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"copiar_df = df.copy()\n",
"copiar_df = copiar_df.drop('Tienda 1')\n",
"copiar_df"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"copiar_df.drop?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos eliminar una columna de manera sencilla, usando simplemente la palabra clave `del` y el índice o nombre de la comuna. "
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Artículo comprado | \n",
" Nombre | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 2 | \n",
" Balón | \n",
" Jaime | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Artículo comprado Nombre\n",
"Tienda 2 Balón Jaime"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"del copiar_df['Costo']\n",
"copiar_df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Finalmente, es muy sencillo agregar una columna al `DataFrame`."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Artículo comprado | \n",
" Costo | \n",
" Nombre | \n",
" Ubicación | \n",
"
\n",
" \n",
" \n",
" \n",
" Tienda 1 | \n",
" Libro | \n",
" 1200 | \n",
" Adelis | \n",
" Venezuela | \n",
"
\n",
" \n",
" Tienda 1 | \n",
" Raspberry pi 3 | \n",
" 15000 | \n",
" Miguel | \n",
" Chile | \n",
"
\n",
" \n",
" Tienda 2 | \n",
" Balón | \n",
" 5000 | \n",
" Jaime | \n",
" Argentina | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Artículo comprado Costo Nombre Ubicación\n",
"Tienda 1 Libro 1200 Adelis Venezuela\n",
"Tienda 1 Raspberry pi 3 15000 Miguel Chile\n",
"Tienda 2 Balón 5000 Jaime Argentina"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df['Ubicación'] = ['Venezuela', 'Chile', 'Argentina']\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"### Lectura de un `DataFrame`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Usemos `!cat` para leer un archivo de formato `CSV`. Nota: `!cat` funciona para **Linux** y **Mac** pero puede no funcionar para **Windows** :("
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15\r\n",
",№ Summer,01 !,02 !,03 !,Total,№ Winter,01 !,02 !,03 !,Total,№ Games,01 !,02 !,03 !,Combined total\r\n",
"Afghanistan (AFG),13,0,0,2,2,0,0,0,0,0,13,0,0,2,2\r\n",
"Algeria (ALG),12,5,2,8,15,3,0,0,0,0,15,5,2,8,15\r\n",
"Argentina (ARG),23,18,24,28,70,18,0,0,0,0,41,18,24,28,70\r\n",
"Armenia (ARM),5,1,2,9,12,6,0,0,0,0,11,1,2,9,12\r\n",
"Australasia (ANZ) [ANZ],2,3,4,5,12,0,0,0,0,0,2,3,4,5,12\r\n",
"Australia (AUS) [AUS] [Z],25,139,152,177,468,18,5,3,4,12,43,144,155,181,480\r\n",
"Austria (AUT),26,18,33,35,86,22,59,78,81,218,48,77,111,116,304\r\n",
"Azerbaijan (AZE),5,6,5,15,26,5,0,0,0,0,10,6,5,15,26\r\n",
"Bahamas (BAH),15,5,2,5,12,0,0,0,0,0,15,5,2,5,12\r\n",
"Bahrain (BRN),8,0,0,1,1,0,0,0,0,0,8,0,0,1,1\r\n",
"Barbados (BAR) [BAR],11,0,0,1,1,0,0,0,0,0,11,0,0,1,1\r\n",
"Belarus (BLR),5,12,24,39,75,6,6,4,5,15,11,18,28,44,90\r\n",
"Belgium (BEL),25,37,52,53,142,20,1,1,3,5,45,38,53,56,147\r\n",
"Bermuda (BER),17,0,0,1,1,7,0,0,0,0,24,0,0,1,1\r\n",
"Bohemia (BOH) [BOH] [Z],3,0,1,3,4,0,0,0,0,0,3,0,1,3,4\r\n",
"Botswana (BOT),9,0,1,0,1,0,0,0,0,0,9,0,1,0,1\r\n",
"Brazil (BRA),21,23,30,55,108,7,0,0,0,0,28,23,30,55,108\r\n",
"British West Indies (BWI) [BWI],1,0,0,2,2,0,0,0,0,0,1,0,0,2,2\r\n",
"Bulgaria (BUL) [H],19,51,85,78,214,19,1,2,3,6,38,52,87,81,220\r\n",
"Burundi (BDI),5,1,0,0,1,0,0,0,0,0,5,1,0,0,1\r\n",
"Cameroon (CMR),13,3,1,1,5,1,0,0,0,0,14,3,1,1,5\r\n",
"Canada (CAN),25,59,99,121,279,22,62,56,52,170,47,121,155,173,449\r\n",
"Chile (CHI) [I],22,2,7,4,13,16,0,0,0,0,38,2,7,4,13\r\n",
"China (CHN) [CHN],9,201,146,126,473,10,12,22,19,53,19,213,168,145,526\r\n",
"Colombia (COL),18,2,6,11,19,1,0,0,0,0,19,2,6,11,19\r\n",
"Costa Rica (CRC),14,1,1,2,4,6,0,0,0,0,20,1,1,2,4\r\n",
"Ivory Coast (CIV) [CIV],12,0,1,0,1,0,0,0,0,0,12,0,1,0,1\r\n",
"Croatia (CRO),6,6,7,10,23,7,4,6,1,11,13,10,13,11,34\r\n",
"Cuba (CUB) [Z],19,72,67,70,209,0,0,0,0,0,19,72,67,70,209\r\n",
"Cyprus (CYP),9,0,1,0,1,10,0,0,0,0,19,0,1,0,1\r\n",
"Czech Republic (CZE) [CZE],5,14,15,15,44,6,7,9,8,24,11,21,24,23,68\r\n",
"Czechoslovakia (TCH) [TCH],16,49,49,45,143,16,2,8,15,25,32,51,57,60,168\r\n",
"Denmark (DEN) [Z],26,43,68,68,179,13,0,1,0,1,39,43,69,68,180\r\n",
"Djibouti (DJI) [B],7,0,0,1,1,0,0,0,0,0,7,0,0,1,1\r\n",
"Dominican Republic (DOM),13,3,2,1,6,0,0,0,0,0,13,3,2,1,6\r\n",
"Ecuador (ECU),13,1,1,0,2,0,0,0,0,0,13,1,1,0,2\r\n",
"Egypt (EGY) [EGY] [Z],21,7,9,10,26,1,0,0,0,0,22,7,9,10,26\r\n",
"Eritrea (ERI),4,0,0,1,1,0,0,0,0,0,4,0,0,1,1\r\n",
"Estonia (EST),11,9,9,15,33,9,4,2,1,7,20,13,11,16,40\r\n",
"Ethiopia (ETH),12,21,7,17,45,2,0,0,0,0,14,21,7,17,45\r\n",
"Finland (FIN),24,101,84,117,302,22,42,62,57,161,46,143,146,174,463\r\n",
"France (FRA) [O] [P] [Z],27,202,223,246,671,22,31,31,47,109,49,233,254,293,780\r\n",
"Gabon (GAB),9,0,1,0,1,0,0,0,0,0,9,0,1,0,1\r\n",
"Georgia (GEO),5,6,5,14,25,6,0,0,0,0,11,6,5,14,25\r\n",
"Germany (GER) [GER] [Z],15,174,182,217,573,11,78,78,53,209,26,252,260,270,782\r\n",
"United Team of Germany (EUA) [EUA],3,28,54,36,118,3,8,6,5,19,6,36,60,41,137\r\n",
"East Germany (GDR) [GDR],5,153,129,127,409,6,39,36,35,110,11,192,165,162,519\r\n",
"West Germany (FRG) [FRG],5,56,67,81,204,6,11,15,13,39,11,67,82,94,243\r\n",
"Ghana (GHA) [GHA],13,0,1,3,4,1,0,0,0,0,14,0,1,3,4\r\n",
"Great Britain (GBR) [GBR] [Z],27,236,272,272,780,22,10,4,12,26,49,246,276,284,806\r\n",
"Greece (GRE) [Z],27,30,42,39,111,18,0,0,0,0,45,30,42,39,111\r\n",
"Grenada (GRN),8,1,0,0,1,0,0,0,0,0,8,1,0,0,1\r\n",
"Guatemala (GUA),13,0,1,0,1,1,0,0,0,0,14,0,1,0,1\r\n",
"Guyana (GUY) [GUY],16,0,0,1,1,0,0,0,0,0,16,0,0,1,1\r\n",
"Haiti (HAI) [J],14,0,1,1,2,0,0,0,0,0,14,0,1,1,2\r\n",
"Hong Kong (HKG) [HKG],15,1,1,1,3,4,0,0,0,0,19,1,1,1,3\r\n",
"Hungary (HUN),25,167,144,165,476,22,0,2,4,6,47,167,146,169,482\r\n",
"Iceland (ISL),19,0,2,2,4,17,0,0,0,0,36,0,2,2,4\r\n",
"India (IND) [F],23,9,6,11,26,9,0,0,0,0,32,9,6,11,26\r\n",
"Indonesia (INA),14,6,10,11,27,0,0,0,0,0,14,6,10,11,27\r\n",
"Iran (IRI) [K],15,15,20,25,60,10,0,0,0,0,25,15,20,25,60\r\n",
"Iraq (IRQ),13,0,0,1,1,0,0,0,0,0,13,0,0,1,1\r\n",
"Ireland (IRL),20,9,8,12,29,6,0,0,0,0,26,9,8,12,29\r\n",
"Israel (ISR),15,1,1,5,7,6,0,0,0,0,21,1,1,5,7\r\n",
"Italy (ITA) [M] [S],26,198,166,185,549,22,37,34,43,114,48,235,200,228,663\r\n",
"Jamaica (JAM) [JAM],16,17,30,20,67,7,0,0,0,0,23,17,30,20,67\r\n",
"Japan (JPN),21,130,126,142,398,20,10,17,18,45,41,140,143,160,443\r\n",
"Kazakhstan (KAZ),5,16,17,19,52,6,1,3,3,7,11,17,20,22,59\r\n",
"Kenya (KEN),13,25,32,29,86,3,0,0,0,0,16,25,32,29,86\r\n",
"North Korea (PRK),9,14,12,21,47,8,0,1,1,2,17,14,13,22,49\r\n",
"South Korea (KOR),16,81,82,80,243,17,26,17,10,53,33,107,99,90,296\r\n",
"Kuwait (KUW),12,0,0,2,2,0,0,0,0,0,12,0,0,2,2\r\n",
"Kyrgyzstan (KGZ),5,0,1,2,3,6,0,0,0,0,11,0,1,2,3\r\n",
"Latvia (LAT),10,3,11,5,19,10,0,4,3,7,20,3,15,8,26\r\n",
"Lebanon (LIB),16,0,2,2,4,16,0,0,0,0,32,0,2,2,4\r\n",
"Liechtenstein (LIE),16,0,0,0,0,18,2,2,5,9,34,2,2,5,9\r\n",
"Lithuania (LTU),8,6,5,10,21,8,0,0,0,0,16,6,5,10,21\r\n",
"Luxembourg (LUX) [O],22,1,1,0,2,8,0,2,0,2,30,1,3,0,4\r\n",
"Macedonia (MKD),5,0,0,1,1,5,0,0,0,0,10,0,0,1,1\r\n",
"Malaysia (MAS) [MAS],12,0,3,3,6,0,0,0,0,0,12,0,3,3,6\r\n",
"Mauritius (MRI),8,0,0,1,1,0,0,0,0,0,8,0,0,1,1\r\n",
"Mexico (MEX),22,13,21,28,62,8,0,0,0,0,30,13,21,28,62\r\n",
"Moldova (MDA),5,0,2,5,7,6,0,0,0,0,11,0,2,5,7\r\n",
"Mongolia (MGL),12,2,9,13,24,13,0,0,0,0,25,2,9,13,24\r\n",
"Montenegro (MNE),2,0,1,0,1,2,0,0,0,0,4,0,1,0,1\r\n",
"Morocco (MAR),13,6,5,11,22,6,0,0,0,0,19,6,5,11,22\r\n",
"Mozambique (MOZ),9,1,0,1,2,0,0,0,0,0,9,1,0,1,2\r\n",
"Namibia (NAM),6,0,4,0,4,0,0,0,0,0,6,0,4,0,4\r\n",
"Netherlands (NED) [Z],25,77,85,104,266,20,37,38,35,110,45,114,123,139,376\r\n",
"Netherlands Antilles (AHO) [AHO] [I],13,0,1,0,1,2,0,0,0,0,15,0,1,0,1\r\n",
"New Zealand (NZL) [NZL],22,42,18,39,99,15,0,1,0,1,37,42,19,39,100\r\n",
"Niger (NIG),11,0,0,1,1,0,0,0,0,0,11,0,0,1,1\r\n",
"Nigeria (NGR),15,3,8,12,23,0,0,0,0,0,15,3,8,12,23\r\n",
"Norway (NOR) [Q],24,56,49,43,148,22,118,111,100,329,46,174,160,143,477\r\n",
"Pakistan (PAK),16,3,3,4,10,2,0,0,0,0,18,3,3,4,10\r\n",
"Panama (PAN),16,1,0,2,3,0,0,0,0,0,16,1,0,2,3\r\n",
"Paraguay (PAR),11,0,1,0,1,1,0,0,0,0,12,0,1,0,1\r\n",
"Peru (PER) [L],17,1,3,0,4,2,0,0,0,0,19,1,3,0,4\r\n",
"Philippines (PHI),20,0,2,7,9,4,0,0,0,0,24,0,2,7,9\r\n",
"Poland (POL),20,64,82,125,271,22,6,7,7,20,42,70,89,132,291\r\n",
"Portugal (POR),23,4,8,11,23,7,0,0,0,0,30,4,8,11,23\r\n",
"Puerto Rico (PUR),17,0,2,6,8,6,0,0,0,0,23,0,2,6,8\r\n",
"Qatar (QAT),8,0,0,4,4,0,0,0,0,0,8,0,0,4,4\r\n",
"Romania (ROU),20,88,94,119,301,20,0,0,1,1,40,88,94,120,302\r\n",
"Russia (RUS) [RUS],5,132,121,142,395,6,49,40,35,124,11,181,161,177,519\r\n",
"Russian Empire (RU1) [RU1],3,1,4,3,8,0,0,0,0,0,3,1,4,3,8\r\n",
"Soviet Union (URS) [URS],9,395,319,296,1010,9,78,57,59,194,18,473,376,355,1204\r\n",
"Unified Team (EUN) [EUN],1,45,38,29,112,1,9,6,8,23,2,54,44,37,135\r\n",
"Saudi Arabia (KSA),10,0,1,2,3,0,0,0,0,0,10,0,1,2,3\r\n",
"Senegal (SEN),13,0,1,0,1,5,0,0,0,0,18,0,1,0,1\r\n",
"Serbia (SRB) [SRB],3,1,2,4,7,2,0,0,0,0,5,1,2,4,7\r\n",
"Serbia and Montenegro (SCG) [SCG],3,2,4,3,9,3,0,0,0,0,6,2,4,3,9\r\n",
"Singapore (SIN),15,0,2,2,4,0,0,0,0,0,15,0,2,2,4\r\n",
"Slovakia (SVK) [SVK],5,7,9,8,24,6,2,2,1,5,11,9,11,9,29\r\n",
"Slovenia (SLO),6,4,6,9,19,7,2,4,9,15,13,6,10,18,34\r\n",
"South Africa (RSA),18,23,26,27,76,6,0,0,0,0,24,23,26,27,76\r\n",
"Spain (ESP) [Z],22,37,59,35,131,19,1,0,1,2,41,38,59,36,133\r\n",
"Sri Lanka (SRI) [SRI],16,0,2,0,2,0,0,0,0,0,16,0,2,0,2\r\n",
"Sudan (SUD),11,0,1,0,1,0,0,0,0,0,11,0,1,0,1\r\n",
"Suriname (SUR) [E],11,1,0,1,2,0,0,0,0,0,11,1,0,1,2\r\n",
"Sweden (SWE) [Z],26,143,164,176,483,22,50,40,54,144,48,193,204,230,627\r\n",
"Switzerland (SUI),27,47,73,65,185,22,50,40,48,138,49,97,113,113,323\r\n",
"Syria (SYR),12,1,1,1,3,0,0,0,0,0,12,1,1,1,3\r\n",
"Chinese Taipei (TPE) [TPE] [TPE2],13,2,7,12,21,11,0,0,0,0,24,2,7,12,21\r\n",
"Tajikistan (TJK),5,0,1,2,3,4,0,0,0,0,9,0,1,2,3\r\n",
"Tanzania (TAN) [TAN],12,0,2,0,2,0,0,0,0,0,12,0,2,0,2\r\n",
"Thailand (THA),15,7,6,11,24,3,0,0,0,0,18,7,6,11,24\r\n",
"Togo (TOG),9,0,0,1,1,1,0,0,0,0,10,0,0,1,1\r\n",
"Tonga (TGA),8,0,1,0,1,1,0,0,0,0,9,0,1,0,1\r\n",
"Trinidad and Tobago (TRI) [TRI],16,2,5,11,18,3,0,0,0,0,19,2,5,11,18\r\n",
"Tunisia (TUN),13,3,3,4,10,0,0,0,0,0,13,3,3,4,10\r\n",
"Turkey (TUR),21,39,25,24,88,16,0,0,0,0,37,39,25,24,88\r\n",
"Uganda (UGA),14,2,3,2,7,0,0,0,0,0,14,2,3,2,7\r\n",
"Ukraine (UKR),5,33,27,55,115,6,2,1,4,7,11,35,28,59,122\r\n",
"United Arab Emirates (UAE),8,1,0,0,1,0,0,0,0,0,8,1,0,0,1\r\n",
"United States (USA) [P] [Q] [R] [Z],26,976,757,666,2399,22,96,102,84,282,48,1072,859,750,2681\r\n",
"Uruguay (URU),20,2,2,6,10,1,0,0,0,0,21,2,2,6,10\r\n",
"Uzbekistan (UZB),5,5,5,10,20,6,1,0,0,1,11,6,5,10,21\r\n",
"Venezuela (VEN),17,2,2,8,12,4,0,0,0,0,21,2,2,8,12\r\n",
"Vietnam (VIE),14,0,2,0,2,0,0,0,0,0,14,0,2,0,2\r\n",
"Virgin Islands (ISV),11,0,1,0,1,7,0,0,0,0,18,0,1,0,1\r\n",
"Yugoslavia (YUG) [YUG],16,26,29,28,83,14,0,3,1,4,30,26,32,29,87\r\n",
"Independent Olympic Participants (IOP) [IOP],1,0,1,2,3,0,0,0,0,0,1,0,1,2,3\r\n",
"Zambia (ZAM) [ZAM],12,0,1,1,2,0,0,0,0,0,12,0,1,1,2\r\n",
"Zimbabwe (ZIM) [ZIM],12,3,4,1,8,1,0,0,0,0,13,3,4,1,8\r\n",
"Mixed team (ZZX) [ZZX],3,8,5,4,17,0,0,0,0,0,3,8,5,4,17\r\n",
"Totals,27,4809,4775,5130,14714,22,959,958,948,2865,49,5768,5733,6078,17579\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"hola\r\n"
]
}
],
"source": [
"!cat olympics.csv"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Pero ... no hay que preocuparse mucho por eso! Podemos leer este archivo en formato `CSV` en un `DataFrame` usando la función `read_csv`. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
" 2 | \n",
" 3 | \n",
" 4 | \n",
" 5 | \n",
" 6 | \n",
" 7 | \n",
" 8 | \n",
" 9 | \n",
" 10 | \n",
" 11 | \n",
" 12 | \n",
" 13 | \n",
" 14 | \n",
" 15 | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" NaN | \n",
" № Summer | \n",
" 01 ! | \n",
" 02 ! | \n",
" 03 ! | \n",
" Total | \n",
" № Winter | \n",
" 01 ! | \n",
" 02 ! | \n",
" 03 ! | \n",
" Total | \n",
" № Games | \n",
" 01 ! | \n",
" 02 ! | \n",
" 03 ! | \n",
" Combined total | \n",
"
\n",
" \n",
" 1 | \n",
" Afghanistan (AFG) | \n",
" 13 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 2 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 13 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 2 | \n",
"
\n",
" \n",
" 2 | \n",
" Algeria (ALG) | \n",
" 12 | \n",
" 5 | \n",
" 2 | \n",
" 8 | \n",
" 15 | \n",
" 3 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 15 | \n",
" 5 | \n",
" 2 | \n",
" 8 | \n",
" 15 | \n",
"
\n",
" \n",
" 3 | \n",
" Argentina (ARG) | \n",
" 23 | \n",
" 18 | \n",
" 24 | \n",
" 28 | \n",
" 70 | \n",
" 18 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 41 | \n",
" 18 | \n",
" 24 | \n",
" 28 | \n",
" 70 | \n",
"
\n",
" \n",
" 4 | \n",
" Armenia (ARM) | \n",
" 5 | \n",
" 1 | \n",
" 2 | \n",
" 9 | \n",
" 12 | \n",
" 6 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 11 | \n",
" 1 | \n",
" 2 | \n",
" 9 | \n",
" 12 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1 2 3 4 5 6 7 8 \\\n",
"0 NaN № Summer 01 ! 02 ! 03 ! Total № Winter 01 ! 02 ! \n",
"1 Afghanistan (AFG) 13 0 0 2 2 0 0 0 \n",
"2 Algeria (ALG) 12 5 2 8 15 3 0 0 \n",
"3 Argentina (ARG) 23 18 24 28 70 18 0 0 \n",
"4 Armenia (ARM) 5 1 2 9 12 6 0 0 \n",
"\n",
" 9 10 11 12 13 14 15 \n",
"0 03 ! Total № Games 01 ! 02 ! 03 ! Combined total \n",
"1 0 0 13 0 0 2 2 \n",
"2 0 0 15 5 2 8 15 \n",
"3 0 0 41 18 24 28 70 \n",
"4 0 0 11 1 2 9 12 "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"df = pd.read_csv('olympics.csv')\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Aquí podemos ignorar la primera fila del `DataFrame` para dejar más limpia la tabla de información no relevante."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" № Summer | \n",
" 01 ! | \n",
" 02 ! | \n",
" 03 ! | \n",
" Total | \n",
" № Winter | \n",
" 01 !.1 | \n",
" 02 !.1 | \n",
" 03 !.1 | \n",
" Total.1 | \n",
" № Games | \n",
" 01 !.2 | \n",
" 02 !.2 | \n",
" 03 !.2 | \n",
" Combined total | \n",
"
\n",
" \n",
" \n",
" \n",
" Afghanistan (AFG) | \n",
" 13 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 2 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 13 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 2 | \n",
"
\n",
" \n",
" Algeria (ALG) | \n",
" 12 | \n",
" 5 | \n",
" 2 | \n",
" 8 | \n",
" 15 | \n",
" 3 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 15 | \n",
" 5 | \n",
" 2 | \n",
" 8 | \n",
" 15 | \n",
"
\n",
" \n",
" Argentina (ARG) | \n",
" 23 | \n",
" 18 | \n",
" 24 | \n",
" 28 | \n",
" 70 | \n",
" 18 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 41 | \n",
" 18 | \n",
" 24 | \n",
" 28 | \n",
" 70 | \n",
"
\n",
" \n",
" Armenia (ARM) | \n",
" 5 | \n",
" 1 | \n",
" 2 | \n",
" 9 | \n",
" 12 | \n",
" 6 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 11 | \n",
" 1 | \n",
" 2 | \n",
" 9 | \n",
" 12 | \n",
"
\n",
" \n",
" Australasia (ANZ) [ANZ] | \n",
" 2 | \n",
" 3 | \n",
" 4 | \n",
" 5 | \n",
" 12 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 3 | \n",
" 4 | \n",
" 5 | \n",
" 12 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" № Summer 01 ! 02 ! 03 ! Total № Winter 01 !.1 \\\n",
"Afghanistan (AFG) 13 0 0 2 2 0 0 \n",
"Algeria (ALG) 12 5 2 8 15 3 0 \n",
"Argentina (ARG) 23 18 24 28 70 18 0 \n",
"Armenia (ARM) 5 1 2 9 12 6 0 \n",
"Australasia (ANZ) [ANZ] 2 3 4 5 12 0 0 \n",
"\n",
" 02 !.1 03 !.1 Total.1 № Games 01 !.2 02 !.2 \\\n",
"Afghanistan (AFG) 0 0 0 13 0 0 \n",
"Algeria (ALG) 0 0 0 15 5 2 \n",
"Argentina (ARG) 0 0 0 41 18 24 \n",
"Armenia (ARM) 0 0 0 11 1 2 \n",
"Australasia (ANZ) [ANZ] 0 0 0 2 3 4 \n",
"\n",
" 03 !.2 Combined total \n",
"Afghanistan (AFG) 2 2 \n",
"Algeria (ALG) 8 15 \n",
"Argentina (ARG) 28 70 \n",
"Armenia (ARM) 9 12 \n",
"Australasia (ANZ) [ANZ] 5 12 "
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv('olympics.csv', index_col = 0, skiprows=1)\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"El atributo `.columns` nos permite ver el nombre de las comlumnas del `DataFrame` y el atributo `.rename` modificar el nombre."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Index(['№ Summer', '01 !', '02 !', '03 !', 'Total', '№ Winter', '01 !.1',\n",
" '02 !.1', '03 !.1', 'Total.1', '№ Games', '01 !.2', '02 !.2', '03 !.2',\n",
" 'Combined total'],\n",
" dtype='object')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.columns"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" # Summer | \n",
" Gold | \n",
" Silver | \n",
" Bronze | \n",
" Total | \n",
" # Winter | \n",
" Gold.1 | \n",
" Silver.1 | \n",
" Bronze.1 | \n",
" Total.1 | \n",
" # Games | \n",
" Gold.2 | \n",
" Silver.2 | \n",
" Bronze.2 | \n",
" Combined total | \n",
"
\n",
" \n",
" \n",
" \n",
" Afghanistan (AFG) | \n",
" 13 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 2 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 13 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 2 | \n",
"
\n",
" \n",
" Algeria (ALG) | \n",
" 12 | \n",
" 5 | \n",
" 2 | \n",
" 8 | \n",
" 15 | \n",
" 3 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 15 | \n",
" 5 | \n",
" 2 | \n",
" 8 | \n",
" 15 | \n",
"
\n",
" \n",
" Argentina (ARG) | \n",
" 23 | \n",
" 18 | \n",
" 24 | \n",
" 28 | \n",
" 70 | \n",
" 18 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 41 | \n",
" 18 | \n",
" 24 | \n",
" 28 | \n",
" 70 | \n",
"
\n",
" \n",
" Armenia (ARM) | \n",
" 5 | \n",
" 1 | \n",
" 2 | \n",
" 9 | \n",
" 12 | \n",
" 6 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 11 | \n",
" 1 | \n",
" 2 | \n",
" 9 | \n",
" 12 | \n",
"
\n",
" \n",
" Australasia (ANZ) [ANZ] | \n",
" 2 | \n",
" 3 | \n",
" 4 | \n",
" 5 | \n",
" 12 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 2 | \n",
" 3 | \n",
" 4 | \n",
" 5 | \n",
" 12 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" # Summer Gold Silver Bronze Total # Winter \\\n",
"Afghanistan (AFG) 13 0 0 2 2 0 \n",
"Algeria (ALG) 12 5 2 8 15 3 \n",
"Argentina (ARG) 23 18 24 28 70 18 \n",
"Armenia (ARM) 5 1 2 9 12 6 \n",
"Australasia (ANZ) [ANZ] 2 3 4 5 12 0 \n",
"\n",
" Gold.1 Silver.1 Bronze.1 Total.1 # Games Gold.2 \\\n",
"Afghanistan (AFG) 0 0 0 0 13 0 \n",
"Algeria (ALG) 0 0 0 0 15 5 \n",
"Argentina (ARG) 0 0 0 0 41 18 \n",
"Armenia (ARM) 0 0 0 0 11 1 \n",
"Australasia (ANZ) [ANZ] 0 0 0 0 2 3 \n",
"\n",
" Silver.2 Bronze.2 Combined total \n",
"Afghanistan (AFG) 0 2 2 \n",
"Algeria (ALG) 2 8 15 \n",
"Argentina (ARG) 24 28 70 \n",
"Armenia (ARM) 2 9 12 \n",
"Australasia (ANZ) [ANZ] 4 5 12 "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"for col in df.columns:\n",
" if col[:2]=='01':\n",
" df.rename(columns={col:'Gold' + col[4:]}, inplace=True)\n",
" if col[:2]=='02':\n",
" df.rename(columns={col:'Silver' + col[4:]}, inplace=True)\n",
" if col[:2]=='03':\n",
" df.rename(columns={col:'Bronze' + col[4:]}, inplace=True)\n",
" if col[:1]=='№':\n",
" df.rename(columns={col:'#' + col[1:]}, inplace=True) \n",
"\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Haciendo búsquedas en un `DataFrame`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos buscar en el `DataFrame` con una **máscara Booleana** qué países tienen (`True`) o no (`False`) una medalla de oro."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Afghanistan (AFG) False\n",
"Algeria (ALG) True\n",
"Argentina (ARG) True\n",
"Armenia (ARM) True\n",
"Australasia (ANZ) [ANZ] True\n",
"Australia (AUS) [AUS] [Z] True\n",
"Austria (AUT) True\n",
"Azerbaijan (AZE) True\n",
"Bahamas (BAH) True\n",
"Bahrain (BRN) False\n",
"Barbados (BAR) [BAR] False\n",
"Belarus (BLR) True\n",
"Belgium (BEL) True\n",
"Bermuda (BER) False\n",
"Bohemia (BOH) [BOH] [Z] False\n",
"Botswana (BOT) False\n",
"Brazil (BRA) True\n",
"British West Indies (BWI) [BWI] False\n",
"Bulgaria (BUL) [H] True\n",
"Burundi (BDI) True\n",
"Cameroon (CMR) True\n",
"Canada (CAN) True\n",
"Chile (CHI) [I] True\n",
"China (CHN) [CHN] True\n",
"Colombia (COL) True\n",
"Costa Rica (CRC) True\n",
"Ivory Coast (CIV) [CIV] False\n",
"Croatia (CRO) True\n",
"Cuba (CUB) [Z] True\n",
"Cyprus (CYP) False\n",
" ... \n",
"Sri Lanka (SRI) [SRI] False\n",
"Sudan (SUD) False\n",
"Suriname (SUR) [E] True\n",
"Sweden (SWE) [Z] True\n",
"Switzerland (SUI) True\n",
"Syria (SYR) True\n",
"Chinese Taipei (TPE) [TPE] [TPE2] True\n",
"Tajikistan (TJK) False\n",
"Tanzania (TAN) [TAN] False\n",
"Thailand (THA) True\n",
"Togo (TOG) False\n",
"Tonga (TGA) False\n",
"Trinidad and Tobago (TRI) [TRI] True\n",
"Tunisia (TUN) True\n",
"Turkey (TUR) True\n",
"Uganda (UGA) True\n",
"Ukraine (UKR) True\n",
"United Arab Emirates (UAE) True\n",
"United States (USA) [P] [Q] [R] [Z] True\n",
"Uruguay (URU) True\n",
"Uzbekistan (UZB) True\n",
"Venezuela (VEN) True\n",
"Vietnam (VIE) False\n",
"Virgin Islands (ISV) False\n",
"Yugoslavia (YUG) [YUG] True\n",
"Independent Olympic Participants (IOP) [IOP] False\n",
"Zambia (ZAM) [ZAM] False\n",
"Zimbabwe (ZIM) [ZIM] True\n",
"Mixed team (ZZX) [ZZX] True\n",
"Totals True\n",
"Name: Gold, Length: 147, dtype: bool"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df['Gold'] > 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"La función `.where()` toma una máscara booleana como condición en el argumento, la aplica al `DataFrame`, y devuelve un `DataFrame` de la misma forma. En nuestro ejemplo, reemplaza con `NaN` los casos `False` y con su valor original, los casos `True`."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" # Summer | \n",
" Gold | \n",
" Silver | \n",
" Bronze | \n",
" Total | \n",
" # Winter | \n",
" Gold.1 | \n",
" Silver.1 | \n",
" Bronze.1 | \n",
" Total.1 | \n",
" # Games | \n",
" Gold.2 | \n",
" Silver.2 | \n",
" Bronze.2 | \n",
" Combined total | \n",
"
\n",
" \n",
" \n",
" \n",
" Afghanistan (AFG) | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
" Algeria (ALG) | \n",
" 12.0 | \n",
" 5.0 | \n",
" 2.0 | \n",
" 8.0 | \n",
" 15.0 | \n",
" 3.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 15.0 | \n",
" 5.0 | \n",
" 2.0 | \n",
" 8.0 | \n",
" 15.0 | \n",
"
\n",
" \n",
" Argentina (ARG) | \n",
" 23.0 | \n",
" 18.0 | \n",
" 24.0 | \n",
" 28.0 | \n",
" 70.0 | \n",
" 18.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 41.0 | \n",
" 18.0 | \n",
" 24.0 | \n",
" 28.0 | \n",
" 70.0 | \n",
"
\n",
" \n",
" Armenia (ARM) | \n",
" 5.0 | \n",
" 1.0 | \n",
" 2.0 | \n",
" 9.0 | \n",
" 12.0 | \n",
" 6.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 11.0 | \n",
" 1.0 | \n",
" 2.0 | \n",
" 9.0 | \n",
" 12.0 | \n",
"
\n",
" \n",
" Australasia (ANZ) [ANZ] | \n",
" 2.0 | \n",
" 3.0 | \n",
" 4.0 | \n",
" 5.0 | \n",
" 12.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.0 | \n",
" 2.0 | \n",
" 3.0 | \n",
" 4.0 | \n",
" 5.0 | \n",
" 12.0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" # Summer Gold Silver Bronze Total # Winter \\\n",
"Afghanistan (AFG) NaN NaN NaN NaN NaN NaN \n",
"Algeria (ALG) 12.0 5.0 2.0 8.0 15.0 3.0 \n",
"Argentina (ARG) 23.0 18.0 24.0 28.0 70.0 18.0 \n",
"Armenia (ARM) 5.0 1.0 2.0 9.0 12.0 6.0 \n",
"Australasia (ANZ) [ANZ] 2.0 3.0 4.0 5.0 12.0 0.0 \n",
"\n",
" Gold.1 Silver.1 Bronze.1 Total.1 # Games Gold.2 \\\n",
"Afghanistan (AFG) NaN NaN NaN NaN NaN NaN \n",
"Algeria (ALG) 0.0 0.0 0.0 0.0 15.0 5.0 \n",
"Argentina (ARG) 0.0 0.0 0.0 0.0 41.0 18.0 \n",
"Armenia (ARM) 0.0 0.0 0.0 0.0 11.0 1.0 \n",
"Australasia (ANZ) [ANZ] 0.0 0.0 0.0 0.0 2.0 3.0 \n",
"\n",
" Silver.2 Bronze.2 Combined total \n",
"Afghanistan (AFG) NaN NaN NaN \n",
"Algeria (ALG) 2.0 8.0 15.0 \n",
"Argentina (ARG) 24.0 28.0 70.0 \n",
"Armenia (ARM) 2.0 9.0 12.0 \n",
"Australasia (ANZ) [ANZ] 4.0 5.0 12.0 "
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"only_gold = df.where(df['Gold'] > 0)\n",
"only_gold.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos contar cuántas países hay medallas de oro hay en total con `count()`"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"100"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"only_gold['Gold'].count()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Si contamos sobre los datos originales, veremos que hay 147 países. Cuenta los países para los cuales la máscara Booleana dio `False` >.<"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"147"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df['Gold'].count()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Podemos establecer otro tipo de condiciones para hacer búsquedas más complejas. Por ejemplo, buscar la cantidad de países que han ganado medalla de oro alguna vez."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"101"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(df[(df['Gold'] > 0) | (df['Gold.1'] > 0)])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"Buscar qué países han ganado sólo medallas de oro en Invierno y nunca en Verano."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" # Summer | \n",
" Gold | \n",
" Silver | \n",
" Bronze | \n",
" Total | \n",
" # Winter | \n",
" Gold.1 | \n",
" Silver.1 | \n",
" Bronze.1 | \n",
" Total.1 | \n",
" # Games | \n",
" Gold.2 | \n",
" Silver.2 | \n",
" Bronze.2 | \n",
" Combined total | \n",
"
\n",
" \n",
" \n",
" \n",
" Liechtenstein (LIE) | \n",
" 16 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 18 | \n",
" 2 | \n",
" 2 | \n",
" 5 | \n",
" 9 | \n",
" 34 | \n",
" 2 | \n",
" 2 | \n",
" 5 | \n",
" 9 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" # Summer Gold Silver Bronze Total # Winter Gold.1 \\\n",
"Liechtenstein (LIE) 16 0 0 0 0 18 2 \n",
"\n",
" Silver.1 Bronze.1 Total.1 # Games Gold.2 Silver.2 \\\n",
"Liechtenstein (LIE) 2 5 9 34 2 2 \n",
"\n",
" Bronze.2 Combined total \n",
"Liechtenstein (LIE) 5 9 "
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df[(df['Gold.1'] > 0) & (df['Gold'] == 0)]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 1
}