除了一列之外,如何分组?

Rom*_*aka 25 r dplyr

group_by除了给定的列之外,如何通过所有列对数据进行分组?

aggregate,它会aggregate(x ~ ., ...).

我尝试了group_by(data, -x),但是这个组由负x组成(即与x分组相同).

eip*_*i10 26

您可以使用标准评估(group_by_而不是group_by)来执行此操作:

# Fake data
set.seed(492)
dat = data.frame(value=rnorm(1000), g1=sample(LETTERS,1000,replace=TRUE),
                 g2=sample(letters,1000,replace=TRUE), g3=sample(1:10, replace=TRUE),
                 other=sample(c("red","green","black"),1000,replace=TRUE))

dat %>% group_by_(.dots=names(dat)[-grep("value", names(dat))]) %>%
  summarise(meanValue=mean(value))
Run Code Online (Sandbox Code Playgroud)
       g1     g2    g3  other   meanValue
   <fctr> <fctr> <int> <fctr>       <dbl>
1       A      a     2  green  0.89281475
2       A      b     2    red -0.03558775
3       A      b     5  black -1.79184218
4       A      c    10  black  0.17518610
5       A      e     5  black  0.25830392
...
Run Code Online (Sandbox Code Playgroud)

有关标准与非标准评估的更多信息,请参阅此插图dplyr.

更新为dplyr0.7.0

为了解决@ÖmerAn的评论:看起来group_by_at是要走的路dplyr0.7.0(有人请纠正我,如果我错了,这个).例如:

dat %>% 
  group_by_at(names(dat)[-grep("value", names(dat))]) %>%
  summarise(meanValue=mean(value))
Run Code Online (Sandbox Code Playgroud)
# Groups:   g1, g2, g3 [?]
       g1     g2    g3  other   meanValue
   <fctr> <fctr> <int> <fctr>       <dbl>
 1      A      a     2  green  0.89281475
 2      A      b     2    red -0.03558775
 3      A      b     5  black -1.79184218
 4      A      c    10  black  0.17518610
 5      A      e     5  black  0.25830392
 6      A      e     5    red -0.81879788
 7      A      e     7  green  0.30836054
 8      A      f     2  green  0.05537047
 9      A      g     1  black  1.00156405
10      A      g    10  black  1.26884303
# ... with 949 more rows
Run Code Online (Sandbox Code Playgroud)

让我们确认两种方法都给出相同的输出(在dplyr0.7.0中):

new = dat %>% 
  group_by_at(names(dat)[-grep("value", names(dat))]) %>%
  summarise(meanValue=mean(value))

old = dat %>% 
  group_by_(.dots=names(dat)[-grep("value", names(dat))]) %>%
  summarise(meanValue=mean(value))

identical(old, new)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

  • 而不是`names(dat)[ - grep("value",names(dat))]`,你也可以使用`setdiff(names(dat),"value")` (11认同)
  • 虽然它有风险,但我猜你甚至可以按位置选择:`names(dat)[ - 1]`.我们打高尔夫球吧?:) (2认同)

ZS2*_*S27 26

基于@ eipi10的dplyr 0.7.0编辑,group_by_at似乎是这项工作的正确功能.但是,如果您只是想省略列"x",那么您可以使用:

new2.0 <- dat %>%
  group_by_at(vars(-x)) %>%
  summarize(mean_value = mean(value))
Run Code Online (Sandbox Code Playgroud)

使用@ eipi10的示例数据:

# Fake data
set.seed(492)
dat <- data.frame(value = rnorm(1000),
             g1 = sample(LETTERS, 1000, replace = TRUE),
             g2 = sample(letters, 1000, replace = TRUE),
             g3 = sample(1:10, replace = TRUE),
             other = sample(c("red", "green", "black"), 1000, replace = TRUE))

new <- dat %>% 
  group_by_at(names(dat)[-grep("value", names(dat))]) %>%
  summarise(meanValue = mean(value))


new2.0 <- dat %>% 
  group_by_at(vars(-value)) %>% 
  summarize(meanValue = mean(value))

identical(new, new2.0)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)


Jan*_*uhr 13

关于这个问题的一个小小的更新,因为我自己偶然发现并找到了当前版本dplyr(0.7.4)的优雅解决方案:在内部group_by_at(),您可以select()使用与使用函数相同的方式提供列的名称vars().这使我们能够hp通过编写以下内容除了一列(在本例中)之外的所有内容:

library(dplyr)
df <- as_tibble(mtcars, rownames = "car")
df %>% group_by_at(vars(-hp))
Run Code Online (Sandbox Code Playgroud)

  • 您甚至可以提供几个要忽略的列:`df%&gt;%group_by_at(vars(-hp,-cyl))`,而无需使用c()构造。超好! (3认同)
  • 它甚至可以使用“group_by(across(!hp)”。如果现在可以将其标记为答案,那就太好了。 (3认同)