Search code examples
rpie-chartdata-sciencedata-analysis

How can I avoid pie chart&legend overlap in R?


I wanna create a pie chart of crime types,and add a legend on the right hand,but I tried many times to avoid overlapping,doesn't work at all.

table(dd$Primary.Type.new)

                 ARSON                    ASSAULT                    BATTERY                   BURGLARY 
                   833                      30743                      91237                      29298 
       CRIMINAL DAMAGE          CRIMINAL TRESPASS         DECEPTIVE PRACTICE                   HOMICIDE 
                 57539                      14353                      17472                        640 
            KIDNAPPING        MOTOR VEHICLE THEFT                  NARCOTOCS OFFENSE INVOLVING CHILDREN 
                   517                      23724                      55685                       3347 
         OTHER OFFENSE             PUBLIC OFFENSE     PUBLIC PEACE VIOLATION                    ROBBERY 
                 30878                       3833                       3632                      18891 
             SEX_CRIME                      THEFT          WEAPONS VIOLATION 
                  9331                     103255                       4792

Type <- table(dd$Primary.Type.new)

Here's that from dput():

structure(c(ARSON = 833L, ASSAULT = 30743L, BATTERY = 91237L, 
BURGLARY = 29298L, `CRIMINAL DAMAGE` = 57539L, `CRIMINAL TRESPASS` = 14353L, 
`DECEPTIVE PRACTICE` = 17472L, HOMICIDE = 640L, KIDNAPPING = 517L, 
`MOTOR VEHICLE THEFT` = 23724L, NARCOTOCS = 55685L, `OFFENSE INVOLVING CHILDREN` = 3347L, 
`OTHER OFFENSE` = 30878L, `PUBLIC OFFENSE` = 3833L, `PUBLIC PEACE VIOLATION` = 3632L, 
ROBBERY = 18891L, `SEX CRIME` = 9331L, THEFT = 103255L, `WEAPONS VIOLATION` = 4792L
), .Dim = 19L, .Dimnames = list(. = c("ARSON", "ASSAULT", "BATTERY", 
"BURGLARY", "CRIMINAL DAMAGE", "CRIMINAL TRESPASS", "DECEPTIVE PRACTICE", 
"HOMICIDE", "KIDNAPPING", "MOTOR VEHICLE THEFT", "NARCOTOCS", 
"OFFENSE INVOLVING CHILDREN", "OTHER OFFENSE", "PUBLIC OFFENSE", 
"PUBLIC PEACE VIOLATION", "ROBBERY", "SEX CRIME", "THEFT", "WEAPONS VIOLATION"
)), class = "table") -> Type

piepercent<- round(100*Type/sum(Type), 1)

pie(Type, edges = 200, radius = 0.8,
clockwise = FALSE,angle = 45, col = rainbow(length(Type)), main = "Pie Chart of Primary Crime Types", labels = piepercent,labelcex = 0.8)

legend("right", inset = .05, title = "Primary Crime Type",legend= dd$Primary.Type.new,fill = rainbow(length(Type)), horiz=FALSE,cex = 0.6)

enter image description here

I tried to use par(), but doestn't work.

and BTW how can I change the labels into percentage? such as convert 20.7 into 20.7%. Thank you very much.

Update I also tried 3D piechart

library(plotrix)
pie3D(Type,labels = piepercent,explode = 0.1, main = "3D Pie Chart of 
Primary Crime Types", labelcex = 0.8)
legend("bottom", inset = .05, title = "Primary Crime Type",legend= dd$Primary.Type.new,fill = rainbow(length(Type)), horiz=TRUE,cex = 0.6)

enter image description here


Solution

  • I hesitate to post this since this is an absolutely terrible use case for a pie chart, but it's possible to make it a bit more readable and color-blind friendly:

    structure(c(ARSON = 833L, ASSAULT = 30743L, BATTERY = 91237L, 
    BURGLARY = 29298L, `CRIMINAL DAMAGE` = 57539L, `CRIMINAL TRESPASS` = 14353L, 
    `DECEPTIVE PRACTICE` = 17472L, HOMICIDE = 640L, KIDNAPPING = 517L, 
    `MOTOR VEHICLE THEFT` = 23724L, NARCOTOCS = 55685L, `OFFENSE INVOLVING CHILDREN` = 3347L, 
    `OTHER OFFENSE` = 30878L, `PUBLIC OFFENSE` = 3833L, `PUBLIC PEACE VIOLATION` = 3632L, 
    ROBBERY = 18891L, `SEX CRIME` = 9331L, THEFT = 103255L, `WEAPONS VIOLATION` = 4792L
    ), .Dim = 19L, .Dimnames = list(. = c("ARSON", "ASSAULT", "BATTERY", 
    "BURGLARY", "CRIMINAL DAMAGE", "CRIMINAL TRESPASS", "DECEPTIVE PRACTICE", 
    "HOMICIDE", "KIDNAPPING", "MOTOR VEHICLE THEFT", "NARCOTOCS", 
    "OFFENSE INVOLVING CHILDREN", "OTHER OFFENSE", "PUBLIC OFFENSE", 
    "PUBLIC PEACE VIOLATION", "ROBBERY", "SEX CRIME", "THEFT", "WEAPONS VIOLATION"
    )), class = "table") -> Type
    

    Order the slices (IMPORTANT):

    Type <- sort(Type, decreasing = TRUE) 
    

    Proper % and decent labels:

    piepercent <- scales::percent(as.numeric(Type/sum(Type)))
    

    Margins:

    par(mar = c(1, 1, 1, 1)) # bltr
    
    pie(
      Type, 
      edges = 200, 
      radius = 0.8,
      clockwise = TRUE, # IMPORTANT
      angle = 45, 
      col = viridis::viridis_pal(option = "magma", direction=-1)(length(Type)),  # BETTER COLOR PALETTE
      labels = tail(piepercent, -7), # NEVER DISPLAY OVERLAPPING LABELS
      cex = 0.7
    )
    
    legend(
      x = 1.2, # DELIBERATE POSITION
      y = 0.5, # DELIBERATE POSITION
      inset = .05, 
      title = "Primary Crime Type", 
      legend = names(Type), # YOU WERE PASSING IN _ALL_ THE REPEAT NAMES
      fill = viridis::viridis_pal(option = "magma", direction=-1)(length(Type)),  # USE THE SAME COLOR PALETTE
      horiz = FALSE,
      cex = 0.6, # PROPER PARAMETER FOR TEXT SIZE
      text.width = 0.7 # SET THE BOX WIDTH
    )
    

    Add the title manually:

    title("Pie Chart of Primary Crime Types", line = -1)
    

    enter image description here