簡體   English   中英

如何在不創建分組變量的情況下分組?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM