170 votes

Groupe par plusieurs colonnes dans dplyr, à l'aide de la chaîne de vecteur d'entrée

Je suis en train de transférer ma compréhension de plyr en dplyr, mais je ne peux pas comprendre comment le groupe sur plusieurs colonnes.

# make data with weird column names that can't be hard coded
data = data.frame(
  asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
  a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)

# get the columns we want to average within
columns = names(data)[-3]

# plyr - works
ddply(data, columns, summarize, value=mean(value))

# dplyr - raises error
data %.%
  group_by(columns) %.%
  summarise(Value = mean(value))
#> Error in eval(expr, envir, enclos) : index out of bounds

Ce matin, mon manque de traduire le plyr exemple dans un dplyr-esque de la syntaxe?

58voto

hadley Points 33766

Le support de cette dans dplyr est actuellement assez faible, finalement, je pense que la syntaxe sera quelque chose comme:

df %.% group_by(.groups = c("asdfgfTgdsx", "asdfk30v0ja"))

Mais que, probablement, ne sera pas là pendant un moment (parce que j'ai besoin de réfléchir à toutes les conséquences).

En attendant, vous pouvez utiliser regroup(), qui prend une liste de symboles:

library(dplyr)

df <-  data.frame(
  asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE),
  a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)

df %.%
  regroup(list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %.%
  summarise(n = n())

Si vous avez un caractère de vecteur de noms de colonnes, vous pouvez les convertir à la bonne structure, avec des lapply() et as.symbol():

vars <- setdiff(names(df), "value")
vars2 <- lapply(vars, as.symbol)

df %.% regroup(vars2) %.% summarise(n = n())

27voto

edward Points 800

Spécification de la chaîne de colonnes en dplyr sont désormais pris en charge par les variantes de l' dplyr fonctions avec des noms finissant en un trait de soulignement. Par exemple, correspondant à l' group_by fonction il y a un group_by_ fonction qui peut prendre des arguments de chaîne. Cette vignette décrit la syntaxe de ces fonctions en détail.

L'extrait de code suivant proprement résout le problème que @sharoz initialement posé (note de la nécessité d'écrire l' .dots argument):

# Given data and columns from the OP

data %>%
    group_by_(.dots = columns) %>%
    summarise(Value = mean(value))

(Notez que dplyr utilise maintenant l' %>% de l'opérateur, et %.% est déconseillée).

17voto

Sebastian Kranz Points 166

Jusqu'à ce que dplyr possède un support complet pour les arguments de la chaîne, peut-être que ce résumé est utile:

https://gist.github.com/skranz/9681509

Il contient des tas de fonctions wrapper comme s_group_by, s_mutate, s_filter, etc qui utilisent des arguments de chaîne. Vous pouvez les mélanger avec la normale dplyr fonctions. Par exemple

cols = c("cyl","gear")
mtcars %.%
  s_group_by(cols) %.%  
  s_summarise("avdisp=mean(disp), max(disp)") %.%
  arrange(avdisp)

11voto

Gavin Simpson Points 72349

Il fonctionne si vous passer les objets (eh bien, vous ne l'êtes pas, mais...), plutôt que comme un caractère de vecteur:

df %.%
    group_by(asdfgfTgdsx, asdfk30v0ja) %.%
    summarise(Value = mean(value))

> df %.%
+   group_by(asdfgfTgdsx, asdfk30v0ja) %.%
+   summarise(Value = mean(value))
Source: local data frame [9 x 3]
Groups: asdfgfTgdsx

  asdfgfTgdsx asdfk30v0ja        Value
1           A           C  0.046538002
2           C           B -0.286359899
3           B           A -0.305159419
4           C           A -0.004741504
5           B           B  0.520126476
6           C           C  0.086805492
7           B           C -0.052613078
8           A           A  0.368410146
9           A           B  0.088462212

df a été votre data.

?group_by dit:

 ...: variables to group by. All tbls accept variable names, some
      will also accept functons of variables. Duplicated groups
      will be silently dropped.

qui-je l'interpréter à dire ne pas le caractère des versions des noms, mais comment vous vous y référer en foo$bar; bar n'est pas cité ici. Ou comment vous vous referez à des variables dans une formule: foo ~ bar.

@Arun mentionne également que vous pouvez faire:

df %.%
    group_by("asdfgfTgdsx", "asdfk30v0ja") %.%
    summarise(Value = mean(value))

Mais vous ne pouvez pas passer à quelque chose qui non évaluée n'est pas un nom de variable dans l'objet de données.

Je suppose que cela est dû à l'interne, les méthodes de Hadley est l'aide à chercher les choses que vous transmettez via l' ... argument.

4voto

Jordan Points 23
data = data.frame(
  my.a = sample(LETTERS[1:3], 100, replace=TRUE),
  my.b = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)

group_by(data,newcol=paste(my.a,my.b,sep="_")) %>% summarise(Value=mean(value))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X