Search code examples
rloopsbar-chartaxis-labels

How to specify number of axis labels


I have a df that looks like this but with 14000+ rows and 30 unique 'Vessel.Pln' identifiers;

I'm using the df to create a stacked barplot of landings by size.code by month for each vessel for a period of 10 years. I want to reduce the number of x axis labels to say every 3 months so that they are legible. I have found a few examples of ways to do it but I'm not sure how to set up an axis sequence when calling the barplot from a matrix of the df.

example of axis label overcrowding

    Size.Code   Date    Vessel.Pln  Weight
            2   2011-01-01  BF206   0.174330
            3   2011-01-01  BF206   0.095940
            4   2011-01-01  BF206   0.143910
            5   2011-01-01  BF206   0.407745
            2   2011-02-01  BF206   0.061425
            3   2011-02-01  BF206   0.234000
            5   2011-02-01  BF206   0.327600
            2   2011-05-01  BF206   0.081900
            3   2011-05-01  BF206   0.152100
            4   2011-05-01  BF206   0.444600
            5   2011-05-01  BF206   1.070550
            2   2011-06-01  BF206   0.273780
            3   2011-06-01  BF206   1.965600
            4   2011-06-01  BF206   0.795600
            1   2011-08-01  BF206   0.421200
            2   2011-08-01  BF206   1.329120
            3   2011-08-01  BF206   2.398500
            4   2011-08-01  BF206   2.000700
            5   2011-08-01  BF206   0.649350
            3   2011-10-01  BF206   0.056160

for (a in unique(grade$Vessel.Pln)) {
  df <- grade[grade$Vessel.Pln == a,]
  library(reshape2)
  df2 <- dcast(df,Size.Code~Date,sum)
  library(RColorBrewer)

  barplot(as.matrix(df2),main=a,
    xlim=c(0, ncol(df2) + 20),
    col=brewer.pal(nrow(df2), "Spectral"),
    ylab="Landings (tonnes)",xlab="Month",las=2,cex.names=0.4,
    args.legend=list(
    x=ncol(df2) + 3,
    y=max(colSums(df2)),
    bty = "n"
 )
)
legend(55, 
       legend = c("1", "2","3","4","5"), 
       fill =brewer.pal(nrow(df2), "Spectral"))
}

Solution

  • To maintain using base R's barplot, consider passing axisnames = FALSE and re-write with axis(). Below rewrites for each quarter between first and last date column.

    Also, consider using by, the function that splits a dataframe into one or more factor(s), to run plots for each distinct Vessel.Pln which avoids the subset call and for loop. Also, be sure to remove the first column of df2 matrix to not plot Size.Code:

    by(grade, grade$Vessel.Pln, function(df) {
    
      df2 <- dcast(df, Size.Code ~ Date,sum, value.var="Weight")
    
      bp <- barplot(as.matrix(df2[-1]), axisnames = FALSE,
                    main = a,
                    xlim = c(0, ncol(df2) + 20),
                    col = brewer.pal(nrow(df2), "Spectral"),
                    ylab = "Landings (tonnes)",xlab="Month",las=2,cex.names=0.4,
                    args.legend = list(
                      x = ncol(df2) + 3,
                      y = max(colSums(df2)),
                      bty = "n"
                    )
      )
    
      legend(55, 
             legend = c("1", "2","3","4","5"), 
             fill =brewer.pal(nrow(df2), "Spectral"))
    
      # REWRITES AXIS FOR YEAR QUARTERS
      axis(1, at = bp[seq(1,ncol(df2[-1]), 3)], 
           labels = names(df2[-1])[seq(1, ncol(df2[-1]), 3)]
      ) 
    
    })
    

    Plot Output