Please don’t sue me, Netflix.

Please don’t sue me, Netflix.

In this post, you will find a compendium of the strange and unique things that you can do in R. Most of them have some legitimate uses alongside the strange ones, but the strange ones still exist.

Send Tweets from R

This is the most obvious and well known package on this list. You can get a developer API and scrape a bunch of tweets. There are some immediate and obvious applications of this, but there is lots of fun to be had. For instance, you can tweet with the twitteR package.

library(twitteR)
?tweet

Some (Reasonable) Uses of this Package

Call an Uber

Working late night on some code and realized you have no way of getting home? You don’t even need to take your eyes off the screen - just call an with the ubeR package!

library(ubeR)
?uber_requests

Some (Reasonable) Uses of this Package

Note: The github page still states that the request ride option points to a sandbox server. As far as I know, you can’t yet call an Uber from R. I haven’t tried it yet because I’m afraid that it will work.

Send a Notification to Your Phone

PushBullet is a service that sends notes, messages, links, and files between your devices (computer, phone, tablet, etc.). It works with pretty much every platform.

In R, you can get an API for your account and send messages from R to your phone. At first, this seems a little bonkers. Why would I be on R without my phone near me?

The github page for rpushbullet by Dirk Eddelbuettel gives a great example:

msg   <- "DONE after 10000 simulations taking 42.43 minutes"  
 
RPushbullet::pbPost("note", title="Simulation complete", body=msg)  
pbPost("note", title="Simulation complete", body=msg)  

The msg can be made from a paste() call that summarizes your results, then you can get an update on a simulation when it finishes! Go grab a coffee, R will let you know when to come back.

Another use (suggested by Karl Broman) is to send a push if there is an error in your simulation (so you don’t check it after a weekend to find that nothing happened).

Another idea: hourly updates.

# initialize some things
t0 <- Sys.time()
hour_counter <- 1
partial_results <- list()

# Get simulatin'
for(i in 1:a_lot){
    partial_results[[i]] <- do_things_or_whatever(variabes[i])
    
    time_so_far <- difftime(Sys.time(), t0, units = "hours")
    if(time_so_far > hour_counter){
        hour_title <- paste(hour_counter, "Hour(s) Elapsed")
        hour_body <- paste("Loop", i, "of", a_lot)
        pbPost(type = "note", title = hour_title,
               body = hour_body)
        
        # Super Important Step - update the counter!
        hour_counter <- hour_counter + 1
    }
}

end_time <- difftime(Sys.time(), t0, units = "hours")
end_body <- paste("Total Time:", end_time, "hrs")
pbPost(type = 'note', title = "Done Simulatin'",
       body = end_body)

If you have a friend that trusts you, you can get an API for their account and send things to them. I suggest that you send them cats. Lots of cats (see below).

PushBullet also has the ability to send texts. As it stands, the API doesn’t seem to allow for this. There’s probably a good reason for that, but could you imagine using R to text someone?

Validate Stories on FiveThirtyEight

During the election, I couldn’t get enough of the election stats at fivethirtyeight.com. They call themselves “data journalists” and a lot of their data is available on github. They released an R package to make it easier to access their data and some of their code.

Some (Reasonable) Uses of this Package

  • Plenty of example data in the package (with help files to tell you about them).
  • A good response when students ask “doesn’t everyone just use Excel?”

This is actually a very useful set of datasets for teaching. They’re not just toy examples - they’re straight out of the headlines!

Star Wars for Data Visualization

Would you like a simple yet effective way to show the errors? Ever notice how TIE fighters look like they have error bars?

par(cex=0.6) # Just for knitr proportions

# Courtesy Samuel Brown
TIEplot <- function(x, y, error, bodEx = 1.3, wingEx = 0.8, 
                    ylim = c(minLim, maxLim), names = NULL, ...){
    arrowsVar <- function(x0, y0, y1, length, ...){
        for(i in 1:length(x0)){
            arrows(x0 = x0[i], y0 = y0[i], y1 = y1[i], 
                   length = length[i], ...)
        }
    }
    maxLim <- 1.1 * max(mapply(sum, y, error))
    minLim <- 0.9 * min(mapply(sum, y, - error))

    plot(x, y, type="n", ylim = ylim, xaxt = "n", ...)
    arrowsVar(x0 = x, y0 = y, y1 = y + 1.96 * error, angle = 90, 
              code = 2, length = wingEx * error, col = "grey75", 
              lwd = 40 * wingEx * error)
    arrowsVar(x0 = x, y0 = y, y1 = y - 1.96 * error, angle = 90, 
              code = 2, length = wingEx * error, col = "grey75", 
              lwd = 40 * wingEx * error)
    points(x, y, pch = 21, col = "grey75", bg = "grey75", 
           cex = 20 * bodEx * error)
    points(x, y, pch = 21, col = "grey25", bg = "grey25", 
           cex = 10 * bodEx * error)
    points(x, y, pch = -0x2055, col = "grey75", 
           cex = 10 * bodEx * error)
    points(x, y, pch = 21, col = "grey25", bg = "grey25", 
           cex = 3 * bodEx * error)
    if(!is.null(names)) axis(1, at = x, labels = names) else axis(1)
}

Values <- c(1,2,5,4)
Errors <- c(0.25, 0.5, 0.33, 0.12)
dummyNames <- paste("Trial", 1:4)

TIEplot(1:4, Values, Errors, names = dummyNames, 
        ylim = c(0,6), main = "Pew Pew!")

All credit for this goes to Samuel Brown. Great work!

Some (Reasonable) Uses of this Package

