{
"cells": [
{
"cell_type": "markdown",
"id": "39ad3312",
"metadata": {},
"source": [
"Retail Analysis examples\n",
"======================\n",
"Simple TenFrame examples for some basic analysis, to show how familiar it is for python users, and to demonstrate performance on a large dataset."
]
},
{
"cell_type": "markdown",
"id": "367cf2c0",
"metadata": {},
"source": [
"Load iris\n",
"----------"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8c9e3979",
"metadata": {},
"outputs": [],
"source": [
"load_ext iris"
]
},
{
"cell_type": "markdown",
"id": "276825b3",
"metadata": {},
"source": [
"Import libraries\n",
"------------------"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "a3f0aa89",
"metadata": {},
"outputs": [],
"source": [
"import py1010\n",
"import tenFrame as tf\n",
"import pandas as pd\n",
"import numpy as np\n",
"tf.useiris(False)\n",
"\n",
"session = py1010.Session(\"1010data URL\", \"USERNAME\", \"PASSWORD\", py1010.POSSESS)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "152b3023",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total sales rows: 5,997,373,902\n",
"Rows with known customers: 836,621,077\n"
]
}
],
"source": [
"sales = tf.TenFrame(session, \"retaildemo.retail.sales_detail\")\n",
"# without downsampling, describe() below takes about 6 minutes. Plan accordingly.\n",
"# sales = sales.sample(frac=1e-3)\n",
"print(f\"Total sales rows: {len(sales):,}\")\n",
"# Sales linked with customer data, filtered to rows where such data exists.\n",
"salescust = tf.merge(sales, \"retaildemo.retail.customers\", on=\"customer_key\")\n",
"salescust.dropna(subset=[\"customer_key\"], inplace=True)\n",
"print(f\"Rows with known customers: {len(salescust):,}\")\n",
"# Sales linked with product data\n",
"salesprod = tf.merge(sales, \"retaildemo.retail.products\", on=\"sku\")"
]
},
{
"cell_type": "markdown",
"id": "5eb564e7",
"metadata": {},
"source": [
"Overview of data\n",
"--------------------\n",
"We can just do the usual `describe()` method for an overview of the sales data."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "166a02b6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 32 ms, sys: 19.2 ms, total: 51.1 ms\n",
"Wall time: 445 ms\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" qty | \n",
" weight | \n",
" xsales | \n",
" price | \n",
" cost | \n",
"
\n",
" \n",
" \n",
" \n",
" count | \n",
" 5.997374e+09 | \n",
" 5.997374e+09 | \n",
" 5.997374e+09 | \n",
" 5.997374e+09 | \n",
" 5.997024e+09 | \n",
"
\n",
" \n",
" mean | \n",
" 1.356727e+00 | \n",
" 1.144611e+00 | \n",
" 3.895354e+00 | \n",
" 3.153982e+00 | \n",
" 2.675612e+00 | \n",
"
\n",
" \n",
" std_s | \n",
" 1.252325e+00 | \n",
" 8.808362e-01 | \n",
" 4.493964e+00 | \n",
" 3.159839e+00 | \n",
" 3.375028e+00 | \n",
"
\n",
" \n",
" min | \n",
" -9.900000e+01 | \n",
" -1.066300e+02 | \n",
" -4.227208e+04 | \n",
" -9.717720e+03 | \n",
" -2.954677e+04 | \n",
"
\n",
" \n",
" lquart | \n",
" 1.000000e+00 | \n",
" 1.000000e+00 | \n",
" 1.770000e+00 | \n",
" 1.370000e+00 | \n",
" 1.070000e+00 | \n",
"
\n",
" \n",
" median | \n",
" 2.000000e+00 | \n",
" 1.000000e+00 | \n",
" 2.870000e+00 | \n",
" 2.500000e+00 | \n",
" 1.920000e+00 | \n",
"
\n",
" \n",
" uquart | \n",
" 2.000000e+00 | \n",
" 1.420000e+00 | \n",
" 4.650000e+00 | \n",
" 3.870000e+00 | \n",
" 3.090000e+00 | \n",
"
\n",
" \n",
" max | \n",
" 9.900000e+01 | \n",
" 1.200000e+02 | \n",
" 8.997500e+02 | \n",
" 1.999900e+02 | \n",
" 2.705800e+03 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" qty weight xsales price cost\n",
"count 5.997374e+09 5.997374e+09 5.997374e+09 5.997374e+09 5.997024e+09\n",
"mean 1.356727e+00 1.144611e+00 3.895354e+00 3.153982e+00 2.675612e+00\n",
"std_s 1.252325e+00 8.808362e-01 4.493964e+00 3.159839e+00 3.375028e+00\n",
"min -9.900000e+01 -1.066300e+02 -4.227208e+04 -9.717720e+03 -2.954677e+04\n",
"lquart 1.000000e+00 1.000000e+00 1.770000e+00 1.370000e+00 1.070000e+00\n",
"median 2.000000e+00 1.000000e+00 2.870000e+00 2.500000e+00 1.920000e+00\n",
"uquart 2.000000e+00 1.420000e+00 4.650000e+00 3.870000e+00 3.090000e+00\n",
"max 9.900000e+01 1.200000e+02 8.997500e+02 1.999900e+02 2.705800e+03"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"sales.describe(exclude=[\"transid\", \"date\", \"tme\", \"sku\", \"store\", \"customer_key\", \"promo_flag\"])"
]
},
{
"cell_type": "markdown",
"id": "697e62f3",
"metadata": {},
"source": [
"More detailed overview\n",
"----------------------------\n",
"The following shows an overview at a slightly more granular level, with customer data."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "82f57bc4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 39.4 ms, sys: 11 ms, total: 50.5 ms\n",
"Wall time: 617 ms\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" gender | \n",
" qty_count | \n",
" qty_mean | \n",
" qty_std_s | \n",
" qty_min | \n",
" qty_lquart | \n",
" qty_median | \n",
" qty_uquart | \n",
" qty_max | \n",
" weight_count | \n",
" ... | \n",
" cost_uquart | \n",
" cost_max | \n",
" age_count | \n",
" age_mean | \n",
" age_std_s | \n",
" age_min | \n",
" age_lquart | \n",
" age_median | \n",
" age_uquart | \n",
" age_max | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" M | \n",
" 176834985.0 | \n",
" 1.310697 | \n",
" 0.962674 | \n",
" -82.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 99.0 | \n",
" 176834985.0 | \n",
" ... | \n",
" 3.21 | \n",
" 765.69 | \n",
" 176834985.0 | \n",
" 47.831535 | \n",
" 10.575100 | \n",
" 18 | \n",
" 41 | \n",
" 48 | \n",
" 55 | \n",
" 92 | \n",
"
\n",
" \n",
" 1 | \n",
" F | \n",
" 566190126.0 | \n",
" 1.309058 | \n",
" 0.958930 | \n",
" -89.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 99.0 | \n",
" 566190126.0 | \n",
" ... | \n",
" 3.20 | \n",
" 824.12 | \n",
" 566190126.0 | \n",
" 47.765438 | \n",
" 10.659013 | \n",
" 18 | \n",
" 41 | \n",
" 48 | \n",
" 55 | \n",
" 96 | \n",
"
\n",
" \n",
" 2 | \n",
" <NA> | \n",
" 93595966.0 | \n",
" 1.398271 | \n",
" 1.185352 | \n",
" -70.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 99.0 | \n",
" 93595966.0 | \n",
" ... | \n",
" 3.26 | \n",
" 712.15 | \n",
" 93595966.0 | \n",
" 46.804938 | \n",
" 10.590270 | \n",
" 17 | \n",
" 40 | \n",
" 47 | \n",
" 54 | \n",
" 94 | \n",
"
\n",
" \n",
"
\n",
"
3 rows × 49 columns
\n",
"
"
],
"text/plain": [
" gender qty_count qty_mean qty_std_s qty_min qty_lquart qty_median \\\n",
"0 M 176834985.0 1.310697 0.962674 -82.0 1.0 1.0 \n",
"1 F 566190126.0 1.309058 0.958930 -89.0 1.0 1.0 \n",
"2 93595966.0 1.398271 1.185352 -70.0 1.0 1.0 \n",
"\n",
" qty_uquart qty_max weight_count ... cost_uquart cost_max age_count \\\n",
"0 1.0 99.0 176834985.0 ... 3.21 765.69 176834985.0 \n",
"1 1.0 99.0 566190126.0 ... 3.20 824.12 566190126.0 \n",
"2 1.0 99.0 93595966.0 ... 3.26 712.15 93595966.0 \n",
"\n",
" age_mean age_std_s age_min age_lquart age_median age_uquart age_max \n",
"0 47.831535 10.575100 18 41 48 55 92 \n",
"1 47.765438 10.659013 18 41 48 55 96 \n",
"2 46.804938 10.590270 17 40 47 54 94 \n",
"\n",
"[3 rows x 49 columns]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"salescust.groupby(\"gender\").describe(exclude=[\"transid\", \"date\", \"tme\", \"sku\", \"store\", \"customer_key\", \"promo_flag\", \"birthdate\", \"customerid\", \"tier\"])\n",
"# (the short and very very wide format is what pandas does as well.)"
]
},