如何避免 R 中的饼图和图例重叠?

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

我想做一个犯罪类型的饼图,在右边加个图例,但是我试了很多次避免重叠,根本不行。

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)

这是来自 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)

我尝试使用 par(),但没有用。

顺便说一句,我怎样才能将标签更改为百分比?例如将 20.7 转换为 20.7%。 非常感谢。

更新 我也试过 3D 饼图

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)

不能让饼图单独存在(现在是 3D 饼图):

structure(list(cat = 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"
), val = c(833, 30743, 91237, 29298, 57539, 14353, 17472, 640, 
517, 23724, 55685, 3347, 30878, 3833, 3632, 18891, 9331, 103255, 
4792), pct = c(0.001666, 0.061486, 0.182474, 0.058596, 0.115078, 
0.028706, 0.034944, 0.00128, 0.001034, 0.047448, 0.11137, 0.006694, 
0.061756, 0.007666, 0.007264, 0.037782, 0.018662, 0.20651, 0.009584
)), class = "data.frame", row.names = c(NA, -19L)) -> xdf

dplyr::arrange(xdf, pct) %>% 
  dplyr::mutate(cat = factor(cat, levels=cat)) %>% 
  dplyr::mutate(lab = sprintf("%s (%s)", scales::comma(val), scales::percent(pct))) %>% 
  ggplot(aes(pct, cat)) +
  geom_segment(aes(xend=0, yend=cat), size=4, color = "#617a89") +
  geom_label(
    aes(label=lab), label.size = 0, hjust=0, nudge_x=0.001, 
    size = 3, family = hrbrthemes::font_rc, color = "#909495"
  ) +
  hrbrthemes::scale_x_percent(expand=c(0,0.001), limits=c(0,0.25)) +
  labs(x = NULL, y = NULL, title = "'Theft', 'Battery' & 'Criminal Damage' Account\nfor Half of Primary Recorded Crime Types") +
  hrbrthemes::theme_ipsum_rc(grid="X") +
  theme(axis.text.x = element_blank())

我是怎么得到的 xdf:

readLines(textConnection("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")) %>% 
  trimws() %>%
  stri_split_regex("[[:space:]]+")  -> x

do.call(rbind.data.frame, lapply(seq.int(1, length(x), 2), function(i) {
  data.frame(
    cat = stri_trans_totitle(gsub("_", " ", x[[i]])), 
    val = as.numeric(x[[i+1]]), 
    stringsAsFactors = FALSE
  )
})) %>% 
  mutate(pct = val/sum(val)) -> xdf

我对 post 犹豫不决,因为这是一个 绝对糟糕的饼图用例 ,但可以使其更具可读性并且 color-blind 友好:

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

订购切片(重要):

Type <- sort(Type, decreasing = TRUE) 

正确的百分比和体面的标签:

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

页边距:

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
)

手动添加标题:

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