【问题标题】:Funnel analysis calculation, how would you calculate a funnel?漏斗分析计算,你会如何计算漏斗?
【发布时间】:2012-05-20 22:54:36
【问题描述】:

假设我跟踪用户在网站上发生的“事件”,事件可能是这样的:

  1. 查看主页
  2. 已将商品添加到购物车
  3. 结帐
  4. 已付款

现在这些事件中的每一个都存储在一个数据库中,例如:

session_id event_name created_date ..

所以现在我想构建一个报告来显示一个特定的漏斗,我将定义如下:

Step#1   event_n
Step#2   event_n2
Step#3   event_n3

所以这个特定的漏斗有 3 个步骤,每个步骤都与任何事件相关联。

鉴于我拥有的上述数据,我现在如何为此构建报告?

注意:只是想清楚一点,我希望能够创建我定义的任何渠道,并能够为其创建报​​告。

我能想到的最基本的方法是:

  1. 获取数据库中每个步骤的所有事件
  2. 第 1 步将是,x% 的人执行 event_n
  3. 现在我必须查询也执行了步骤#1 的步骤#2 的数据,并显示 %
  4. 与 #3 相同,但对于 step#3 与 step#2 的条件

我很好奇这些在线服务如何在托管的 Saas 环境中显示这些类型的报告。 map-reduce 是否以某种方式使这变得更容易?

【问题讨论】:

  • 如果您认为这样更容易,您可以在 reducer 中获取每个会话 ID 的所有事件。

标签: java math hadoop mapreduce bigdata


【解决方案1】:

首先给出答案,使用标准 SQL,给出您的假设: 有一个布局简单的表 EVENTS:

EVENTS
-----------------------------
SESION_ID , EVENT_NAME , TMST

获取在某个时间执行第 1 步的会话:

-- QUERY 1
SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event1' GROUP BY SESSION_ID;

在这里,我假设 event1 可以在每个会话中发生不止一次。结果是在某个时间展示了 event1 的唯一会话列表。

为了得到step2和step3,我也可以这样做:

-- QUERY 2
SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event2' GROUP BY SESSION_ID;
-- QUERY 3
SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event3' GROUP BY SESSION_ID;

现在,您要选择按顺序执行 step1、step2 和 step3 的会话。 更准确地说,您需要计算执行第 1 步的会话数,然后计算执行第 2 步的会话数,然后计算执行第 3 步的会话数。 基本上我们只需要将上述 3 个查询与 left join 结合起来,就可以列出进入漏斗的会话以及它们执行了哪些步骤:

-- FUNNEL FOR S1/S2/S3
SELECT 
  SESSION_ID, 
  Q1.TMST IS NOT NULL AS PERFORMED_STEP1,
  Q2.TMST IS NOT NULL AS PERFORMED_STEP2,
  Q3.TMST IS NOT NULL AS PERFORMED_STEP3
