Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ibarrajo/154d3d82849c1494ecfffc3299d8eb15 to your computer and use it in GitHub Desktop.
Save ibarrajo/154d3d82849c1494ecfffc3299d8eb15 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {},
"cell_type": "markdown",
"source": "## Josué Alexander Ibarra - 2018-05-21\n\nI created this jupyter notebook to show some of the specific ideas I mentioned which we didn't have the time to explore on our interview last Monday. I'm sharing this with you on the MIT license so feel free to use this as a boilerplate on any future interviews.\n\n\n## Challenge\n\n At Cedar, we aim to find the best messaging that will motivate the patient to engage with us.\n You have two lists of data:\n\n 1) A list of bill notification messages sent to patients.\n Each message has the following properties: patient_id, channel_type, timestamp\n channel_type can be \"text\", \"email\", \"paper mail\", or another channels for contacting patients.\n\n 2) A list of payments that Cedar received from patients.\n Each message has the following properties: patient_id, payment_amount, timestamp\n\n Each list is stored in memory in a list or array data structure.\n\n Your goal is to produce output that allows us to see which channel type\n is most effective at driving payments."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "import time\nimport seaborn\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom numpy.random import choice\nfrom pylab import *",
"execution_count": 1,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Since we don't have actual data to use, I created the following generators with a few features.\n\n1. Channel types are extendable\n2. Channel types are also weighted like real data would be naturally.\n3. Timestamp difference between invoice notification and payment spaced randomly but logically.\n3. Building a step up from the challenge, the lists are converted into data frames"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# types with corresponding distribution weights\nchannelTypes = {\n 'text': 0.2,\n 'email': 0.5,\n 'paper_mail': 0.3\n}\n\ndef generateTimestamp(start=None, end=None):\n start = 946684800 if start is None else start\n end = time.time() if end is None else end\n return randint(start, end)\n\n# randomly generate invoices\ndef generateBillNotifications(n):\n notifications = []\n for i in range(0, n):\n b = {'patient_id': None, 'channel_type': None, 'timestamp': None}\n b['patient_id'] = i + 1000\n b['channel_type'] = choice(list(channelTypes.keys()), p=list(channelTypes.values()))\n b['timestamp'] = generateTimestamp()\n notifications.append(b)\n return pd.DataFrame(notifications)\n\n# generate payments for randomly selected invoices\ndef generatePayments(invoices):\n # select anywhere from 0 to all of the invoices\n paidInvoices = invoices.sample(randint(0, len(invoices)))\n payments = []\n for i, invoice in paidInvoices.iterrows():\n p = {'patient_id': None, 'payment_amount': None, 'timestamp': None}\n p['patient_id'] = invoice['patient_id']\n p['payment_amount'] = randint(1,10000)\n p['timestamp'] = generateTimestamp(start=invoice['timestamp'])\n payments.append(p)\n return pd.DataFrame(payments)",
"execution_count": 2,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "invoices = generateBillNotifications(10000)\ninvoices[:10]",
"execution_count": 3,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 3,
"data": {
"text/plain": " channel_type patient_id timestamp\n0 email 1000 1289771509\n1 email 1001 1414226660\n2 text 1002 990610270\n3 paper_mail 1003 1347108734\n4 email 1004 1081675517\n5 email 1005 992769694\n6 text 1006 1510985177\n7 email 1007 1220289840\n8 paper_mail 1008 1069108345\n9 email 1009 1264183486",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>channel_type</th>\n <th>patient_id</th>\n <th>timestamp</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>email</td>\n <td>1000</td>\n <td>1289771509</td>\n </tr>\n <tr>\n <th>1</th>\n <td>email</td>\n <td>1001</td>\n <td>1414226660</td>\n </tr>\n <tr>\n <th>2</th>\n <td>text</td>\n <td>1002</td>\n <td>990610270</td>\n </tr>\n <tr>\n <th>3</th>\n <td>paper_mail</td>\n <td>1003</td>\n <td>1347108734</td>\n </tr>\n <tr>\n <th>4</th>\n <td>email</td>\n <td>1004</td>\n <td>1081675517</td>\n </tr>\n <tr>\n <th>5</th>\n <td>email</td>\n <td>1005</td>\n <td>992769694</td>\n </tr>\n <tr>\n <th>6</th>\n <td>text</td>\n <td>1006</td>\n <td>1510985177</td>\n </tr>\n <tr>\n <th>7</th>\n <td>email</td>\n <td>1007</td>\n <td>1220289840</td>\n </tr>\n <tr>\n <th>8</th>\n <td>paper_mail</td>\n <td>1008</td>\n <td>1069108345</td>\n </tr>\n <tr>\n <th>9</th>\n <td>email</td>\n <td>1009</td>\n <td>1264183486</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {}
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "payments = generatePayments(invoices)\npayments[:10]",
"execution_count": 4,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 4,
"data": {
"text/plain": " patient_id payment_amount timestamp\n0 10780 9578 1509186216\n1 10331 1544 1241538460\n2 6578 9274 1427657128\n3 9500 9114 1390174185\n4 8065 3868 1526258284\n5 10149 8039 1257680107\n6 6024 9231 1491059129\n7 10724 7163 1420921548\n8 3264 5468 1507826298\n9 3081 3783 1204927855",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>patient_id</th>\n <th>payment_amount</th>\n <th>timestamp</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>10780</td>\n <td>9578</td>\n <td>1509186216</td>\n </tr>\n <tr>\n <th>1</th>\n <td>10331</td>\n <td>1544</td>\n <td>1241538460</td>\n </tr>\n <tr>\n <th>2</th>\n <td>6578</td>\n <td>9274</td>\n <td>1427657128</td>\n </tr>\n <tr>\n <th>3</th>\n <td>9500</td>\n <td>9114</td>\n <td>1390174185</td>\n </tr>\n <tr>\n <th>4</th>\n <td>8065</td>\n <td>3868</td>\n <td>1526258284</td>\n </tr>\n <tr>\n <th>5</th>\n <td>10149</td>\n <td>8039</td>\n <td>1257680107</td>\n </tr>\n <tr>\n <th>6</th>\n <td>6024</td>\n <td>9231</td>\n <td>1491059129</td>\n </tr>\n <tr>\n <th>7</th>\n <td>10724</td>\n <td>7163</td>\n <td>1420921548</td>\n </tr>\n <tr>\n <th>8</th>\n <td>3264</td>\n <td>5468</td>\n <td>1507826298</td>\n </tr>\n <tr>\n <th>9</th>\n <td>3081</td>\n <td>3783</td>\n <td>1204927855</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "After generating the two dataframes `invoices` containing all of the notifications sent and `payments` containing a random amount of payments that correspond to some of the invoices sent we can start our data analysis.\n\nThe first step is to do an outer join of our two data frames on the unique `patient_id`.\n\nWe also take the opportunity to create two new colums.\n\n1. `is_paid` a boolean determining if a patient paid based on the contents of the `timestamp_payment`\n2. `payment_wait` is an integer denoting the number of seconds since the bill came out until a payment was made."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "invoices = pd.merge(invoices, payments, on='patient_id', how='outer', suffixes=('_invoice','_payment'))\ninvoices['is_paid'] = invoices['timestamp_payment'].notnull()\ninvoices['payment_wait'] = invoices['timestamp_payment'] - invoices['timestamp_invoice']\ninvoices[:10]",
"execution_count": 5,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 5,
"data": {
"text/plain": " channel_type patient_id timestamp_invoice payment_amount \\\n0 email 1000 1289771509 NaN \n1 email 1001 1414226660 NaN \n2 text 1002 990610270 NaN \n3 paper_mail 1003 1347108734 NaN \n4 email 1004 1081675517 NaN \n5 email 1005 992769694 1538.0 \n6 text 1006 1510985177 NaN \n7 email 1007 1220289840 NaN \n8 paper_mail 1008 1069108345 NaN \n9 email 1009 1264183486 6938.0 \n\n timestamp_payment is_paid payment_wait \n0 NaN False NaN \n1 NaN False NaN \n2 NaN False NaN \n3 NaN False NaN \n4 NaN False NaN \n5 1.477958e+09 True 485188507.0 \n6 NaN False NaN \n7 NaN False NaN \n8 NaN False NaN \n9 1.515415e+09 True 251231949.0 ",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>channel_type</th>\n <th>patient_id</th>\n <th>timestamp_invoice</th>\n <th>payment_amount</th>\n <th>timestamp_payment</th>\n <th>is_paid</th>\n <th>payment_wait</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>email</td>\n <td>1000</td>\n <td>1289771509</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>1</th>\n <td>email</td>\n <td>1001</td>\n <td>1414226660</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>2</th>\n <td>text</td>\n <td>1002</td>\n <td>990610270</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>3</th>\n <td>paper_mail</td>\n <td>1003</td>\n <td>1347108734</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>4</th>\n <td>email</td>\n <td>1004</td>\n <td>1081675517</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>5</th>\n <td>email</td>\n <td>1005</td>\n <td>992769694</td>\n <td>1538.0</td>\n <td>1.477958e+09</td>\n <td>True</td>\n <td>485188507.0</td>\n </tr>\n <tr>\n <th>6</th>\n <td>text</td>\n <td>1006</td>\n <td>1510985177</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>7</th>\n <td>email</td>\n <td>1007</td>\n <td>1220289840</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>8</th>\n <td>paper_mail</td>\n <td>1008</td>\n <td>1069108345</td>\n <td>NaN</td>\n <td>NaN</td>\n <td>False</td>\n <td>NaN</td>\n </tr>\n <tr>\n <th>9</th>\n <td>email</td>\n <td>1009</td>\n <td>1264183486</td>\n <td>6938.0</td>\n <td>1.515415e+09</td>\n <td>True</td>\n <td>251231949.0</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Now that we have the joined dataframe `invoices` we can first start off by creating histograms on the column type and comparing the distribution of the notifications by `channel_type`.\n\nWe try to find a correlation to a channel being more performant by grouping them by `is_paid`. Most of the time the generated data will not show an inclination for a method to be more effective at this stage since the paid records are randomly selected."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "invoices.hist(column='channel_type', by='is_paid');",
"execution_count": 6,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<matplotlib.figure.Figure at 0x110e2e6d8>",
"image/png": "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\n"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "To yield a better insight of what we are doing we can better aggregate the number of payments by `channel_type` using the `crosstab` pandas method."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "pd.crosstab(invoices['channel_type'], invoices['is_paid'], margins=True)",
"execution_count": 7,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 7,
"data": {
"text/plain": "is_paid False True All\nchannel_type \nemail 4218 781 4999\npaper_mail 2484 521 3005\ntext 1671 325 1996\nAll 8373 1627 10000",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th>is_paid</th>\n <th>False</th>\n <th>True</th>\n <th>All</th>\n </tr>\n <tr>\n <th>channel_type</th>\n <th></th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>email</th>\n <td>4218</td>\n <td>781</td>\n <td>4999</td>\n </tr>\n <tr>\n <th>paper_mail</th>\n <td>2484</td>\n <td>521</td>\n <td>3005</td>\n </tr>\n <tr>\n <th>text</th>\n <td>1671</td>\n <td>325</td>\n <td>1996</td>\n </tr>\n <tr>\n <th>All</th>\n <td>8373</td>\n <td>1627</td>\n <td>10000</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Integer amounts are not quite cutting it, maybe if we read it in more absolute terms using percentages."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "pd.crosstab(invoices['channel_type'], invoices['is_paid'], margins=True, normalize ='all')",
"execution_count": 8,
"outputs": [
{
"output_type": "execute_result",
"execution_count": 8,
"data": {
"text/plain": "is_paid False True All\nchannel_type \nemail 0.4218 0.0781 0.4999\npaper_mail 0.2484 0.0521 0.3005\ntext 0.1671 0.0325 0.1996\nAll 0.8373 0.1627 1.0000",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th>is_paid</th>\n <th>False</th>\n <th>True</th>\n <th>All</th>\n </tr>\n <tr>\n <th>channel_type</th>\n <th></th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>email</th>\n <td>0.4218</td>\n <td>0.0781</td>\n <td>0.4999</td>\n </tr>\n <tr>\n <th>paper_mail</th>\n <td>0.2484</td>\n <td>0.0521</td>\n <td>0.3005</td>\n </tr>\n <tr>\n <th>text</th>\n <td>0.1671</td>\n <td>0.0325</td>\n <td>0.1996</td>\n </tr>\n <tr>\n <th>All</th>\n <td>0.8373</td>\n <td>0.1627</td>\n <td>1.0000</td>\n </tr>\n </tbody>\n</table>\n</div>"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "We understand that the way the data was generated, a stronger correlation of a `channel_type` to its performance might not be strongly shown.\n\nA neat way to visualize and in my opinion the best way to find hidden correlations is to create a heatmap.\n\nTo do this, the first step is to create a one-hot encoding of our categorical data (the channel types). It is accomplished by the pandas `get_dummies` method and joined into a column-wise subset of our `invoices` table.\n\nWe run the correlation and generate the output using the data visualization library `seaborn`.\n\nResults will vary on each full run of this notebook, but the interesting correlations will be clearly visible here."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# one-hot encoding for channel_type\ninvoicesCorr = invoices[['is_paid']].join(pd.get_dummies(invoices['channel_type']))\n\ninvoicesCorr = invoicesCorr.corr()\nseaborn.heatmap(invoicesCorr)\n\nplt.title('Channel type correlation heatmap')\nplt.show()",
"execution_count": 9,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<matplotlib.figure.Figure at 0x110c19cc0>",
"image/png": "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\n"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Calculate per-channel payment rate"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "for channel in invoices['channel_type'].unique():\n totalPayments = invoices[(invoices['channel_type'] == channel) & invoices['is_paid']].sum()['payment_amount']\n totalNotifications = invoices[invoices['channel_type'] == channel].count()['channel_type']\n paymentRate = totalPayments / totalNotifications\n print(\"Each {} has a mean payment rate of ${:.2f}\".format(channel, paymentRate))\n",
"execution_count": 22,
"outputs": [
{
"output_type": "stream",
"text": "Each email has a mean payment rate of $752.18\nEach text has a mean payment rate of $785.12\nEach paper_mail has a mean payment rate of $872.86\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Now, the answer to the question of which channel type performs better.\n\nSince we are using mock data here, the answer is hard to determine, but the methods we used to explore the data still stand strongly.\n\nUsing real data with the same constraints as this challenge could still open the door to obtain insights into the following questions:\n\n1. Is the payment_amount affecting the time it takes to get paid?\n2. Are some notification channels quicker in the time it takes us to get paid?\n3. And finally how much are we getting paid by each notification channel type\n\nBesides having the holistic insight of \"this channel is better than all of the others\". It would not be surprising to find that certain notification types such as text work better for recently invoiced patients. Whereas other more formal methods such as certified mail can be more successful bringing in payments for invoices that have been long overdue.\n\n---\n\n Personally, I had fun working a bit more on this.\n It's something that could not be done in a standard technical interview, and I took\n the liberty of making this an exercise of my data science skills.\n I really hope this is useful or that you get the chance to run these computations on real data.\n\n I look forward to hearing back from you!\n\n - Josué Alexander Ibarra\n\n josue@elninja.com\n \n---"
},
{
"metadata": {},
"cell_type": "markdown",
"source": " MIT License\n\n Copyright (c) 2018 Josué Alexander Ibarra\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE."
}
],
"metadata": {
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"language_info": {
"name": "python",
"version": "3.6.4",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment