[英]How to group_by without creating a grouping variable?
我需要使用輔助分組變量執行基本的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
你可以使用ave
代替:
df %>% mutate(w = ave(v, cumsum(u), FUN = cumprod))
by
也可以:
df %>%
by(cumsum(.$u), mutate, w = cumprod(v)) %>%
unclass %>%
bind_rows
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.