Es gibt mehrere Aspekte auf Ihre Frage.
Was Sie mit den Daten erstellen können müssen Sie
Es several kinds of retention sind. Der Einfachheit halber werden wir nur zwei erwähnen:
Day-N-Aufbewahrung: Wenn ein Benutzer am Tag 0 registriert ist, hat sie sich am Tag N eingeloggt? (Der Logging-Tag N + 1 beeinflusst diese Metrik nicht). Um es zu messen, müssen Sie alle Protokolle Ihrer Benutzer verfolgen.
Rolling Retention: Wenn ein Benutzer am Tag 0 registriert, hat sie sich am Tag N oder einem beliebigen Tag danach eingeloggt? (Das Anmelden am Tag N + 1 wirkt sich auf diese Metrik aus). Um es zu messen, brauchen Sie nur die letzten bekannten Logs Ihrer Benutzer.
Wenn ich Ihre Tabelle richtig verstehe, haben Sie zwei relevante Variablen, um Ihre Kohorten-Tabelle zu erstellen: Registrierungsdatum und letztes Protokoll (Besuchswoche). Die Anzahl der wöchentlichen Besuche scheint irrelevant.
Also mit diesem können Sie nur mit Option 2, rollende Retention gehen.
Wie die Tabelle bauen
Lassen Sie uns zunächst ein Dummy-Datensatz aufbauen, damit wir genug zu arbeiten und Sie können es reproduzieren:
import pandas as pd
import numpy as np
import math
import datetime as dt
np.random.seed(0) # so that we all have the same results
def random_date(start, end,p=None):
# Return a date randomly chosen between two dates
if p is None:
p = np.random.random()
return start + dt.timedelta(seconds=math.ceil(p * (end - start).days*24*3600))
n_samples = 1000 # How many users do we want ?
index = range(1,n_samples+1)
# A range of signup dates, say, one year.
end = dt.datetime.today()
from dateutil.relativedelta import relativedelta
start = end - relativedelta(years=1)
# Create the dataframe
users = pd.DataFrame(np.random.rand(n_samples),
index=index, columns=['signup_date'])
users['signup_date'] = users['signup_date'].apply(lambda x : random_date(start, end,x))
# last logs randomly distributed within 10 weeks of singing up, so that we can see the retention drop in our table
users['last_log'] = users['signup_date'].apply(lambda x : random_date(x, x + relativedelta(weeks=10)))
So, jetzt sollten wir etwas haben, das sieht wie folgt aus:
users.head()
Hier ist ein Code eine Kohorte-Tabelle zu erstellen:
### Some useful functions
def add_weeks(sourcedate,weeks):
return sourcedate + dt.timedelta(days=7*weeks)
def first_day_of_week(sourcedate):
return sourcedate - dt.timedelta(days = sourcedate.weekday())
def last_day_of_week(sourcedate):
return sourcedate + dt.timedelta(days=(6 - sourcedate.weekday()))
def retained_in_interval(users,signup_week,n_weeks,end_date):
'''
For a given list of users, returns the number of users
that signed up in the week of signup_week (the cohort)
and that are retained after n_weeks
end_date is just here to control that we do not un-necessarily fill the bottom right of the table
'''
# Define the span of the given week
cohort_start = first_day_of_week(signup_week)
cohort_end = last_day_of_week(signup_week)
if n_weeks == 0:
# If this is our first week, we just take the number of users that signed up on the given period of time
return len(users[(users['signup_date'] >= cohort_start)
& (users['signup_date'] <= cohort_end)])
elif pd.to_datetime(add_weeks(cohort_end,n_weeks)) > pd.to_datetime(end_date) :
# If adding n_weeks brings us later than the end date of the table (the bottom right of the table),
# We return some easily recognizable date (not 0 as it would cause confusion)
return float("Inf")
else:
# Otherwise, we count the number of users that signed up on the given period of time,
# and whose last known log was later than the number of weeks added (rolling retention)
return len(users[(users['signup_date'] >= cohort_start)
& (users['signup_date'] <= cohort_end)
& pd.to_datetime((users['last_log']) >= pd.to_datetime(users['signup_date'].map(lambda x: add_weeks(x,n_weeks))))
])
Damit wir die eigentliche Funktion erstellen:
def cohort_table(users,cohort_number=6,period_number=6,cohort_span='W',end_date=None):
'''
For a given dataframe of users, return a cohort table with the following parameters :
cohort_number : the number of lines of the table
period_number : the number of columns of the table
cohort_span : the span of every period of time between the cohort (D, W, M)
end_date = the date after which we stop counting the users
'''
# the last column of the table will end today :
if end_date is None:
end_date = dt.datetime.today()
# The index of the dataframe will be a list of dates ranging
dates = pd.date_range(add_weeks(end_date,-cohort_number), periods=cohort_number, freq=cohort_span)
cohort = pd.DataFrame(columns=['Sign up'])
cohort['Sign up'] = dates
# We will compute the number of retained users, column-by-column
# (There probably is a more pythonesque way of doing it)
range_dates = range(0,period_number+1)
for p in range_dates:
# Name of the column
s_p = 'Week '+str(p)
cohort[s_p] = cohort.apply(lambda row: retained_in_interval(users,row['Sign up'],p,end_date), axis=1)
cohort = cohort.set_index('Sign up')
# absolute values to percentage by dividing by the value of week 0 :
cohort = cohort.astype('float').div(cohort['Week 0'].astype('float'),axis='index')
return cohort
Jetzt können Sie es nennen, und das Ergebnis sehen:
cohort_table(users)
Hoffe, dass eshilft
Können Sie ein Beispiel Ihres Dataframe in eine gültige HTML-Tabelle einfügen? Das würde anderen erlauben, es in Pandas zu lesen, um ihre Antworten auf Ihre Frage zu QA zu geben. –