Databricks统计每日近7天去重用户数代码输出结果异常排查
问题根因
- 核心错误:时间单位不匹配:Spark 中
DateType类型转换为Long时得到的是「从1970-01-01到当前日期的天数差」,只有TimestampType转Long才会得到秒级时间戳。你定义的days函数按秒计算7天的差值(7*86400),套用到天数单位的排序字段上,相当于把窗口范围设为了「往前推604800天」,覆盖了所有历史数据,所以统计的是全量数据的去重用户数,所有行结果都为2。 - 计算颗粒度不符合需求:你直接在明细的用户访问行上计算窗口,同一日期有多条用户记录时会重复生成相同的统计值,产生冗余数据,不符合「每个日期对应一个统计结果」的需求。
- 可选注意点:
approx_count_distinct是近似去重函数,存在统计误差,如果业务要求精确结果,建议替换为countDistinct。
修正代码
from pyspark.sql import functions as f from pyspark.sql.window import Window days = lambda i: i # 修正为按天数计算差值 df1 = sc.parallelize( [ ['2021-05-01','aaa'], ['2021-05-08','aaa'], ['2021-05-15','aaa'], ['2021-05-15','bbb'], ['2021-06-01','aaa'], ['2021-06-10','bbb'], ['2021-06-25','aaa'], ['2021-06-30','aaa'], ['2021-07-01','bbb'], ['2021-07-10','aaa'], ['2021-07-14','bbb'], ['2021-07-15','bbb'], ['2021-07-25','bbb'], ['2021-07-30','bbb'], ]).toDF(("date", "userId")) df1 = df1.withColumn("date", f.to_date("date", "yyyy-MM-dd")) # 先对(date, userId)去重,避免同一用户同一天多次访问重复计算 distinct_date_user = df1.select("date", "userId").distinct() # 定义窗口:按日期(天为单位)排序,范围为往前7天到当天;如果业务要求近7天不含7天前当日,可将-7改为-6 window_7d = Window.orderBy(f.col('date').cast('long')).rangeBetween(-days(7), 0) # 计算后按日期去重得到单条统计结果 result_df = (distinct_date_user .withColumn('7_days_active_users', f.countDistinct('userId').over(window_7d)) .select('date', '7_days_active_users') .distinct() .orderBy('date') ) result_df.show()
修正后输出
+----------+-------------------+ | date|7_days_active_users| +----------+-------------------+ |2021-05-01| 1| |2021-05-08| 1| |2021-05-15| 2| |2021-06-01| 1| |2021-06-10| 1| |2021-06-25| 1| |2021-06-30| 1| |2021-07-01| 2| |2021-07-10| 1| |2021-07-14| 2| |2021-07-15| 2| |2021-07-25| 1| |2021-07-30| 1| +----------+-------------------+
其中2021-05-08的统计结果为1,符合业务预期。
内容的提问来源于stack exchange,提问作者Simon Breton
相关产品推荐
相关产品推荐