FROM
  -- QUERY 1
  (SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event1' GROUP BY SESSION_ID) AS Q1,
LEFT JOIN
  -- QUERY 2
  (SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event2' GROUP BY SESSION_ID) AS Q2,
LEFT JOIN
  -- QUERY 3
  (SELECT SESSION_ID,MIN(TMST) FROM EVENTS WHERE EVENT_NAME='event2' GROUP BY SESSION_ID) AS Q3
-- Q2 & Q3
ON Q2.SESSION_ID=Q3.SESSION_ID AND Q2.TMST<Q3.TMST
-- Q1 & Q2
ON Q1.SESSION_ID=Q2.SESSION_ID AND Q1.TMST<Q2.TMST

结果是在第 1 步进入渠道的唯一会话列表,并且可能已继续到第 2 步和第 3 步...例如:

SESSION_ID_1,TRUE,TRUE,TRUE
SESSION_ID_2,TRUE,TRUE,FALSE
SESSION_ID_3,TRUE,FALSE,FALSE
...

现在我们只需要计算一些统计数据,例如:

SELECT
  STEP1_COUNT,
  STEP1_COUNT-STEP2_COUNT AS EXIT_AFTER_STEP1,
  STEP2_COUNT*100.0/STEP1_COUNT AS PERCENTAGE_TO_STEP2,
  STEP2_COUNT-STEP3_COUNT AS EXIT_AFTER_STEP2,
  STEP3_COUNT*100.0/STEP2_COUNT AS PERCENTAGE_TO_STEP3,
  STEP3_COUNT*100.0/STEP1_COUNT AS COMPLETION_RATE
FROM
(-- QUERY TO COUNT session at each step
  SELECT
    SUM(CASE WHEN PERFORMED_STEP1 THEN 1 ELSE 0 END) AS STEP1_COUNT,
    SUM(CASE WHEN PERFORMED_STEP2 THEN 1 ELSE 0 END) AS STEP2_COUNT,
    SUM(CASE WHEN PERFORMED_STEP3 THEN 1 ELSE 0 END) AS STEP3_COUNT
  FROM
    [... insert the funnel query here ...]
) AS COMPUTE_STEPS

等等!

现在开始讨论。 第一点,鉴于您采用“设置”(或功能)思维方式而不是“程序”方法,结果非常简单。不要将数据库可视化为具有列和行的固定表的集合......这就是它的实现方式,但它不是您与之交互的方式。都是布景,你可以按照自己的方式安排布景!

第二点,如果您使用的是 MPP 数据库,查询将自动优化为并行运行。您甚至不需要对查询进行不同的编程,使用 map-reduce 或其他什么...我在我的测试数据集上运行了相同的查询,其中包含超过 1 亿个事件并在几秒钟内获得结果。

最后但同样重要的是,查询开启了无限的可能性。只需按推荐人、关键字、着陆页、用户信息对结果进行分组,然后分析哪个提供了最佳转化率!

【讨论】:

  • 我认为这个查询可能有问题,例如如果我想知道谁做了:E1、E2、E3 并且我与 E2、E1、E2、E3 有一个会话我相信上面的查询会失败(因为它只考虑事件的第一次发生)
  • 其实不是。初始查询中的唯一约束是 E1,E1,,E2,*,E3... 可以强制执行严格的事件序列 E1=>E2=>E3 但是这将需要首先计算会话中的事件(例如,可以使用窗口函数轻松完成)
【解决方案2】:

您思考这个问题的方式的核心问题是您在思考 SQL/表类型模型。每个事件都是一个记录。 NoSQL 技术的优点之一(您对此有所了解)是您可以自然地将记录存储为每个记录一个会话。以基于会话的方式存储数据后,您可以编写一个例程来检查该会话是否符合该模式。不需要做连接或任何事情,只需在会话中的事务列表上循环。这就是半结构化数据的力量。

如果您将会话存储在一起会怎样?然后,您所要做的就是遍历每个会话并查看它是否匹配。

在我看来,这是一个非常棒的 HBase 用例。

使用 HBase,您将会话 ID 存储为行键,然后将每个事件存储为值,并将时间戳作为列限定符。剩下的就是按会话 ID 分组在一起的数据,然后按时间排序。

好的,现在您想弄清楚有多少会话执行了行为 1,然后是 2,然后是 3。您对这些数据运行 MapReduce 作业。 MapReduce 作业将为每个行键/值对提供一个会话。在数据上编写一个循环以检查它是否与模式匹配。如果它确实计数+ 1,如果不是,则不要。


无需全力以赴地使用 HBase,您就可以使用 MapReduce 对静止的无组织数据进行会话处理。按会话 ID 分组,然后在 reducer 中,您将与该会话关联的所有事件组合在一起。现在,您基本上是在使用 HBase 的地方,您可以在 reducer 中编写一个检查模式的方法。


如果您没有大量可笑的数据,HBase 可能会过大。在这种情况下,任何可以分层存储数据的数据库都会很好。 MongoDB、Cassandra、Redis 都会浮现在脑海中,各有优缺点。

【讨论】:

  • 不确定我是否清楚,但我想要的是让用户能够定义一个漏斗(每一步的步骤和匹配事件),并能够查看历史数据的报告.我想这意味着我必须运行批处理作业才能将旧数据拉入给定的数据存储/结构中,对吧?没有神奇的方法可以解决这个问题吗?
  • 我刚刚在 hbase 上阅读,我喜欢如何以这种分组方式存储相关数据等。不过,我该如何做与 mongodb 类似的事情呢? (此时 hbase 对我来说可能太多了)
  • 是的,您必须编写某种流程将它们组合在一起,或者如果您使用的是存储此类数据的数据存储,您只需修改记录即可。如果您是在做用户而不是会话,只需按用户分组而不是会话 ID。
  • 对于 MongoDB,您可以很容易地将列表存储为 json。我想每个用户都会是一个记录并有一个操作列表。不过,我不是专家,也不是 MongoDB。
【解决方案3】:

我最近发布了一个开源 Hive UDF 来执行此操作:hive-funnel-udf

这种漏斗分析任务使用起来非常简单,只需编写 Hive,无需编写自定义 Java MapReduce 代码。

这仅在您使用 Hive/Hadoop 存储和查询数据时才有效。

【讨论】:

  • 请不要发帖duplicate answers。相反,请考虑其他可以帮助未来用户找到所需答案的操作,如链接帖子中所述。
猜你喜欢
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 2013-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多