【问题标题】:R: Calculating cumulative number of unique entriesR:计算唯一条目的累积数量
【发布时间】:2017-12-15 16:09:29
【问题描述】:

我有一个来自多个实验的数据框。我希望计算每次连续实验后获得的唯一值的累积数量。

例如,考虑:

test <- data.frame(exp = c( rep("exp1" , 4) , rep("exp2" , 4), rep("exp3" , 4) , rep("exp4" , 5) ) , 
                   entries = c("abcd","efgh","ijkl","mnop", "qrst" , "uvwx" , "abcd","efgh","ijkl" , "qrst" , "uvwx", 
                               "yzab" , "yzab" , "cdef" , "mnop" , "uvwx" , "ghij"))

> test
    exp entries
1  exp1    abcd
2  exp1    efgh
3  exp1    ijkl
4  exp1    mnop
5  exp2    qrst
6  exp2    uvwx
7  exp2    abcd
8  exp2    efgh
9  exp3    ijkl
10 exp3    qrst
11 exp3    uvwx
12 exp3    yzab
13 exp4    yzab
14 exp4    cdef
15 exp4    mnop
16 exp4    uvwx
17 exp4    ghij

唯一条目的总数为九。现在我希望结果看起来像:

   exp cum_unique_entries
1  exp1    4
2  exp2    6
3  exp3    7
4  exp4    9

最后我想以条形图的形式绘制它。 我可以使用 for 循环方法来做到这一点,但感觉必须有更优雅的方式。

【问题讨论】:

  • Exp1 有 4 个唯一条目,然后添加 exp2 总共有 6 个唯一条目,...
  • 与data.table...library(data.table); setDT(test); unique(test, by="entries")[, .N, by=exp][, cn := cumsum(N)][]

标签: r dplyr


【解决方案1】:

这是dplyr 的另一个解决方案:

library(dplyr)

test %>%
  mutate(cum_unique_entries = cumsum(!duplicated(entries))) %>%
  group_by(exp) %>%
  slice(n()) %>%
  select(-entries)

test %>%
  mutate(cum_unique_entries = cumsum(!duplicated(entries))) %>%
  group_by(exp) %>%
  summarise(cum_unique_entries = last(cum_unique_entries))

结果:

# A tibble: 4 x 2
     exp cum_unique_entries
  <fctr>              <int>
1   exp1                  4
2   exp2                  6
3   exp3                  7
4   exp4                  9

注意:

首先求所有非重复项的累积总和(cumsum(!duplicated(entries))),group_byexp,并取每组的最后一个cumsum,这个数字就是每组的累积唯一条目。

【讨论】:

  • 谢谢,这很好。出于某种原因,我正在尝试 cumsum(n_distinct(entry))
  • 再次感谢,您的问题让我更容易理解和实施我的实际问题。我试图总结我过去两年实验的结果,其中有 100 多个实验和大约 20k 的观察结果。干杯!
  • @ktyagi dplyr 非常高效,可以很好地与 2M obs 配合使用。但是,如果您有更多的数据,我建议尝试@dww 的data.table 原始速度解决方案,它基本上是在做同样的事情,但使用data.table
【解决方案2】:

library(data.table) 我们可以做到

setDT(test)[, new := cumsum(!duplicated(entries))]
test[, .(cum_unique_entries = new[.N]), by = exp]

【讨论】:

    【解决方案3】:

    1) sqldf 这可以在单个复杂连接中完成:

    library(sqldf)
    
    sqldf("select b.exp, count(Distinct a.entries) cum 
           from test a join test b on a.exp <= b.exp group by b.exp")
    

    给予:

       exp cum
    1 exp1   4
    2 exp2   6
    3 exp3   7
    4 exp4   9
    

    这个想法也可以使用其他框架翻译成相应的代码,尽管它在 base 和 dplyr 中效率很低,因为必须进行 n x n 笛卡尔连接然后对其进行子集化,而 SQL 可能会对其进行优化以避免产生大的中间结果。

    2) rollapplyrexptest 排序,并使用rollapplyr 计算唯一条目的累积数量。然后使用!duplicated(..., fromLast = TRUE) 取每个exp 组的最后一个

    library(zoo)
    
    n <- nrow(test)    
    test_sorted <- test[order(test$exp), ]
    len_uniq <- function(x) length(unique(x))
    test_cum <- transform(test_sorted,  cum = rollapplyr(entries, 1:n, len_uniq, fill = NA))
    test_cum[!duplicated(test_cum$exp, fromLast = TRUE), -2]
    

    给予:

        exp cum
    4  exp1   4
    8  exp2   6
    12 exp3   7
    17 exp4   9
    

    【讨论】:

      【解决方案4】:
      temp = split(test$entries, test$exp)
      data.frame(E = names(temp),
                 V = sapply(Reduce(c, temp, accumulate = TRUE), function(x) length(unique(x))))
      #     E V
      #1 exp1 4
      #2 exp2 6
      #3 exp3 7
      #4 exp4 9
      

      【讨论】:

        【解决方案5】:

        我会使用 reshape 包中的 cast 函数(simple examplefull reference)。 它应该像

        一样简单
        reshape::cast(test, exp~., value="entries", function(x) length(unique(x)) )
        

        我正在做的是告诉函数考虑您的数据集,使用 test 变量作为 id 变量并“忽略”所有其他变量(这就是 . 的含义),添加“指标" 由在名为 entries 的列上计算的给定函数 (function(x) length(unique(x))) 返回。

        有点像SQL 聚合函数和group by 构造! 它的 SQL 等价物是

        SELECT exp, count(distinct entries)
        FROM test
        GROUP BY test
        

        【讨论】:

        • 我收到一个错误:as.character(formula) 中的错误:无法将“内置”类型强制转换为“字符”类型的向量
        • 抱歉,我丢失了~....我已添加它并改进了答案!
        猜你喜欢
        • 2013-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多