In [1]:
from datetime import datetime
import pandas as pd
import numpy as np

Some intuition


In [141]:
# Randomly generated customer IDs and purchased months
df = pd.DataFrame([
    {'customer': customer_id, 'month': month}
    for month, customer_id in
    zip(np.random.randint(1, 13, 100), np.random.randint(1, 31, 100))
])

In [142]:
cohort = df.sort_values(by='month').groupby('customer')['month'].first()
cohort = cohort.to_frame(name='cohort')

In [143]:
cohort.head()


Out[143]:
cohort
customer
1 6
2 7
3 12
4 7
5 8

In [144]:
df_cohort = pd.merge(df, cohort, right_index=True, left_on='customer')
df_cohort.head()


Out[144]:
customer month cohort
0 15 12 3
30 15 5 3
46 15 3 3
48 15 11 3
1 22 5 4

In [145]:
df_cohort.groupby('cohort').size()


Out[145]:
cohort
1      7
2     36
3     11
4     16
5      2
6      9
7     14
8      4
12     1
dtype: int64

In [202]:
def cohort_generator(df, group_by, customer_column, period_column):
    results = []
    
    for cohort, data in df.groupby(group_by):
        cohort_size = data[customer_column].nunique()
        unique_periods = sorted(df[period_column].unique())

        for period in unique_periods:
            unique = data[data[period_column] >= period][customer_column].nunique()
            if period >= cohort and unique >= 0:
                retention = unique / cohort_size
                results.append({'cohort': cohort,
                               'period': period,
                               'retention': retention})
            
    c = pd.DataFrame.from_records(results)
    return c.pivot(index='period', columns='cohort')

In [163]:
cohort_generator(df_cohort, 'cohort', 'customer', 'month')


Out[163]:
retention
cohort 1 2 3 4 5 6 7 8 12
period
1 1.0 NaN NaN NaN NaN NaN NaN NaN NaN
2 1.0 1.000 NaN NaN NaN NaN NaN NaN NaN
3 1.0 1.000 1.000000 NaN NaN NaN NaN NaN NaN
4 1.0 1.000 1.000000 1.0 NaN NaN NaN NaN NaN
5 1.0 0.875 1.000000 1.0 1.0 NaN NaN NaN NaN
6 1.0 0.875 1.000000 1.0 1.0 1.000000 NaN NaN NaN
7 1.0 0.875 1.000000 1.0 1.0 0.666667 1.0 NaN NaN
8 1.0 0.750 1.000000 1.0 0.0 0.666667 0.8 1.0 NaN
9 1.0 0.750 1.000000 0.6 0.0 0.666667 0.8 0.5 NaN
10 0.0 0.750 1.000000 0.4 0.0 0.666667 0.6 0.5 NaN
11 0.0 0.750 0.333333 0.2 0.0 0.333333 0.2 0.5 NaN
12 0.0 0.625 0.333333 0.2 0.0 0.000000 0.2 0.0 1.0

Actual data


In [7]:
orders = pd.read_csv('orders.csv')[['customer_id', 'created_at']]

In [8]:
orders['created_at'] = pd.to_datetime(orders['created_at'])

In [226]:
orders.head()


Out[226]:
customer_id created_at
0 1 2013-04-07 12:00:00
1 2 2013-04-04 12:00:00
2 4 2013-04-06 12:00:00
3 3 2013-04-08 12:00:00
4 10 2013-04-04 12:00:00

In [9]:
%%time
# Extract year and date only
orders['created_at_month_year'] = orders['created_at'].map(lambda x: x.strftime('%Y-%m'))


CPU times: user 27.1 s, sys: 441 ms, total: 27.6 s
Wall time: 27.6 s

In [228]:
orders.head()


Out[228]:
customer_id created_at created_at_month_year
0 1 2013-04-07 12:00:00 2013-04
1 2 2013-04-04 12:00:00 2013-04
2 4 2013-04-06 12:00:00 2013-04
3 3 2013-04-08 12:00:00 2013-04
4 10 2013-04-04 12:00:00 2013-04

