gpt4 book ai didi

r - 如何在不创建分组变量的情况下分组?

转载 作者:行者123 更新时间:2023-12-04 10:45:03 24 4
gpt4 key购买 nike

我需要执行一个基本的 group_by/mutate使用辅助分组变量进行操作。例如:

df <- data.frame(
u = c(0, 0, 1, 0, 1),
v = c(8, 4, 2, 3, 5)
)

df %>%
group_by(tmp = cumsum(u)) %>%
mutate(w = cumprod(v)) %>%
ungroup %>%
select(-tmp)

我的问题是,如果 df恰好已经包含一个名为 tmp 的列我会失去它。

当然我可以选择一个非常奇特的名字而不是 tmp减少碰撞的可能性(或者我什至可以选择像 strrep("z", max(nchar(names(df))) + 1) 这样的东西),但我更喜欢有一个更干净的解决方案。

换句话说,我正在寻找 dplyr相当于这个 data.table线:
setDT(df)[, w := cumprod(v), by = cumsum(u)]

最佳答案

我们可以创建一个函数来处理这个问题。假设要创建的临时分组变量是'tmp',通过连接数据集的列名并调用make.unique , 如果数据集中已经存在 'tmp' 列,则重复的列将重命名为 'tmp.1'。使用 !! ,使用 'tmp.1'(来自 nm1)命名列不会影响数据集中已经存在的 'tmp'。如果没有 'tmp', 列,分组列将被命名为 'tmp',稍后用 select 删除。

f1 <- function(dat, grpCol, Col) {
grpCol <- enquo(grpCol)
Col <- enquo(Col)

changeCol <- "tmp"
nm1 <- tail(make.unique(c(names(dat), changeCol)), 1)
dat %>%
group_by(!! (nm1) := cumsum(!! grpCol)) %>%
mutate(w = cumprod(!!Col)) %>%
ungroup %>%
select(-one_of(nm1))


}

- 运行函数
f1(df, u, v)
# A tibble: 5 x 3
# u v w
# <dbl> <dbl> <dbl>
#1 0 8.00 8.00
#2 0 4.00 32.0
#3 1.00 2.00 2.00
#4 0 3.00 6.00
#5 1.00 5.00 5.00


f1(df %>% mutate(tmp = 1), u, v) #create a 'tmp' column in dataset
# A tibble: 5 x 4
# u v tmp w
# <dbl> <dbl> <dbl> <dbl>
#1 0 8.00 1.00 8.00
#2 0 4.00 1.00 32.0
#3 1.00 2.00 1.00 2.00
#4 0 3.00 1.00 6.00
#5 1.00 5.00 1.00 5.00

作为关于传递表达式的后续(来自@Frank 的评论)
expr <- quos(tmp = cumsum(u), w = cumprod(v))
#additional checks outside the function
names(expr)[1] <- if(names(expr)[1] %in% names(df))
strrep(names(expr)[1], 2) else names(expr)[1]


f2 <- function(dat, exprs ){

dat %>%
group_by(!!! exprs[1]) %>%
mutate(!!! exprs[2])

}

f2(df, expr)
# A tibble: 5 x 4
# Groups: tmp [3]
# u v tmp w
# <dbl> <dbl> <dbl> <dbl>
#1 0 8.00 0 8.00
#2 0 4.00 0 32.0
#3 1.00 2.00 1.00 2.00
#4 0 3.00 1.00 6.00
#5 1.00 5.00 2.00 5.00

关于r - 如何在不创建分组变量的情况下分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49325477/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com