计算保留(或查找一个集合中的一个记录是否存在于另一个记录中)

时间:2013-06-11 18:28:39

标签: sql r

我正在使用SQL从SQL Server获取数据并在R中处理它。我可以用任何一个来解决我的问题。

这是我的数据:

structure(list(id = c(1, 2, 3, 1, 2), FY = c(2010, 2008, 2009, 2011, 2009), sales = c(100, 200, 300, 400, 500)), .Names = c("id", "FY", "sales"), row.names = c(NA, -5L), class = "data.frame")

我称之为测试

 id FY   sales
 1 2010   100
 2 2008   200
 3 2009   300
 1 2011   400
 2 2009   500
编辑:我想找到的是客户保留,即谁在2008年和2009年购买;谁在2009年和2010年购买;谁在2010年和2011年购买。

最终结果网格将在明年保留客户的年份中放置1或非空值。

我想要获得的最终结果将如下所示:

id 2008 2009 2010 2011
1               1     
2     1     

使用这种类型的表格,我可以计算每年的保留百分比。

现在,我可以编写各种CASE语句和子查询来创建这样的网格,但是我的实际数据已超过10年,而且我不愿意多年来硬编码。也许,一旦数据为R,在cast中执行此操作会更容易,但我很难对此进行编码。

3 个答案:

答案 0 :(得分:3)

tbl <- xtabs( ~ id+FY, data=test)  #......
tbl

所以这是积极的销售,你想要连续几年是1的那些:

 0+( tbl[ , -1]==1 & tbl[,-ncol(tbl)]==1)
#-------
   FY
id  2009 2010 2011
  1    0    0    1
  2    1    0    0
  3    0    0    0

逻辑运算将生成TRUE和FALSE矩阵,并将0添加到逻辑将其转换为0/1。我注意到这个结果的不同之处并认为它更容易接受。您的标签可能表明我们可以看到未来。如果您不同意,您可以使用启示,因为列标签取自第一个参数:

0+( tbl[,-ncol(tbl)]==1 &tbl[ , -1]==1)

答案 1 :(得分:0)

以下是进行数据透视的一种方法(使用聚合):

select id,
       p2008 * p2009 as [2008],
       p2009 * p2010 as [2009],
       p2010 * p2011 as [2010],
       p2011 * p2012 as [2011]
from (select t.*,
             (case when FY = 2008 then 1 end) as p2008,
             (case when FY = 2009 then 1 end) as p2009,
             (case when FY = 2010 then 1 end) as p2010,
             (case when FY = 2011 then 1 end) as p2011,
             (case when FY = 2012 then 1 end) as p2012
      from test t
     ) t
group by id

如果您对进行此类保留分析感兴趣,您应该了解生存分析,尤其是复发事件分析。

答案 2 :(得分:0)

我自己丑陋的黑客:

    require('sqldf')
    require('plyr')

    test_returning <- ddply(test, .(FY), function(df) { 
      cur_fy <- unique(df$FY)
      q1 <- 'select count(1) as returning from df'
      q2 <- paste('where exists (select 0 from test t where t.id = df.id and t.FY = ', cur_fy + 1, ")", sep = " ")
      qry <- paste(q1, q2, sep = " ")
      sqldf(qry)
    })

    test_total <- ddply(test, .(FY), summarize, total = length(id))
    test_retention <- merge(test_returning, test_total, all.y = TRUE)
    test_retention$retpct <- with(test_retention, returning/total)