it-swarm.com.de

R: Kreisdiagramm mit Prozentangaben als Beschriftungen mit ggplot2

Aus einem Datenrahmen möchte ich ein Kreisdiagramm für fünf Kategorien mit ihren Prozentsätzen als Beschriftungen in derselben Grafik in der Reihenfolge vom höchsten zum niedrigsten im Uhrzeigersinn darstellen.

Mein Code lautet:

League<-c("A","B","A","C","D","E","A","E","D","A","D")
data<-data.frame(League) # I have more variables 

p<-ggplot(data,aes(x="",fill=League))
p<-p+geom_bar(width=1)
p<-p+coord_polar(theta="y")
p<-p+geom_text(data,aes(y=cumsum(sort(table(data)))-0.5*sort(table(data)),label=paste(as.character(round(sort(table(data))/sum(table(data)),2)),rep("%",5),sep="")))
p

Ich benutze

cumsum(sort(table(data)))-0.5*sort(table(data))

um das Etikett in den entsprechenden Bereich zu legen und

label=paste(as.character(round(sort(table(data))/sum(table(data)),2)),rep("%",5),sep="")

für die Etiketten ist dies der Prozentsatz.

Ich erhalte folgende Ausgabe:

Error: ggplot2 doesn't know how to deal with data of class uneval
10
pescobar

Ich habe den größten Teil Ihres Codes erhalten. Ich fand es ziemlich einfach zu debuggen, indem ich den coord_polar... wegließ, um besser zu sehen, was als Balkendiagramm vor sich geht.

Die Hauptsache war, den Faktor vom höchsten zum niedrigsten umzuordnen, um die Plotreihenfolge zu korrigieren, und dann einfach mit den Labelpositionen spielen, um sie richtig zu machen. Ich habe auch Ihren Code für die Etiketten vereinfacht (Sie benötigen nicht den as.character oder die rep, und paste0 ist eine Abkürzung für sep = "".)

League<-c("A","B","A","C","D","E","A","E","D","A","D")
data<-data.frame(League) # I have more variables 

data$League <- reorder(data$League, X = data$League, FUN = function(x) -length(x))

at <- nrow(data) - as.numeric(cumsum(sort(table(data)))-0.5*sort(table(data)))

label=paste0(round(sort(table(data))/sum(table(data)),2) * 100,"%")

p <- ggplot(data,aes(x="", fill = League,fill=League)) +
  geom_bar(width = 1) +
  coord_polar(theta="y") +
  annotate(geom = "text", y = at, x = 1, label = label)
p

Die at-Berechnung ermittelt die Zentren der Keile. (Es ist einfacher, sie als Mittelpunkt der Balken in einem gestapelten Balkendiagramm zu betrachten. Führen Sie einfach den obigen Plot aus, ohne die Zeile coord_polar zu sehen.) Die Berechnung der Variable at lässt sich wie folgt aufteilen:

table(data) ist die Anzahl der Zeilen in jeder Gruppe, und sort(table(data)) ordnet sie in der Reihenfolge an, in der sie geplottet werden. Wenn man die cumsum() davon nimmt, erhält man die Kanten der einzelnen Stäbe, wenn man sie übereinander stapelt, und durch Multiplizieren mit 0,5 erhält man die Hälfte der Höhe jedes Stabs im Stapel (oder die halbe Breite der Keile des Kuchens). 

as.numeric() stellt einfach sicher, dass wir einen numerischen Vektor anstelle eines Objekts der Klasse table haben.

Wenn Sie die halben Breiten von den kumulativen Höhen abziehen, erhalten Sie die Mittelpunkte für jeden Balken, wenn Sie ihn stapeln. Ggplot wird jedoch die Balken mit den größten Stapeln an der Unterseite stapeln, wohingegen alle unsere sort()ing die kleinsten zuerst setzen, so dass wir nrow - alles tun müssen, da wir eigentlich die Labelpositionen relativ zu top der Bar, nicht der Boden. (Und mit den ursprünglich disaggregierten Daten ist nrow() die Gesamtzahl der Zeilen und somit die Gesamthöhe des Balkens.)

10
Gregor

Vorwort: Ich habe aus freien Willen keine Kreisdiagramme erstellt.

Hier ist eine Modifikation der ggpie-Funktion, die Prozentsätze enthält:

library(ggplot2)
library(dplyr)

#
# df$main should contain observations of interest
# df$condition can optionally be used to facet wrap
#
# labels should be a character vector of same length as group_by(df, main) or
# group_by(df, condition, main) if facet wrapping
#

pie_chart <- function(df, main, labels = NULL, condition = NULL) {

  # convert the data into percentages. group by conditional variable if needed
  df <- group_by_(df, .dots = c(condition, main)) %>%
    summarize(counts = n()) %>%
    mutate(perc = counts / sum(counts)) %>%
    arrange(desc(perc)) %>%
    mutate(label_pos = cumsum(perc) - perc / 2,
           perc_text = paste0(round(perc * 100), "%"))

  # reorder the category factor levels to order the legend
  df[[main]] <- factor(df[[main]], levels = unique(df[[main]]))

  # if labels haven't been specified, use what's already there
  if (is.null(labels)) labels <- as.character(df[[main]])

  p <- ggplot(data = df, aes_string(x = factor(1), y = "perc", fill = main)) +

    # make stacked bar chart with black border
    geom_bar(stat = "identity", color = "black", width = 1) +

    # add the percents to the interior of the chart
    geom_text(aes(x = 1.25, y = label_pos, label = perc_text), size = 4) +

    # add the category labels to the chart
    # increase x / play with label strings if labels aren't pretty
    geom_text(aes(x = 1.82, y = label_pos, label = labels), size = 4) +

    # convert to polar coordinates
    coord_polar(theta = "y") +

    # formatting
    scale_y_continuous(breaks = NULL) +
    scale_fill_discrete(name = "", labels = unique(labels)) +
    theme(text = element_text(size = 22),
          axis.ticks = element_blank(),
          axis.text = element_blank(),
          axis.title = element_blank())

  # facet wrap if that's happening
  if (!is.null(condition)) p <- p + facet_wrap(condition)

  return(p)
}

Beispiel:

# sample data
resps <- c("A", "A", "A", "F", "C", "C", "D", "D", "E")
cond <- c(rep("cat A", 5), rep("cat B", 4))
example <- data.frame(resps, cond)

Wie bei einem typischen ggplot-Aufruf:

ex_labs <- c("alpha", "charlie", "delta", "echo", "foxtrot")

pie_chart(example, main = "resps", labels = ex_labs) +
  labs(title = "unfacetted example")

 Unfacetted pie chart abomination

ex_labs2 <- c("alpha", "charlie", "foxtrot", "delta", "charlie", "echo")

pie_chart(example, main = "resps", labels = ex_labs2, condition = "cond") +
  labs(title = "facetted example")

 enter image description here

10
alexpghayes

Es funktionierte für alle enthaltenen Funktionen stark inspiriert von hier

 ggpie <- function (data) 
{
  # prepare name
  deparse( substitute(data) ) -> name ;

  # prepare percents for legend
  table( factor(data) ) -> tmp.count1
  prop.table( tmp.count1 ) * 100 -> tmp.percent1 ;
  paste( tmp.percent1, " %", sep = "" ) -> tmp.percent2 ;
  as.vector(tmp.count1) -> tmp.count1 ;

  # find breaks for legend
  rev( tmp.count1 ) -> tmp.count2 ;
  rev( cumsum( tmp.count2 ) - (tmp.count2 / 2) ) -> tmp.breaks1 ;

  # prepare data
  data.frame( vector1 = tmp.count1, names1 = names(tmp.percent1) ) -> tmp.df1 ;


  # plot data
  tmp.graph1 <- ggplot(tmp.df1, aes(x = 1, y = vector1, fill = names1 ) ) +
    geom_bar(stat = "identity", color = "black" ) +
    guides( fill = guide_legend(override.aes = list( colour = NA ) ) ) +
    coord_polar( theta = "y" ) +
    theme(axis.ticks = element_blank(),
          axis.text.y = element_blank(),
          axis.text.x = element_text( colour = "black"),
          axis.title = element_blank(),
          plot.title = element_text( hjust = 0.5, vjust = 0.5) ) +
    scale_y_continuous( breaks = tmp.breaks1, labels = tmp.percent2 ) +   
    ggtitle( name ) + 
    scale_fill_grey( name = "") ;

  return( tmp.graph1 )
} ;

Ein Beispiel :

sample( LETTERS[1:6], 200, replace = TRUE) -> vector1 ;
ggpie(vector1)

Ausgabe

0
François Jean