
{
"cell_type": "markdown",
"id": "eb3e0742",
"metadata": {},
"source": [
"Count of transactions by date\n",
"-----------------------------------"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "7eea22bf",
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\t\n",
"\t\n",
"\t\n",
"\t\n",
"\n",
"\n",
"CPU times: user 18.3 ms, sys: 10.5 ms, total: 28.8 ms\n",
"Wall time: 1.16 s\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" date | \n",
" transid_cnt | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 2012-12-31 | \n",
" 3332409 | \n",
"
\n",
" \n",
" 1 | \n",
" 2013-01-01 | \n",
" 1912203 | \n",
"
\n",
" \n",
" 2 | \n",
" 2013-01-02 | \n",
" 2374098 | \n",
"
\n",
" \n",
" 3 | \n",
" 2013-01-03 | \n",
" 2403905 | \n",
"
\n",
" \n",
" 4 | \n",
" 2013-01-04 | \n",
" 2512208 | \n",
"
\n",
" \n",
" 5 | \n",
" 2013-01-05 | \n",
" 2792596 | \n",
"
\n",
" \n",
" 6 | \n",
" 2013-01-06 | \n",
" 3134535 | \n",
"
\n",
" \n",
" 7 | \n",
" 2013-01-07 | \n",
" 2659785 | \n",
"
\n",
" \n",
" 8 | \n",
" 2013-01-08 | \n",
" 2425479 | \n",
"
\n",
" \n",
" 9 | \n",
" 2013-01-09 | \n",
" 2338966 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" date transid_cnt\n",
"0 2012-12-31 3332409\n",
"1 2013-01-01 1912203\n",
"2 2013-01-02 2374098\n",
"3 2013-01-03 2403905\n",
"4 2013-01-04 2512208\n",
"5 2013-01-05 2792596\n",
"6 2013-01-06 3134535\n",
"7 2013-01-07 2659785\n",
"8 2013-01-08 2425479\n",
"9 2013-01-09 2338966"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"r = sales.groupby(\"date\").transid.cnt()\n",
"r.printprettyXML()\n",
"q = r.iloc[0] # Something to make the time shown honest.\n",
"r"
]
},
{
"cell_type": "markdown",
"id": "ebf6e067",
"metadata": {},
"source": [
"Total sales by date\n",
"----------------------"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "97fa288a",
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\t\n",
"\t\n",
"\t\n",
"\t\n",
"\n",
"\n",
"CPU times: user 22.5 ms, sys: 11.3 ms, total: 33.8 ms\n",
"Wall time: 1.33 s\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" date | \n",
" xsales_sum | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 2012-12-31 | \n",
" 1.335217e+07 | \n",
"
\n",
" \n",
" 1 | \n",
" 2013-01-01 | \n",
" 6.713122e+06 | \n",
"
\n",
" \n",
" 2 | \n",
" 2013-01-02 | \n",
" 8.270888e+06 | \n",
"
\n",
" \n",
" 3 | \n",
" 2013-01-03 | \n",
" 8.443139e+06 | \n",
"
\n",
" \n",
" 4 | \n",
" 2013-01-04 | \n",
" 9.015836e+06 | \n",
"
\n",
" \n",
" 5 | \n",
" 2013-01-05 | \n",
" 1.000415e+07 | \n",
"
\n",
" \n",
" 6 | \n",
" 2013-01-06 | \n",
" 1.086893e+07 | \n",
"
\n",
" \n",
" 7 | \n",
" 2013-01-07 | \n",
" 9.230439e+06 | \n",
"
\n",
" \n",
" 8 | \n",
" 2013-01-08 | \n",
" 8.493609e+06 | \n",
"
\n",
" \n",
" 9 | \n",
" 2013-01-09 | \n",
" 8.253537e+06 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" date xsales_sum\n",
"0 2012-12-31 1.335217e+07\n",
"1 2013-01-01 6.713122e+06\n",
"2 2013-01-02 8.270888e+06\n",
"3 2013-01-03 8.443139e+06\n",
"4 2013-01-04 9.015836e+06\n",
"5 2013-01-05 1.000415e+07\n",
"6 2013-01-06 1.086893e+07\n",
"7 2013-01-07 9.230439e+06\n",
"8 2013-01-08 8.493609e+06\n",
"9 2013-01-09 8.253537e+06"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"r = sales.groupby(\"date\")['xsales'].sum()\n",
"r.printprettyXML()\n",
"q = r.iloc[0]\n",
"r"
]
},