In [10]:
%%time
# Assign a cohort to each 
cohort = orders.sort_values(by='created_at_month_year').groupby('customer_id')['created_at_month_year'].first()
cohort = cohort.to_frame(name='cohort')


CPU times: user 4.43 s, sys: 213 ms, total: 4.65 s
Wall time: 4.66 s

In [230]:
cohort.head()


Out[230]:
cohort
customer_id
1 2013-04
2 2013-04
3 2013-04
4 2013-04
5 2013-04

In [11]:
%%time
df_cohort = pd.merge(orders[['customer_id',
                             'created_at_month_year']],
                     cohort, right_index=True, left_on='customer_id')
assert len(orders) == len(df_cohort)


CPU times: user 1.44 s, sys: 165 ms, total: 1.61 s
Wall time: 1.61 s

In [232]:
df_cohort.head()


Out[232]:
customer_id created_at_month_year cohort
0 1 2013-04 2013-04
287846 1 2013-10 2013-04
1646408 1 2015-03 2013-04
1871621 1 2015-04 2013-04
1 2 2013-04 2013-04

In [239]:
# Number of unique customers in each cohort
df_cohort.groupby('cohort').agg({'customer_id': pd.Series.nunique}).head()


Out[239]:
customer_id
cohort
2013-04 28874
2013-05 30851
2013-06 29953
2013-07 31013
2013-08 30851

In [235]:
%%time
cohort = cohort_generator(df_cohort, 'cohort', 'customer_id', 'created_at_month_year')


CPU times: user 46.3 s, sys: 960 ms, total: 47.2 s
Wall time: 47.3 s

In [236]:
cohort


