首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有if/else函数的mutate()

具有if/else函数的mutate()
EN

Stack Overflow用户
提问于 2017-05-15 21:03:59
回答 4查看 1.5K关注 0票数 3

我有一个例子

代码语言:javascript
运行
复制
df <- data.frame(cust = sample(1:100, 1000, TRUE),
             channel = sample(c("WEB", "POS"), 1000, TRUE))

我想要变异

代码语言:javascript
运行
复制
get_channels <- function(data) {
    d <- data
    if(unique(d) %>% length() == 2){
        d <- "Both"
    } else {
        if(unique(d) %>% length() < 2 && unique(d) == "WEB") {
            d <- "Web"
        } else {
            d <- "POS"
            }
        }
    return(d)
}

这在没有问题的情况下工作,而且在小的数据文件上,它根本不需要时间。

代码语言:javascript
运行
复制
start.time <- Sys.time()

df %>%
    group_by(cust) %>%
    mutate(chan = get_channels(channel)) %>%
    group_by(cust) %>% 
    slice(1) %>%
    group_by(chan) %>%
    summarize(count = n()) %>%
    mutate(perc = count/sum(count))

end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken

0.34602秒时差

但是,当数据帧变得相当大时,例如,在cust >1000000或更多的情况下,我的基本if/else fx所需的时间要长得多,要长得多。

如何简化此功能,使其运行得更快?

EN

回答 4

Stack Overflow用户

发布于 2017-05-15 21:09:50

为此,您应该使用data.table。

代码语言:javascript
运行
复制
setDT(df)
t1 = Sys.time()
df = df[ , .(channels = ifelse(uniqueN(channel) == 2, "both", as.character(channel[1]))), by = .(cust)]

> Sys.time() - t1
Time difference of 0.00500083 secs

> head(df)
   cust channels
1:   37     both
2:   45     both
3:   74     both
4:   20     both
5:    1     both
6:   68     both
票数 5
EN

Stack Overflow用户

发布于 2017-05-15 23:55:16

您可以在基R中这样做:

代码语言:javascript
运行
复制
web_cust <- unique(df$cust[df$channel=="WEB"])
pos_cust <- unique(df$cust[df$channel=="POS"])

both <- length(intersect(web_cust, pos_cust))
web_only <- length(setdiff(web_cust, pos_cust))
pos_only <- length(setdiff(pos_cust, web_cust))

数据:

代码语言:javascript
运行
复制
set.seed(1)
df <- data.frame(cust = sample(2e6, 1e7, TRUE),
                 channel = sample(c("WEB", "POS"), 1e7, TRUE), 
                 stringsAsFactors = F)
票数 3
EN

Stack Overflow用户

发布于 2017-05-15 23:39:38

速度更快的dplyr版本,耗时约1/3,但可能仍比数据表版本慢。uniqueN借用了克里斯托费森的回答。

代码语言:javascript
运行
复制
 df %>%
    group_by(cust) %>%
    summarize(chan = if_else(uniqueN(channel) == 2, "Both", as.character(channel[1]))) %>%
    group_by(chan) %>%
    summarize(n = n() ) %>%
    mutate(perc = n /sum(n))

此外,通过这样优化您的功能,可以显着地提高您的原有功能:

代码语言:javascript
运行
复制
  get_channels <- function(data) {
    ud <- unique(data)
    udl <- length(ud)
    if(udl == 2) {
      r <- "Both"
    } else {
      if(udl < 2 && ud == "WEB") {
        r <- "Web"
      } else {
        r <- "POS"
      }
    }
    return(r)
  }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43988790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档