None.

Speaking of special plotting characters…

CatterPlots

This is pretty self explanatory.

#library(devtools)
#install_github("Gibbsdavidl/CatterPlots")
library(CatterPlots)

# Warning: This package is very buggy
# The function looks for x and y OUTSIDE of the function call
# I don't pass these as arguments, but they must exist in the 
# GLOBAL environment for the function to work
x <- 1
y <- 1

purr <- catplot(xs=1, ys=1, cat = 1, xlim=c(0,11), ylim=c(0,11), 
                # catcolour must be c(red, green, blue, alpha)
                catcolor = c(0.2,0.5,1,1))
# the axes are weird, I can't figure out why
axis(1, at = (1:11)/11, labels = 1:11)
axis(2, at = (1:11)/11, labels = 1:11)
for(i in 2:11){
    cats(purr, i, i, cat = i, catcolor = c(0.2,0.5,1,1))
}

All credit goes to David L Gibbs. Note that you can also plot with emoji.

Speaking of cats…

Plot a Random Kitty

The original function can be found here, courtesy of Christina Bergey. However, it seems to be out of date. The original function included some inspirational quotes, but the API seems to have changed. An updated version with some formatting fixes can be found below.

plot.kitty <- function() {
    
    library(jpeg) 
    
    temp.cat = tempfile()
    download.file("http://thecatapi.com/api/images/get?format=src&type=jpg", 
                  destfile=temp.cat, mode = "wb")
    
    kitty = readJPEG(temp.cat)
    
    # Get dimensions
    kitty.h = dim(kitty)[1]
    kitty.w = dim(kitty)[2]
    kitty.ratio = kitty.h / kitty.w
    
    opar <- par()$mar
    
    par(mar=rep(1, 4))

    # Only plot if version of R supports it
    if (exists("rasterImage")) {
        
        plot(0:1, 0:1, type='n', xaxt='n', yaxt='n')
        
        rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4], 
             col = "black")
        
        # If image is lanscape, set width to be 0.6 and compute height
        if (kitty.w > kitty.h) {
            center.x = 0.5
            x.limits = c(center.x - 0.5, center.x + 0.5)
            width = x.limits[2] - x.limits[1]
            
            height = width * kitty.ratio
            center.y = 1 - (1.5 * height / 2)
            y.limits = c(center.y - (height / 2), center.y + (height / 2))
        } else {
            # Otherwise, set height to be 0.6 and compute width
            center.y = 1 - (0.6 / 2)
            y.limits = c(center.y - 0.7, center.y + 0.3)
            height = y.limits[2] - y.limits[1]
            
            center.x = 0.5
            width = height / kitty.ratio
            x.limits = c(center.x - (width / 2), center.x + (width / 2))
            
        }
        
        rasterImage(kitty, x.limits[1], y.limits[1], x.limits[2], y.limits[2])
        
    }
    par(mar=opar)
    
}
plot.kitty()

I would just like to take a moment and comment on the code for the plots. I changed a few values and removed the section for quotes, but the rest of the code is Christina’s. It’s rare that I find nicely formatted and commented code on github, so kudos!

Some (Reasonable) Uses of this Code

None, really. I have a .R file that I source at startup (changing mean to default to na.rm=TRUE and shortening par(mfrow=c(1,2)) to pm(12)), and I put this code at the end of it just in case I want to see a cat.

Maybe you’ve been reading about predatory publishing and just really need to see something cute.

Keeping track of Predatory Publishers

With the “publish or perish” mentality, there’s bound to be some people trying to game the system. There might be some researchers looking for an easy way to publish, but as long as we have good journals this isn’t a problem.

Unfortunately, their not all good journals. There are plenty of journals that will charge the researcher to publish and promise peer review and prestige, but then they take their paper (under their own copyright) and publish as is (regardless of the content). This is bad for pretty much all of science.

There used to be a well maintained list of such journals, but it was managed by a single person working for free. It was mysteriously shut down. Open source will prevail (R is a testament to that), and that’s where this package comes in.

library(predatory)
## Thank you for using predatory! I also built a simple shiny app with similar funcionality.
## It is available at:
## 
## https://msperlin.shinyapps.io/shiny-predatory/
my.str <- 'finance'
temp <- find.predatory(x = my.str)
## 
## Found 141 row(s)
temp
## # A tibble: 141 × 5
##                                   publisher
##                                       <chr>
## 1  Academic and Business Research Institute
## 2  Academic and Business Research Institute
## 3        Academic and Scientific Publishing
## 4        Academic and Scientific Publishing
## 5        Academic and Scientific Publishing
## 6        Academic and Scientific Publishing
## 7        Academic and Scientific Publishing
## 8        Academic and Scientific Publishing
## 9        Academic and Scientific Publishing
## 10       Academic and Scientific Publishing
## # ... with 131 more rows, and 4 more variables: journal_name <chr>,
## #   issn <chr>, SJR_2015 <dbl>, JCR_2014 <chr>

Some (Reasonable) Uses of this Package

If you’re already aware of predatory publishers, you probably won’t need this. However, this is still another fun dataset to play with and it’s always worth warning people about predatory publishers.

Bonus: Realistic Coffee Rings

This isn’t an R thing, it’s a LaTeX thing, but I assume that the audience has some overlap.

You know those old papers that you find with the coffee ring on them? It’s like discovering an old manuscript that you though was long lost.

Well, now you can get that experience built in to LaTeX! The following image comes from the package creator Hanno Rein. Obviously it’s a bit out of date (2009), but the package is still available on their site!