user432797
user432797

Reputation: 603

Automate plotting of different figures in R

I want to make function that loops through a dataframe to plots different plot figures next to each using par(), one plot is bar plot, second is scatter plot and the last is box plot, my data frame:

structure(list(rated = c(FALSE, TRUE, TRUE, TRUE), turns = c(13L, 
16L, 61L, 61L), victory_status = structure(c(2L, 3L, 1L, 1L), .Label = c("mate", 
"outoftime", "resign"), class = "factor"), winner = structure(c(2L, 
1L, 2L, 2L), .Label = c("charcoal", "cream"), class = "factor"), 
    increment_code = structure(c(1L, 3L, 3L, 2L), .Label = c("15+2", 
    "20+0", "5+10"), class = "factor"), cream_rating = c(1500L, 
    1322L, 1496L, 1439L), charcoal_rating = c(1191L, 1261L, 1500L, 
    1454L), opening_name = structure(c(4L, 2L, 1L, 3L), .Label = c("King's Pawn Game: Leonardis Variation", 
    "Nimzowitsch Defense: Kennedy Variation", "Queen's Pawn Game: Zukertort Variation", 
    "Slav Defense: Exchange Variation"), class = "factor")), row.names = c(NA, 
4L), class = "data.frame")

I tried:

par(mai=rep(0.5, 4))
layout(matrix(c(1,1, 2,2, 0, 3,3, 0), ncol = 4, byrow = TRUE))
chess_games<-read.csv("./data/games.csv")
chess_games_rated<-table(chess_games$rated)
head (chess_games_rated)
barplot(chess_games_rated, cex.lab=1.5, cex.axis=1.2, font=1)


chess_games<-read.csv("./data/games.csv")
chess_games_rated<-table(chess_games$winner, chess_games$rated)
barplot(chess_games_rated, col=c("blue","red","green"), cex.axis=1.5)
legend(x="topleft", legend = levels(chess_games$winner), col=c("blue","red","green"), pch=19, cex=1, pt.cex = 1)

boxplot.1<-boxplot(cream_rating ~ victory_status, chess_games[!chess_games$winner %in% "draw", ], cex.axis=1.2)

Can I assign the above code into a function?

Upvotes: 0

Views: 91

Answers (1)

r2evans
r2evans

Reputation: 160817

A literal translation of your three manual plots into a function looks like below.

myfunc <- function(data) {
  stopifnot(
    all(c("rated", "winner", "cream_rating", "victory_status") %in% names(data))
  )

  layout(matrix(c(1,1, 2,2, 0, 3,3, 0), ncol = 4, byrow = TRUE))

  rated <- xtabs(~ rated, data = data)
  br1 <- barplot(rated, cex.lab = 1.5, cex.axis = 1.2, font = 1)

  winner_rated <- xtabs(~ winner + rated, data = data)
  br2 <- barplot(winner_rated, col = c("blue","red","green"), cex.axis = 1.5)
  legend(x = "topleft", legend = levels(data$winner),
         col = c("blue","red","green"), pch = 19, cex = 1, pt.cex = 1)

  bx3 <- boxplot(cream_rating ~ victory_status, data = data[!data$winner %in% "draw", ],
                 cex.axis = 1.2)
  invisible(list(br1, br2, bx3))
}

myfunc(chess_games)

sample 3-way plot

It does not check that data$winner is a factor, nor if the number of unique levels is other than length 3.

It does invisibly return a list with the return value of each of the three plots. While it seems uninspiring for the barplots, it is still somewhat informative if you want/need it elsewhere. The boxplot contains significantly more information if you need it.

ret <- myfunc(chess_games)
str(ret)
# List of 3
#  $ : num [1:2, 1] 0.7 1.9
#  $ : num [1:2] 0.7 1.9
#  $ :List of 6
#   ..$ stats: 'integer' num [1:5, 1:4] NA NA NA NA NA ...
#   ..$ n    : num [1:4] 0 3 1 1
#   ..$ conf : num [1:2, 1:4] NA NA 1458 1534 1500 ...
#   ..$ out  : num(0) 
#   ..$ group: num(0) 
#   ..$ names: chr [1:4] "draw" "mate" "outoftime" "resign"

It is not general, in that it won't work with customizations or slightly-different data. Doing so would be rather difficult, since you're using different customization for each plot. Because of this, I start with stopifnot which will complain (and fail) if all of the required columns are not found.

If you need this to be more dynamic (variable number of plots or different variables to run table (or xtabs) on, then this is certainly feasible but you will need to lose per-plot customization.


Data. I removed the last column since you weren't using it and it was not parsing with this simple read.table.

chess_games <- read.table(header = TRUE, stringsAsFactors = TRUE, text="
   rated   turns   victory_status  winner  increment_code  cream_rating    charcoal_rating
   FALSE   13     outoftime       cream    15+2             1500           1191
   TRUE    16      resign        charcoal  5+10             1322           1261
   TRUE    61      mate           cream    5+10             1496           1500
   TRUE    61      mate           cream    20+0            1439            1454
   TRUE    95      mate           cream    30+3            1523            1469
   FALSE   5       draw            draw    10+0            1250            1002            ")

Upvotes: 1

Related Questions