def date_pair(dates): """日期配对生成器 将日期序列进行配对生成当前日期及其之后的日期配对信息,同时保留最大长度的日期长度,不能配 对的信息以 None 补齐 Args: ------- dates: list,日期序列数据 Examples: ------- >>> dates = ['2020-12', '2021-01', '2021-02'] >>> for date1, date2 in date_pair(dates): >>> print(date1, date2) 2020-12 2020-12 2020-12 2021-01 2020-12 2021-02 2021-01 2021-01 2021-01 2021-02 None None 2021-02 2021-02 None None None None """ dates = sorted(dates) for index in range(len(dates)): for elem in dates[index:]: yield dates[index], elem # 优选补齐当前日期下的信息 for _ in range(index): yield None, None
def extract_monthly_rention(data, dates, groups, padding="-%", full="100%", ucol="user_id"): """计算月度用户留存率 计算各月用户的留存率 Args: ------ data: pd.DataFrame, 用户数据,包括发生交互的时间戳信息 dates: list, 需要统计的时间列表,各个元素为需要统计的时间信息 groups: dict,对需要统计的时间信息进行 GROUP BY 之后,生成的字典信息 padding: str,用于填充需要补齐的时间留存率,默认为 '-%' full: str, 用于填充当前月份下的留存率,默认为 '100%' ucol: str, 表示的是 data 数据中的用户字段名称 """ result = [] login_user = set() # 登陆用户 date = None element = [] for index, (current, query) in enumerate(date_pair(dates)): # 更新在新日期下的新用户,以及合并已登陆用户 if date is None or (current is not None and date != current): new_user = set(data.loc[groups[current], ucol].unique()) - login_user login_user |= set(data.loc[groups[current], ucol].unique()) date = current
# 如果 element 有元素时,更新结果数据 if element: result.append(element) element = []
# 如果当前日期和查询日期相同,是当前月份留存 if query is not None and current == query: element.append(full)
# 如果是补齐的日期对信息,直接填充数据值 elif query is None: element.append(padding) # 其他情况时,直接查询数据计算留存 else: active = new_user & set(data.loc[groups[query], ucol].unique()) element.append("{0:.2f}%".format(len(active) / len(new_user) * 100)) else: result.append(element) # 生成报告 columns = [f"留存率_{i}" for i in range(len(dates))] report = pd.DataFrame(data=result, columns=columns, index=dates) return report