Out[236]:
retention
cohort 2013-04 2013-05 2013-06 2013-07 2013-08 2013-09 2013-10 2013-11 2013-12 2014-01 ... 2015-07 2015-08 2015-09 2015-10 2015-11 2015-12 2016-01 2016-02 2016-03 2016-04
period
2013-04 1.000000 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-05 0.986839 1.000000 NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-06 0.985212 0.984603 1.000000 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-07 0.983480 0.982821 0.984976 1.000000 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-08 0.981852 0.980390 0.983107 0.982781 1.000000 NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-09 0.979497 0.977829 0.980937 0.980943 0.979450 1.000000 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-10 0.977627 0.975236 0.978299 0.978041 0.976532 0.977918 1.000000 NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-11 0.974510 0.972221 0.975628 0.975333 0.973777 0.975208 0.973073 1.000000 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-12 0.971220 0.968785 0.972557 0.972302 0.970017 0.972231 0.969655 0.969568 1.000000 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-01 0.967341 0.964896 0.968718 0.967949 0.966711 0.968617 0.965334 0.966030 0.966098 1.000000 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-02 0.962769 0.960844 0.964144 0.963435 0.961849 0.964067 0.961045 0.961793 0.962041 0.962968 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-03 0.957886 0.955723 0.959370 0.958727 0.957376 0.959684 0.956530 0.956921 0.957437 0.958675 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-04 0.952137 0.949596 0.953627 0.952858 0.951314 0.954866 0.950919 0.951782 0.951706 0.953774 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-05 0.945903 0.943503 0.947151 0.946603 0.944605 0.948175 0.944212 0.945375 0.945879 0.948552 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-06 0.939046 0.936761 0.939205 0.939832 0.937150 0.940781 0.936988 0.939035 0.938506 0.941408 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-07 0.931184 0.929954 0.931459 0.931835 0.929727 0.933655 0.930184 0.931127 0.930232 0.933944 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-08 0.921625 0.920586 0.922645 0.923322 0.921721 0.923751 0.920832 0.921750 0.920959 0.924558 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-09 0.910646 0.911283 0.913197 0.913714 0.911316 0.914082 0.909965 0.911205 0.911719 0.914531 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-10 0.899598 0.899809 0.901679 0.902686 0.901462 0.902305 0.898388 0.900928 0.901900 0.902390 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-11 0.886542 0.886551 0.888993 0.889466 0.888723 0.889257 0.884973 0.888147 0.888377 0.889256 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-12 0.871788 0.873391 0.874003 0.874085 0.873489 0.874368 0.870622 0.874566 0.873567 0.874487 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-01 0.854748 0.857606 0.855874 0.856544 0.856666 0.857372 0.853370 0.857782 0.858789 0.857957 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-02 0.835215 0.839033 0.836544 0.837584 0.837023 0.838201 0.834892 0.837193 0.838796 0.838993 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-03 0.815717 0.820135 0.818048 0.818721 0.815727 0.819365 0.814995 0.818907 0.820058 0.818907 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-04 0.789915 0.794431 0.793744 0.790894 0.789893 0.793971 0.788617 0.795482 0.794623 0.793631 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-05 0.761931 0.767593 0.766735 0.763905 0.762925 0.768443 0.762722 0.768353 0.768352 0.768196 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-06 0.731662 0.736216 0.736120 0.733434 0.731743 0.737696 0.733634 0.736185 0.739375 0.736770 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-07 0.697583 0.701890 0.702133 0.700932 0.698292 0.704975 0.700322 0.703550 0.703413 0.702749 ... 1.000000 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-08 0.656785 0.664452 0.661570 0.659369 0.658131 0.665763 0.661045 0.664576 0.663587 0.663826 ... 0.666011 1.000000 NaN NaN NaN NaN NaN NaN NaN NaN
2015-09 0.609891 0.620563 0.615297 0.614903 0.614956 0.619827 0.617285 0.617092 0.619092 0.619394 ... 0.621012 0.619802 1.000000 NaN NaN NaN NaN NaN NaN NaN
2015-10 0.562721 0.574309 0.565686 0.567439 0.565363 0.568169 0.569526 0.568206 0.572376 0.571790 ... 0.572627 0.573840 0.566545 1.000000 NaN NaN NaN NaN NaN NaN
2015-11 0.505749 0.517033 0.512102 0.511398 0.509384 0.510857 0.513157 0.508609 0.516388 0.516242 ... 0.513564 0.516765 0.511119 0.505937 1.000000 NaN NaN NaN NaN NaN
2015-12 0.443860 0.456744 0.448536 0.448715 0.447960 0.448526 0.451048 0.448412 0.455634 0.454671 ... 0.449695 0.454955 0.448469 0.447879 0.450010 1.000000 NaN NaN NaN NaN
2016-01 0.371580 0.382289 0.377291 0.374424 0.376681 0.376292 0.377556 0.377703 0.381777 0.378524 ... 0.377633 0.383000 0.379660 0.374575 0.379730 0.379674 1.000000 NaN NaN NaN
2016-02 0.288460 0.299374 0.296431 0.291878 0.292146 0.294757 0.297581 0.295816 0.296072 0.296771 ... 0.292345 0.299095 0.297437 0.292509 0.297504 0.296874 0.288980 1.000000 NaN NaN
2016-03 0.203817 0.211144 0.209061 0.203753 0.207740 0.207300 0.211448 0.208789 0.206439 0.210021 ... 0.206413 0.209908 0.209387 0.206368 0.207836 0.209649 0.207388 0.207600 1.000000 NaN
2016-04 0.099155 0.102622 0.104364 0.100055 0.101780 0.103014 0.104063 0.105779 0.102189 0.104754 ... 0.103093 0.104455 0.102264 0.102574 0.103985 0.104243 0.105098 0.103783 0.096181 1.0

37 rows × 37 columns

Revenue


In [2]:
orders = pd.read_csv('orders.csv')[['id', 'customer_id', 'created_at']]
orders.head()


Out[2]:
id customer_id created_at
0 1 1 2013-04-07 12:00:00
1 2 2 2013-04-04 12:00:00
2 3 4 2013-04-06 12:00:00
3 4 3 2013-04-08 12:00:00
4 5 10 2013-04-04 12:00:00

In [3]:
items = pd.read_csv('order_items.csv')[['order_id', 'product_id', 'quantity']]
items.head()


Out[3]:
order_id product_id quantity
0 1 1 1
1 2 6 1
2 3 2 1
3 4 1 1
4 5 1 1

In [4]:
# No order has more than one item
items.order_id.value_counts().head()


Out[4]:
2047      1
650647    1
531881    1
529832    1
552359    1
Name: order_id, dtype: int64

In [5]:
products = pd.read_csv('products.csv')[['id', 'price']]
products.head()


Out[5]:
id price
0 1 8999
1 2 4999
2 3 12999
3 4 9999
4 5 7999

In [6]:
items_products = pd.merge(items,
                          products,
                          how='left',
                          left_on='product_id',
                          right_on='id')[['order_id', 'quantity', 'price']]
items_products['total'] = items_products.quantity * items_products.price
items_products = items_products[['order_id', 'total']]
items_products.head()


Out[6]:
order_id total
0 1 8999
1 2 7999
2 3 4999
3 4 8999
4 5 8999

In [7]:
combined = pd.merge(orders, items_products, how='left', left_on='id', right_on='order_id')
assert len(orders) == len(combined)
combined = combined[['customer_id', 'created_at', 'total']]
combined.head()


Out[7]:
customer_id created_at total
0 1 2013-04-07 12:00:00 8999.0
1 2 2013-04-04 12:00:00 7999.0
2 4 2013-04-06 12:00:00 4999.0
3 3 2013-04-08 12:00:00 8999.0
4 10 2013-04-04 12:00:00 8999.0

In [8]:
%%time
combined['created_at'] = pd.to_datetime(combined['created_at'])


CPU times: user 804 ms, sys: 56.1 ms, total: 860 ms
Wall time: 857 ms

In [9]:
%%time
# Extract year and date only
combined['created_at_month_year'] = combined['created_at'].map(lambda x: x.strftime('%Y-%m'))


CPU times: user 27.6 s, sys: 488 ms, total: 28.1 s
Wall time: 28.1 s

In [10]:
%%time
# Assign a cohort to each 
cohort = combined.sort_values(by='created_at_month_year').groupby('customer_id')['created_at_month_year'].first()
cohort = cohort.to_frame(name='cohort')


CPU times: user 4.46 s, sys: 198 ms, total: 4.66 s
Wall time: 4.66 s

In [11]:
cohort.head()


Out[11]:
cohort
customer_id
1 2013-04
2 2013-04
3 2013-04
4 2013-04
5 2013-04

In [12]:
%%time
df_cohort = pd.merge(combined[['customer_id',
                             'created_at_month_year', 'total']],
                     cohort, right_index=True, left_on='customer_id')
assert len(orders) == len(df_cohort)


CPU times: user 1.5 s, sys: 189 ms, total: 1.69 s
Wall time: 1.69 s

In [13]:
df_cohort.head()


Out[13]:
customer_id created_at_month_year total cohort
0 1 2013-04 8999.0 2013-04
287846 1 2013-10 9999.0 2013-04
1646408 1 2015-03 NaN 2013-04
1871621 1 2015-04 NaN 2013-04
1 2 2013-04 7999.0 2013-04

In [14]:
revenue = df_cohort.groupby(['cohort', 'created_at_month_year']).agg({'total': pd.np.sum})
revenue.head()


Out[14]:
total
cohort created_at_month_year
2013-04 2013-04 216899526.0
2013-05 25514894.0
2013-06 26227225.0
2013-07 26419512.0
2013-08 27238296.0

In [58]:
revenue.reset_index().rename(columns={
    'created_at_month_year': 'period',
    'total': 'revenue'
}).pivot(index='cohort', columns='period')


