Controlling format/placement of axis labels when p

2019-07-16 00:18发布

I'd like to gain greater control over axis label size and placement when plotting a 2-dimensional table in R, but the plotting rules seem to work differently for table objects than for data frames. To make my questions concrete, I've pasted in fake data at the end of this message using dput(). Running that code will create the dept.table object used in the plotting code below.

When you run plot on a 2D table in R, it creates a mosaic plot, as in the following:

plot(dept.table, 
     col=c("yellow","blue","red"), 
     las=1, 
     cex=.7, 
     dir=c("h","v"), 
     off=c(8,4))

There are three changes I'd like to make to the axis labels in the plot created by this call.

First, alternate the height of the "Freshman", "Sophomore", etc. labels across the top, so that they don't overlap (I know I can shorten them, but I want to figure this out for future reference as well, since it's not always convenient to shorten labels). I thought of turning off axis labels and adding them manually with the text() function. However, adding xaxt = 'n' to the plot call evidently doesn't work when plotting a table object (R gives an "extra argument(s) 'xaxt' will be disregarded" message).

Another option is to rotate the x-axis labels by setting las=2. However, I'd prefer to have the labels horizontal for easier reading. I should note, though, that when I do set las=2, the label "Graduate Student" overlaps onto the plot area.

So there are several issues here:

  1. How do I turn off plotting of the x-axis labels so that I can add labels manually?
  2. Better yet, is there a more elegant way to get the labels to alternate up and down so that they don't overlap, without having to set the position of each one manually?
  3. If a label overlaps the plot area, is there a way (other than shortening the label) to eliminate the overlap?
  4. Is there a way to have different text sizes for the x-axis and y-axis labels? The actual plot I want to make has many more departments (the vertical axis) so I'd like to use a smaller text size for the y axis than for the x axis. The only option for axis text size seems to be cex, which adjusts both axes. Is there a way to adjust each axis separately?

  5. The y-axis labels are left justified. Is there a way to get them right justified, so they'll be close to the plot area?

By the way, although I made this plot with base graphics, I'd be interested in whether there are better ways to do it with lattice, ggplot2, or perhaps another package.

dept.table = structure(c(10, 15, 20, 200, 5, 15, 35, 200, 49, 15, 25, 20, 
250, 5, 12, 34, 150, 30, 50, 108, 75, 800, 32, 39, 135, 400, 
195, 80, 99, 64, 700, 47, 41, 134, 350, 160, 5, 10, 5, 110, 5, 
4, 10, 30, 13), .Dim = c(9L, 5L), .Dimnames = structure(list(
    c("Anthropology", "Economics", "Mathematics", "Business Administration", 
    "Geography", "Special Education, & Deaf Studies", "History", 
    "Kinesiology & Health Science", "Family & Consumer Sciences"
    ), c("Freshman", "Sophomore", "Junior", "Senior", "Graduate Student"
    )), .Names = c("", "")), class = "table")

1条回答
相关推荐>>
2楼-- · 2019-07-16 00:41

An approach using ggplot

# convert to a data frame
dept_data <- as.data.frame(dept.table)

Given you are attempting to plot the proportions (not the raw numbers)

# add proportions
library(plyr)
dept_data_prop <- ddply(dept_data, .(Var1), mutate, prop = Freq /sum(Freq))


library(ggplot2)
ggplot(dept_data_prop, aes(x= Var1, y = prop, colour = Var2, fill = Var2)) + 
  geom_bar() + 
  coord_flip() + 
  facet_wrap(~Var1, scales = 'free', ncol = 1) + 
  opts(strip.background =theme_blank(), strip.text.x = theme_blank(), 
       strip.text.y = theme_text(), axis.ticks = theme_blank(), 
       axis.title.x = theme_blank(), axis.text.x = theme_blank()) + xlab('') + 
  scale_fill_brewer('Student',  type = 'div', palette = 5) + 
  scale_colour_brewer('Student', type = 'div', palette = 5) + 
  scale_x_discrete(expand = c(0,0)) + 
  scale_y_continuous(expand=c(0,0))

To find out more about the available options, look at ?opts

The following is adapted from learning r

To get the bar widths proportional to the total counts

dept_data <- as.data.frame(dept.table)
names(dept_data) <- c('department', 'student', 'count')



dept_prop <- ddply(dept_data, .(department), mutate, 
               prop_department = count / sum(count),
               max_department = cumsum(prop_department),
               min_department = max_department - prop_department,
               total_department = sum(count))


dept_prop <- mutate(dept_prop, prop_total = total_department / sum(count))

dept_prop <- ddply(dept_prop, .(student), mutate, 
   max_total = cumsum(prop_total), 
   min_total = max_total - prop_total)



ggplot(dept_prop, aes(xmin = min_department, xmax = max_department, 
                      ymin = min_total, ymax = max_total)) +
 geom_rect(aes(colour = student, fill =student)) + 
 facet_grid(department~., scales = 'free', space = 'free') +
 opts(strip.background =theme_blank(), 
   strip.text.y = theme_text(hjust = 0.05), axis.ticks = theme_blank(), 
   axis.title.x = theme_blank(), axis.text.x = theme_blank(), 
   axis.title.y = theme_blank(), axis.text.y = theme_blank(), 
   legend.position = 'bottom', legend.justification = 'left',
   panel.border = theme_blank(), panel.background = theme_blank(), 
   panel.grid.major = theme_blank(), panel.grid.minor = theme_blank()) +
   xlab('') + 
 scale_fill_brewer('Student',  palette = 'Set1') + 
 scale_colour_brewer('Student', palette = 'Set1') + 
 scale_x_continuous(expand = c(0, 0)) + 
 scale_y_continuous(expand = c(0, 0))
查看更多
登录 后发表回答