函数结果(数据帧)不是我所期望的

时间:2012-05-11 19:53:38

标签: r function dataframe plyr

我正在尝试为“粘性”定义一个函数 - 一个衡量用户参与度的业务分析指标 - 我的函数正在返回一个填充了意外数据的数据框。

stickiness <- function(tdata) {
    require(plyr)
    mau_unique <- dlply(.data = tdata,
                        .variables = "dt",
                        .fun = function(x){unique(x$username)})
    dates_char <- names(mau_unique)
    dates_vector <- as.Date(dates_char[28:(length(dates_char))],
                            format = "%Y-%m-%d")
    output_df <- data.frame(dates_vector,
                            matrix(data = 0,
                                   nrow = length(dates_char) - 27,
                                   ncol = 3))
    colnames(output_df) <- c("Date", "DAU", "MAU", "Stickiness")
    for (i in 1:length(dates_vector)) {
        dt <- dates_vector[i]
        output_df[i, "DAU"] <- length(unlist(mau_unique[[as.character(dt)]][2]))
        set28 <- unique(unlist(lapply(X = mau_unique[i:(i + 27)], FUN = "[[", 2)))  
        output_df[i, "MAU"] <- length(set28)
        output_df[i, "Stickiness"] <- output_df[i, "DAU"] / output_df[i, "MAU"]
    }
    return(output_df) 
}

返回以下内容:

         Date DAU MAU Stickiness
1  2012-04-28   1  28 0.03571429
2  2012-04-29   1  28 0.03571429
3  2012-04-30   1  28 0.03571429
4  2012-05-01   1  28 0.03571429
5  2012-05-02   1  28 0.03571429
6  2012-05-03   1  28 0.03571429
7  2012-05-04   1  28 0.03571429
8  2012-05-05   1  28 0.03571429
9  2012-05-06   1  28 0.03571429
10 2012-05-07   1  28 0.03571429

我期待以下内容:

         Date   DAU    MAU Stickiness
1  2012-04-28 25000 250000 0.10000000
...  ...      ...   ...    ...
10 2012-05-07 27371 284114 0.09633809

我怀疑问题与我正在评估的环境有关。

更新的样本数据:

> tdata
                 dt  username
    4236 2012-04-06 241343664
    3091 2012-04-06 306001012
    2936 2012-04-06 388682041
    5790 2012-04-05 235612064
    6763 2012-04-05  69650072
    3392 2012-04-06    617142
    7684 2012-04-05 189752749
    3904 2012-04-06 255852653
    7915 2012-04-05 182713266
    6107 2012-04-05 187675644

更新工作功能(使用Brian Diggs的回答):

stickiness <- function(tdata) {
    require(plyr)
    mau_unique <- dlply(.data = tdata,
                        .variables = "dt",
                        .fun = function(x){unique(x$username)})
    dates_char <- names(mau_unique)
    dates_vector <- as.Date(dates_char[28:(length(dates_char))],
                            format = "%Y-%m-%d")
    output_df <- data.frame(dates_vector,
                            matrix(data = 0,
                                   nrow = length(dates_char) - 27,
                                   ncol = 3))
    colnames(output_df) <- c("Date", "DAU", "MAU", "Stickiness")
    for (i in 1:length(dates_vector)) {
        dt <- dates_vector[i]
        output_df[i, "DAU"] <- length((mau_unique[[as.character(dt)]])
        set28 <- unique(do.call(c, mau_unique[i:(i + 27)]))  
        output_df[i, "MAU"] <- length(set28)
        output_df[i, "Stickiness"] <- output_df[i, "DAU"] / output_df[i, "MAU"]
    }
    return(output_df) 
}

1 个答案:

答案 0 :(得分:4)

感谢您添加一些示例数据,但它仍然无法真正重现,因为该函数假定数据跨越至少28天(或者更确切地说,至少28个唯一日期)。

问题,就像我能说的那样,在你的for循环中。使用您的示例数据

> mau_unique
$`2012-04-05`
[1] 235612064  69650072 189752749 182713266 187675644

$`2012-04-06`
[1] 241343664 306001012 388682041    617142 255852653

attr(,"split_type")
[1] "data.frame"
attr(,"split_labels")
          dt
1 2012-04-05
2 2012-04-06

所以在计算DAU时,您从mau_unique中提取相应的元素。使用DAU的虚拟值计算dt向外工作:

> dt <- as.Date("2012-04-05")
> dt
[1] "2012-04-05"
> as.character(dt)
[1] "2012-04-05"
> mau_unique[[as.character(dt)]]
[1] 235612064  69650072 189752749 182713266 187675644
> mau_unique[[as.character(dt)]][2]
[1] 69650072
> unlist(mau_unique[[as.character(dt)]][2])
[1] 69650072
> length(unlist(mau_unique[[as.character(dt)]][2]))
[1] 1

我不知道应该如何计算DAU,但是你总是从mau_unique中的相应向量中获取第二个用户名,并取长度,这就是为什么你总是得到1。你正在为set28做类似的事情;我不知道你为什么一直试图把第二个元素拉出来。


编辑:

综合生成的数据很好。这是在一个小空间中创建大量数据的好方法,设置随机种子将允许每个人使用相同的数据。

set.seed(1234)
tdata <- data.frame(dt = sample(seq(as.Date("2012-04-01"),
                                    as.Date("2012-04-30"),
                                    by = "day"),
                                size = 10000,
                                replace = TRUE),
                    username = sample(10000:10200,
                                      10000,
                                      replace = TRUE))

鉴于你对DAUMAU的描述,我认为你的for循环应该是:(函数的其余部分没有改变)

for (i in 1:length(dates_vector)) {
    dt <- dates_vector[i]
    output_df[i, "DAU"] <- length(mau_unique[[as.character(dt)]])
    output_df[i, "MAU"] <- length(unique(unlist(mau_unique[i:(i+27)])))
    output_df[i, "Stickiness"] <- output_df[i, "DAU"] / output_df[i, "MAU"]
}

鉴于此,你的粘性是:

> stickiness(tdata)
        Date DAU MAU Stickiness
1 2012-04-28 156 201  0.7761194
2 2012-04-29 168 201  0.8358209
3 2012-04-30 152 201  0.7562189