Out[58]:
revenue
period 2013-04 2013-05 2013-06 2013-07 2013-08 2013-09 2013-10 2013-11 2013-12 2014-01 ... 2015-07 2015-08 2015-09 2015-10 2015-11 2015-12 2016-01 2016-02 2016-03 2016-04
cohort
2013-04 216899526.0 25514894.0 26227225.0 26419512.0 27238296.0 26811655.0 26953020.0 26306898.0 27117914.0 28049071.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-05 NaN 232107922.0 26940399.0 28880927.0 28575980.0 28521738.0 28876224.0 27650180.0 29597311.0 28330289.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-06 NaN NaN 226205043.0 27377372.0 27899470.0 26903092.0 27643548.0 26991132.0 28005795.0 28217347.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-07 NaN NaN NaN 234239087.0 27902357.0 27995429.0 29258999.0 28589001.0 28323543.0 29144705.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-08 NaN NaN NaN NaN 232414240.0 26891138.0 28408414.0 28407545.0 29164234.0 28222726.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-09 NaN NaN NaN NaN NaN 225802212.0 26460161.0 26729968.0 27601337.0 26987381.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-10 NaN NaN NaN NaN NaN NaN 234676292.0 26828754.0 28158126.0 29055815.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-11 NaN NaN NaN NaN NaN NaN NaN 225629435.0 26484060.0 28729198.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-12 NaN NaN NaN NaN NaN NaN NaN NaN 233756503.0 27495206.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-01 NaN NaN NaN NaN NaN NaN NaN NaN NaN 235037977.0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-03 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-04 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-05 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-06 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-07 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-08 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-09 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-10 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-11 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2014-12 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-01 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-03 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-04 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-05 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-06 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-07 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-08 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-09 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-10 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-11 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2015-12 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2016-01 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2016-02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2016-03 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2016-04 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

37 rows × 37 columns

Total revenue over the upcoming periods


In [19]:
def cohort_revenue_generator(df):
    results = []
    
    for cohort, data in df.groupby('cohort'):
        cohort_size = data['customer_id'].nunique()
        unique_periods = sorted(df['created_at_month_year'].unique())

        for period in unique_periods:
            revenue = data[data['created_at_month_year'] >= period].total.sum()
            if period >= cohort and revenue >= 0:
                results.append({'cohort': cohort,
                               'period': period,
                               'revenue': revenue})
            
    c = pd.DataFrame.from_records(results)
    return c.pivot(index='period', columns='cohort')

In [20]:
cohort_revenue_generator(df_cohort)


Out[20]:
revenue
cohort 2013-04 2013-05 2013-06 2013-07 2013-08 2013-09 2013-10 2013-11 2013-12 2014-01 2014-02 2014-03 2014-04
period
2013-04 528091201.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-05 311191675.0 536370347.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-06 285676781.0 304262425.0 494393172.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-07 259449556.0 277322026.0 268188129.0 481365898.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2013-08 233030044.0 248441099.0 240810757.0 247126811.0 451340765.0 NaN NaN NaN NaN NaN NaN NaN NaN
2013-09 205791748.0 219865119.0 212911287.0 219224454.0 218926525.0 406975229.0 NaN NaN NaN NaN NaN NaN NaN
2013-10 178980093.0 191343381.0 186008195.0 191229025.0 192035387.0 181173017.0 394951253.0 NaN NaN NaN NaN NaN NaN
2013-11 152027073.0 162467157.0 158364647.0 161970026.0 163626973.0 154712856.0 160274961.0 355623353.0 NaN NaN NaN NaN NaN
2013-12 125720175.0 134816977.0 131373515.0 133381025.0 135219428.0 127982888.0 133446207.0 129993918.0 338833037.0 NaN NaN NaN NaN
2014-01 98602261.0 105219666.0 103367720.0 105057482.0 106055194.0 100381551.0 105288081.0 103509858.0 105076534.0 310986455.0 NaN NaN NaN
2014-02 70553190.0 76889377.0 75150373.0 75912777.0 77832468.0 73394170.0 76232266.0 74780660.0 77581328.0 75948478.0 251515540.0 NaN NaN
2014-03 46638266.0 51224884.0 49225624.0 49913547.0 51173281.0 48320699.0 50535412.0 49003398.0 52034914.0 50848134.0 43451855.0 265138004.0 NaN
2014-04 19427875.0 21207372.0 20234417.0 20360186.0 20877614.0 19959468.0 20889916.0 20161145.0 21404055.0 20888291.0 18578224.0 21601313.0 187361476.0

Further investigation


In [36]:
orders = pd.read_csv('/Users/amir.ziai/Downloads/data/orders.csv')
orders[orders.id == 1]


Out[36]:
id customer_id mc_cid created_at updated_at
0 1 1 aadf87qef-2013-04-01 2013-04-07 12:00:00 2016-04-28 21:15:27

In [37]:
items = pd.read_csv('/Users/amir.ziai/Downloads/data/order_items.csv')
items[items.order_id == 1]


