rplot

R stm package plot decide side of the text


In page 19 of the stm tutorial, Figure 6: Graphical display of topical prevalence contrast

https://cran.r-project.org/web/packages/stm/vignettes/stmVignette.pdf

Anyone has the idea how to plot the text of the figure in according to the dot side (i.e., 'Obama' and 'Sarah Palin' on the left hand side of the dot while 'Bush Presidency' on the right hand side of the dot)?

enter image description here


Solution

  • The estimateEffect method of the plot function doesn't allow custom positioning of the labels. However, you can save the plot to an object and use the elements to create a custom plot. You'll also need to add "omit.plot=TRUE".

    p <- plot(prep, covariate = "rating", topics = c(3, 7, 20),
          model = poliblogPrevFit, method = "difference",
          cov.value1 = "Liberal", cov.value2 = "Conservative",
          xlab = "More Conservative ... More Liberal",
          main = "Effect of Liberal vs. Conservative",
          xlim = c(-.1, .1), labeltype = "custom",
          custom.labels = c('Obama', 'Sarah Palin','Bush Presidency'),
          omit.plot=TRUE)  # Add this
    

    p is a list, which contains all the necessary data to create the same plot.

    plot(0, 0, col = "white", 
         ylim=c(0,4), 
         ylab="", yaxt = "n",
         xlim = c(-.1, .1), 
         xlab = "More Conservative ... More Liberal",
         main = "Effect of Liberal vs. Conservative")
    
    it <- length(p$topics)
    
    for (i in 1:length(p$topics)) {
      points(p$means[[i]], it, pch = 16)
      lines(c(p$cis[[i]][1], p$cis[[i]][2]), c(it, it))
      axis(2, at = it, labels = stringr::str_wrap(p$labels[i], width = 25), 
           las = 1, cex = 0.25, tick = FALSE, 
           pos = p$cis[[i]][1])
      it = it - 1
    }
    

    This code comes directly from the plotDifference function of the stm package. Note how the labels are done using the axis function to draw tick labels (without the axis). axis(2, ...) means a left axis.

    enter image description here

    I'm not sure why the results differ from Figure 6. Anyway, to modify the position of the labels, you have to tell the axis function which side to draw the axis (with the corresponding tick labels). One way is to create the required values first.

    POS <- c(1, 1, 2)  # The actual position (uses ci - lower [1] or upper [2])
    AXIS <- c(2, 2, 4) # which axis (2=left, 4=right)
    

    This will tell R to put the labels for Obama and Palin on the left (as before) but put the label for Bush on the right. Now run the code from above again except for the modifications shown:

    plot(0, 0, col = "white", 
         ylim=c(0,4), 
         ylab="", yaxt = "n",
         xlim = c(-.1, .1), 
         xlab = "More Conservative ... More Liberal",
         main = "Effect of Liberal vs. Conservative")
    
    lines(c(0, 0), c(0, length(p$topics) + 2), lty = 2)
    
    it <- length(p$topics)
    
    for (i in 1:length(p$topics)) {
      points(p$means[[i]], it, pch = 16)
      lines(c(p$cis[[i]][1], p$cis[[i]][2]), c(it, it))
    
      # Modify the following line
      axis(AXIS[i], at = it, labels = stringr::str_wrap(p$labels[i], width = 25), 
           las = 1, cex = 0.25, tick = FALSE, 
           pos = p$cis[[i]][POS[i]])
      it = it - 1
    }
    

    enter image description here