
{
"cell_type": "markdown",
"id": "c0242e88",
"metadata": {},
"source": [
"Transactions, total sales, and sales per transaction, by customer\n",
"-----------------------------------------------------------------------------"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "d5dea487",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\n",
"\t\n",
"\t\n",
"\t= 1)\"/>\n",
"\t\n",
"\t\t\n",
"\t\t\n",
"\t\n",
"\t\n",
"\n",
"\n",
"CPU times: user 40.5 ms, sys: 20.3 ms, total: 60.8 ms\n",
"Wall time: 1.38 s\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" customer_key | \n",
" transid_count | \n",
" xsales_sum | \n",
" sales_per_trans | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1 | \n",
" 776.0 | \n",
" 3268.82 | \n",
" 4.212397 | \n",
"
\n",
" \n",
" 1 | \n",
" 2 | \n",
" 1131.0 | \n",
" 2518.92 | \n",
" 2.227162 | \n",
"
\n",
" \n",
" 2 | \n",
" 3 | \n",
" 1754.0 | \n",
" 5529.91 | \n",
" 3.152742 | \n",
"
\n",
" \n",
" 3 | \n",
" 4 | \n",
" 1721.0 | \n",
" 5131.60 | \n",
" 2.981755 | \n",
"
\n",
" \n",
" 4 | \n",
" 5 | \n",
" 2743.0 | \n",
" 8399.06 | \n",
" 3.061998 | \n",
"
\n",
" \n",
" 5 | \n",
" 6 | \n",
" 1961.0 | \n",
" 9066.47 | \n",
" 4.623391 | \n",
"
\n",
" \n",
" 6 | \n",
" 7 | \n",
" 153.0 | \n",
" 1339.69 | \n",
" 8.756144 | \n",
"
\n",
" \n",
" 7 | \n",
" 8 | \n",
" 198.0 | \n",
" 523.50 | \n",
" 2.643939 | \n",
"
\n",
" \n",
" 8 | \n",
" 9 | \n",
" 1177.0 | \n",
" 4034.91 | \n",
" 3.428131 | \n",
"
\n",
" \n",
" 9 | \n",
" 10 | \n",
" 618.0 | \n",
" 1840.90 | \n",
" 2.978803 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" customer_key transid_count xsales_sum sales_per_trans\n",
"0 1 776.0 3268.82 4.212397\n",
"1 2 1131.0 2518.92 2.227162\n",
"2 3 1754.0 5529.91 3.152742\n",
"3 4 1721.0 5131.60 2.981755\n",
"4 5 2743.0 8399.06 3.061998\n",
"5 6 1961.0 9066.47 4.623391\n",
"6 7 153.0 1339.69 8.756144\n",
"7 8 198.0 523.50 2.643939\n",
"8 9 1177.0 4034.91 3.428131\n",
"9 10 618.0 1840.90 2.978803"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"r = salescust.groupby(\"customer_key\").agg({\"transid\":\"count\", \"xsales\":\"sum\"})\n",
"r['sales_per_trans'] = r['xsales_sum'] / r['transid_count']\n",
"r.printprettyXML()\n",
"q = r.iloc[0]\n",
"r"
]
},