Out[37]:
id order_id product_id quantity created_at updated_at
0 1 1 1 1 2015-04-02 12:00:00 2016-04-24 19:04:05

In [30]:
pd.read_csv('/Users/amir.ziai/Downloads/data/products.csv', nrows=10)


Out[30]:
id name category price created_at updated_at
0 1 Exotic Meats Crate food 8999 2016-04-24 19:04:05 2016-04-24 19:04:05
1 2 Sriracha Crate food 4999 2016-04-24 19:04:05 2016-04-24 19:04:05
2 3 Zombie Annihilation Crate outdoors 12999 2016-04-24 19:04:05 2016-04-24 19:04:05
3 4 Personalized Whiskey Crate glassware 9999 2016-04-24 19:04:05 2016-04-24 19:04:05
4 5 NFL Barware Crate glassware 7999 2016-04-24 19:04:05 2016-04-24 19:04:05
5 6 Retro Gamer Crate gaming 7999 2016-04-24 19:04:05 2016-04-24 19:04:05
6 7 Grill Master Crate grilling 1099 2016-04-24 19:04:05 2016-04-24 19:04:05
7 8 Personalized Growler Crate glassware 10999 2016-04-24 19:04:05 2016-04-24 19:04:05
8 9 Hot Sauce Making Kit food 5999 2016-04-24 19:04:05 2016-04-24 19:04:05
9 10 Saloon Nuts Crate food 3999 2016-04-24 19:04:05 2016-04-24 19:04:05

In [28]:
pd.read_csv('/Users/amir.ziai/Downloads/data/order_items.csv', nrows=10)


Out[28]:
id order_id product_id quantity created_at updated_at
0 1 1 1 1 2015-04-02 12:00:00 2016-04-24 19:04:05
1 2 2 6 1 2015-04-08 12:00:00 2016-04-24 19:04:05
2 3 3 2 1 2015-04-05 12:00:00 2016-04-24 19:04:05
3 4 4 1 1 2015-04-06 12:00:00 2016-04-24 19:04:05
4 5 5 1 1 2015-04-02 12:00:00 2016-04-24 19:04:05
5 6 6 7 1 2015-04-08 12:00:00 2016-04-24 19:04:05
6 7 7 4 1 2015-04-07 12:00:00 2016-04-24 19:04:05
7 8 8 4 1 2015-04-03 12:00:00 2016-04-24 19:04:05
8 9 10 2 1 2015-04-02 12:00:00 2016-04-24 19:04:05
9 10 9 9 1 2015-04-04 12:00:00 2016-04-24 19:04:05

In [27]:
pd.read_csv('/Users/amir.ziai/Downloads/data/customers.csv', nrows=10)


Out[27]:
id first_name last_name email orders_count created_at updated_at
0 1 Nigel Larson stan_crona@paucek.co NaN 2015-04-02 12:00:00 2016-04-24 19:04:05
1 2 Jessy Lynch jonas_roob@davis.io NaN 2015-04-08 12:00:00 2016-04-24 19:04:05
2 3 Ocie Davis laurel@maggioswaniawski.org NaN 2015-04-05 12:00:00 2016-04-24 19:04:05
3 4 Lemuel Hayes simone.armstrong@hodkiewicz.io NaN 2015-04-06 12:00:00 2016-04-24 19:04:05
4 5 Christophe Orn elvis@dietrich.biz NaN 2015-04-07 12:00:00 2016-04-24 19:04:05
5 6 Cathryn Cartwright thalia.fisher@langworthgibson.name NaN 2015-04-03 12:00:00 2016-04-24 19:04:05
6 7 Abner Little bart.kuphal@hirthe.org NaN 2015-04-04 12:00:00 2016-04-24 19:04:05
7 8 Jett Cummings rhoda_prosacco@cormierbergstrom.com NaN 2015-04-09 12:00:00 2016-04-24 19:04:05
8 9 Keaton Schamberger lilla@raynor.com NaN 2015-04-02 12:00:00 2016-04-24 19:04:05
9 10 Iva Morissette michale@olson.co NaN 2015-04-08 12:00:00 2016-04-24 19:04:05

In [ ]: