2017-02-27 3 views
0

J'ai un data.frame avec plusieurs facteurs tels que:R: Tri facteur par la fréquence de niveau et de traçage

df<-data.frame(Var1=as.factor(sample(c("AB", "BC", "CD", "DE", "EF"), 1000, replace=TRUE))) 

avec

summary(df$Var1) 
AB BC CD DE EF 
209 195 178 221 197 

Je veux tracer la fréquence des niveaux de chaque facteur dans le data.frame comme suit:

Cependant, l'ordre des niveaux est alphabétique et non par fréquence. En utilisant nombre de bibliothèque (plyr) Je peux créer une nouvelle data.frame qui me donne la fréquence de chaque niveau:

df_count <-count(df, "Var1") 
Var1 freq 
1 AB 209 
2 BC 195 
3 CD 178 
4 DE 221 
5 EF 197 

Ce que je peux ensuite modifier l'ordre à l'aide

df_count$Var1<-factor(df_count$Var1, levels=df_count$Var1[order(df_count$freq, decreasing=TRUE)]) 

qui, une fois tracée donnez-moi ce que je veux, la fréquence triée de chaque niveau. 1.) Est-ce la solution la plus élégante? Cela me donne un data.frame supplémentaire pour chaque facteur/colonne dans mon data.frame d'origine, et je pense qu'il doit y avoir un moyen plus simple. 2.) Lors du traçage, comment puis-je renommer les légendes de légende et m'assurer qu'elles reçoivent le bon niveau de facteur? Si j'utilise

scale_fill_manual(labels=c("Name of AB", "Name of BC", "Name of CD", "Name of DE","Name of EF")) 

les étiquettes ne se rapportent pas au bon niveau. Ici, la première entrée dans la légende sera "DE" car c'est le niveau avec la fréquence la plus haute mais l'étiquette dira "Nom de AB" comme défini dans scale_fill_manual. Je pourrais vérifier l'ordre des étiquettes manuellement à chaque fois mais il doit y avoir un moyen automatique?

Répondre

1

Vous voulez reorder(), je pense. En général reorder(x,y,FUN) change l'ordre des niveaux d'un facteur x en fonction des résultats de l'application de la fonction FUN à une deuxième variable y. Dans ce cas, vous pouvez utiliser FUN=length, et peu importe ce que vous utilisez pour y.

Mettre en place des données (j'ai choisi de modifier les probabilités pour rendre le résultat plus clair):

set.seed(101) 
df <- data.frame(Var1=as.factor(sample(c("AB", "BC", "CD", "DE", "EF"), 
          prob=c(0.1,0.5,0.2,0.05,0.15), 
            1000, replace=TRUE))) 

terrain de base (mauvaise commande):

library(ggplot2) 
print(g1 <- ggplot(df, aes(x=factor(1), fill=Var1))+ 
    geom_bar(width=1, colour="black")+ 
    coord_polar(theta="y")+ 
    theme_void()) 

enter image description here

Maintenant réordonner:

df$Var1 <- reorder(df$Var1,df$Var1,FUN=length) 
levels(df$Var1) 
## [1] "DE" "AB" "EF" "CD" "BC" 

Vérifiez que l'ordre est juste:

sort(table(df$Var1)) 
## DE AB EF CD BC 
## 46 105 163 189 497 

Imprimer la nouvelle parcelle (bâton dans les nouvelles données avec %+% et retourner l'ordre de la légende avec guide_legend(): vous pouvez également utiliser function(x) -length(x) comme FUN pour changer l'ordre de les niveaux en premier lieu).

print(g1 %+% df + 
    scale_fill_discrete(guide=guide_legend(reverse=TRUE))) 

enter image description here

+0

Cela fonctionne parfaitement, merci! Combiné avec l'indice d'aosmith comment utiliser correctement les vecteurs nommés, il fonctionne comme un charme :-) – user45017

3

Les fonctions du paquet forcats peuvent aider avec l'ordre de facteur. En particulier, fct_infreq va définir l'ordre des niveaux en fonction de la fréquence de chaque niveau.

library(forcats) 

df$Var1 = fct_infreq(df$Var1) 

Vous pouvez utiliser le nom des vecteurs pour éviter l'ordre dans les scale_*_manual fonctions.

scale_fill_manual(labels = c(AB = "Name of AB", 
         BC = "Name of BC", 
         CD = "Name of CD", 
         DE = "Name of DE", 
         EF = "Name of EF")) 

donc votre code de complot pourrait ressembler à quelque chose comme

ggplot(df, aes(x = factor(1), fill = fct_infreq(Var1)))+ 
    geom_bar(width = 1, colour = "black")+ 
    coord_polar(theta = "y")+ 
    theme_void() + 
    scale_fill_discrete(labels = c(AB = "Name of AB", 
          BC = "Name of BC", 
          CD = "Name of CD", 
          DE = "Name of DE", 
          EF = "Name of EF")) 
+0

Merci pour votre réponse! J'ai décidé de prendre la réponse de Ben Bolker car elle n'utilise que des fonctions de base, mais votre explication sur la façon d'utiliser correctement les vecteurs pour les étiquettes a été très utile :-) – user45017

0

Vous avez également une solution simple en utilisant la bibliothèque forcats, et la fonction fct_infreq.

library(forcats) 
ggplot(df, aes(x = factor(1), fill = fct_infreq(Var1)))+ 
    geom_bar(width = 1, colour = "black")+ 
    coord_polar(theta = "y")+ 
    theme_void() + 
    guides(fill = guide_legend(title = "Var1")) 

Pie chart

Notez que le diagramme circulaire est considéré comme le mal (vous pouvez google que), et vous pouvez transmettre les mêmes informations avec une carte simple barre:

ggplot(df, aes(x = fct_infreq(Var1), fill = fct_infreq(Var1))) + 
    geom_bar(width = 1, colour = "black", show.legend = FALSE) + 
    xlab("Var1") 

Bar chart