
{
"cell_type": "markdown",
"id": "7a6796ce",
"metadata": {},
"source": [
"Charting examples\n",
"-----------------------\n",
" 1. Bar chart on total sales by gender.\n",
" 2. Histogram on age.\n",
" 3. Bar chart on number of transactions by age group.\n",
" 4. Bar chart on total sales by age group."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "7361a514",
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 952 ms, sys: 449 ms, total: 1.4 s\n",
"Wall time: 1min 48s\n"
]
},
{
"data": {
"text/plain": [
""
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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a88+++xt76usrNR///d/y263q7KysgGnal44MgIAaNY2bdpU7fqPPvpIc+fOlaenp37xi1808FTNC58zAgDAt+zdu1cDBw7UD3/4Qz399NM6deqUXn31VdNjuTViBAAASYcPH9aoUaM0ZMgQhYeH6/jx41qwYIHuu+8+06O5PWIEANCsFRQUaPLkyXrooYfUsmVLffHFF0pNTVXXrl1Nj9ZscAErAKBZ8/b2ls1m04wZM/T444/fdrt//dd/bcCpmhdiBADQrLVoUfNJApvNxrtp7iFiBAAAGMU1IwCAZu/q1as6dOhQtfcdPnxYly9fbuCJmhdiBADQ7JWXl2vAgAH6/PPPndYfOXJEkZGRxMg9RowAAJo9f39/jRo1Sh988IHT+tWrV+vJJ59Up06dDE3WPBAjAABImjBhgj788ENdv35dkmRZln77299q0qRJZgdrBogRAAAkjRgxQi1btlRmZqYkadeuXbp8+bJGjx5tdrBmgBgBAECSh4eHxo8f7zhVs3r1ao0dO1atW7c2PJn74629AAD8v0OHDunRRx/VyZMnFRERoe3bt+uxxx4zPZbbI0YAAPiWqKgo+fj4qLi4WMeOHTM9TrPAaRoAAL5l4sSJys7O1sSJE02P0my0ND0AAACNyfjx4/WPf/xDkydPNj1Ks8FpGgAAYBSnaQAAgFHECAAAMIoYAQAARhEjABq1SZMm8QmYgJsjRgAAgFHECAC3ZlmW44vPADROxAiAWrl06ZLGjRuntm3bKjg4WO+8846GDBmiWbNmSZLKy8s1Z84cdenSRW3bttWAAQOUlZXl2H/lypXy9/fXtm3bFBERoXbt2mnEiBEqKipybFNZWamEhAT5+/srICBAc+bM0T9/+oBlWfqP//gP9ejRQ23atFH//v31+9//3nF/VlaWbDabtm3bpujoaHl6emrPnj339HcD4O4QIwBqJSEhQXv37tWWLVu0Y8cO7dmzRwcOHHDcP3nyZO3du1fr1q3TF198oeeff14jRozQiRMnHNtcvXpVCxcu1OrVq5Wdna38/HwlJiY67l+0aJHS0tKUmpqqTz/9VH//+9+1adMmpzlef/11paena9myZTp8+LBmz56t8ePHa/fu3U7bzZkzR8nJyTp69KgefPDBe/RbAVAvLACoQVlZmdWqVStrw4YNjnUXL160vL29rZdfftk6efKkZbPZrMLCQqf9hg0bZiUlJVmWZVnp6emWJOvkyZOO+99//30rKCjIsRwcHGzNnz/fsVxRUWF17drVeuaZZyzLsqzLly9bXl5e1r59+5weZ+rUqdYPfvADy7Isa9euXZYka/PmzfXz5AHcc3wcPIAanTp1ShUVFXr00Ucd6/z8/BQeHi5JOnDggCzLUlhYmNN+drtdAQEBjmVvb2/17NnTsRwcHKySkhJJUmlpqYqKihQTE+O4v2XLloqOjnacqjly5IiuXbum7373u06PU15ersjISKd10dHRd/OUATQgYgRAjW7GgM1mq3Z9VVWVPDw8tH//fnl4eDht065dO8f/btWqldN9NpvtlmtC7qSqqkqSlJmZqS5dujjd5+np6bTctm3bWv9cAGYRIwBq1LNnT7Vq1Uqff/65QkJCJEllZWU6ceKEnnjiCUVGRqqyslIlJSUaNGhQnR7Dz89PwcHB+vOf/6zBgwdLkq5fv679+/fr4YcfliT17t1bnp6eys/P1xNPPFE/Tw6AccQIgBr5+Pho4sSJ+ulPf6r27dsrMDBQ//7v/64WLVrIZrMpLCxM48aN04QJE7Ro0SJFRkbq/Pnz2rlzp/r166e4uLhaPc7LL7+s+fPnq1evXoqIiNDixYt18eJFpzkSExM1e/ZsVVVVaeDAgSorK9O+ffvUrl07vvIdaKKIEQC1snjxYsXHx+vpp5+Wr6+v5syZo4KCAnl5eUmS0tPTNW/ePL3yyisqLCxUQECAYmJiah0ikvTKK6+oqKhIkyZNUosWLTRlyhQ9++yzKi0tdWzzy1/+UoGBgUpOTtapU6fk7++vhx9+WHPnzq335wygYdgsV07YAsD/u3Llirp06aJFixZp6tSppscB0IRxZARArRw8eFDHjh3To48+qtLSUr311luSpGeeecbwZACaOmIEQK0tXLhQx48fV+vWrRUVFaU9e/aoQ4cOpscC0MRxmgYAABjFx8EDAACjiBEAAGAUMQIAAIwiRgAAgFHECAAAMIoYAQAARhEjAADAKGIEAAAYRYwAAACj/g84/Kvx4lE7uAAAAABJRU5ErkJggg==\n",
"text/plain": [
"