【问题标题】:Function result (dataframe) not what I expect函数结果(数据框)不是我所期望的
【发布时间】:2012-05-11 19:53:37
【问题描述】:

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

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

UPDATE 工作函数(使用 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) 
}

【问题讨论】:

    标签: r function dataframe plyr


    【解决方案1】:

    感谢您添加一些示例数据,但由于该函数假定数据至少跨越 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
    

    【讨论】:

    • DAU 代表“每日活跃用户”;它是特定日期唯一用户集的基数。 MAU 代表“每月活跃用户”;它是特定日期的唯一用户集的基数 UNION 过去 27 天的唯一用户集。
    • 关于数据,要发的太多了,但是可以轻松生成通用数据集date_vec &lt;- sample(seq(as.Date("2012-04-01"), as.Date("2012-04-30"), by = "day"), size = 10000, replace = TRUE); username_vec &lt;- sample(10000:10200, 10000, replace = TRUE); tdata &lt;- data.frame(dt = date_vec, username = username_vec)
    • 感谢您的帮助。我以为我已经(成功地)检查了我的代码进行了几次迭代,但显然情况并非如此。我在上面添加了工作功能。
    猜你喜欢
    • 1970-01-01
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多