Time for action - building a graphic with multiple visuals

Within R, it is possible to generate graphics that are composed from two or more separate visuals. Let us build a graphic that displays several pieces of information about our fire attack strategy simultaneously:

  1. Prepare the graphic window to display multiple graphics simultaneously:
    > #use par(mfcol) to prepare the graphic window to display multiple graphics simultaneously
    > #the mfcol argument receives a vector indicating the number of rows and columns to reserve for separate graphics in the graphics window
    > #here, we want 4 total graphics, so use a 2x2 vector
    > par(mfcol = c(2,2))
    > #note that a blank graphic window will open
    > #if this window is closed, your graphic window will default back to displaying a single visual
    > #if it remains open, your graphic window will continue to add visuals to the 2x2 grid as they are created
    
  2. Create the first graphic:
    > #create the first graphic by duplicating the steps taken in the Building a graphic activity
    > #this scatterplot depicted the number of Shu and Wei soldiers engaged in past fire attacks
    > plot(x = 0, y = 0, main = buildFireSoldiersMain,
    xlab = buildFireSoldiersLabX, ylab = buildFireSoldiersLabY,
    xlim = buildFireSoldiersLimX, ylim = buildFireSoldiersLimY,
    type = buildFireSoldiersType, xaxt = buildFireSoldiersAxtX,
    yaxt = buildFireSoldiersAxtY)
    > axis(side = 1, at = c(0:30), las = 0)
    > axis(side = 2,
    graphicscreating, with multiple visualsat = c(1000, 5000, 10000, 20000, 30000, 40000, 50000),
    las = 1)
    > points(x = pointsFireShuSoldiersDataX,
    y = pointsFireShuSoldiersDataY,
    type = pointsFireShuSoldiersType,
    col = pointsFireShuSoldiersColor)
    > points(x = pointsFireWeiSoldiersDataX,
    y = pointsFireWeiSoldiersDataY,
    type = pointsFireWeiSoldiersType,
    col = pointsFireWeiSoldiersColor,
    pch = pointsFireWeiSoldiersPch)
    > legend(x = 0, y = 50000, legend = c("Shu", "Wei"),
    fill = c(pointsFireShuSoldiersColor,
    pointsFireWeiSoldiersColor))
    
  3. Your graphic will now have additional space surrounding it, which can be used to incorporate new graphics, as shown in the following:
    Time for action - building a graphic with multiple visuals
  4. Add a second chart to the graphic:
    > #add a second chart that depicts the duration of past battles
    > #create new variables where necessary
    > #otherwise reuse the variables from our initial graphic
    > #basic parameters
    > buildFireDurationMain <- "Duration in Days"
    > buildFireDurationLabY <- "Days"
    > buildFireDurationLimY <- c(0, 14)
    > #use the plot(...) function to create a foundation for the graphic
    > plot(x = 0, y = 0, main = buildFireDurationMain,
    xlab = buildFireSoldiersLabX, ylab = buildFireDurationLabY,
    xlim = buildFireSoldiersLimX, ylim = buildFireDurationLimY,
    type = buildFireSoldiersType, xaxt = buildFireSoldiersAxtX,
    yaxt = buildFireSoldiersAxtY)
    > #axes
    > #x axis
    > axis(side = 1, at = c(0:30), las = 0)
    > #y axis
    > axis(side = 2, at = c(0:14), las = 1)
    > #use lines(...) to add data to the graphic
    graphicscreating, with multiple visuals> #add a line representing the duration in days for each battle
    > lineFireDurationDataX <- c(1:30)
    > lineFireDurationDataY <- subsetFire$DurationInDays
    > lineFireDurationType <- "o"
    > lineFireDurationWidth <- 1
    > lineFireDurationColor <- "red"
    > lines(x = lineFireDurationDataX, y = lineFireDurationDataY,
    type = lineFireDurationType, lwd = lineFireDurationWidth,
    col = lineFireDurationColor)
    > #use abline(...) to add a horizontal line to the chart
    > #add a line representing the mean duration
    > lineFireDurationMeanWidth <- 3
    > lineFireDurationMeanColor <- "blue"
    > abline(h = mean(lineFireDurationDataY),
    lwd = lineFireDurationMeanWidth,
    col = lineFireDurationMeanColor)
    
  5. Your new chart will be added to the existing graphic, as shown in the following:
    Time for action - building a graphic with multiple visuals
  6. Add a third chart to the graphic:
    > #add a third chart that depicts the percentage of victorious fire attacks when the strategy is executed successfully
    > #basic parameters
    > buildFireResultMain <- "Result When Successfully Executed"
    > buildFireResultSlices <- c(length(subset(numericResultFire,
    numericExecutionFire == 1 & numericResultFire == 1)),
    length(subset(numericExecutionFire,
    numericExecutionFire == 1 & numericResultFire == 0)))
    > buildFireResultLabels <- paste(buildFireResultSlices /
    sum(buildFireResultSlices) * 100, "%", sep = "")
    > buildFireResultColors <- c("red", "blue")
    > #use the pie(...) function to create and display the pie chart
    > pie(x = buildFireResultSlices,
    labels = buildFireResultLabels,
    main = buildFireResultMain,
    col = buildFireResultColors)
    > #legend
    > legend(x = "topright", legend = c("Victory", "Defeat"),
    fill = buildFireResultColors, cex = 0.85)
    
  7. Your new chart will be added to the existing graphic, as shown in the following:
    Time for action - building a graphic with multiple visuals
  8. Add a fourth chart to the graphic:
    > #add a fourth chart that compares the gold cost (in thousands) of the fire attack with the other battle methods
    > #get the raw cost of the various methods using comparable resources
    > goldCostFire <- functionGoldCost(2500, 225, 7)
    > goldCostAmbush <- functionGoldCost(meanShuSoldiersAmbush,
    225, meanDurationAmbush)
    > goldCostHeadToHead <-
    functionGoldCost(meanShuSoldiersHeadToHead, 225,
    meanDurationHeadToHead)
    > goldCostSurround <- functionGoldCost(meanShuSoldiersSurround,
    225, meanDurationSurround)
    > #basic parameters
    > #note that the bar heights are divided by 1000 so they are represented in thousands of gold
    > #presenting larger numbers in this manner is one way to keep our axes cleaner and our graphics more readable
    > buildCostHeight <- c(goldCostFire, goldCostAmbush,
    goldCostHeadToHead, goldCostSurround) / 1000
    > buildCostMain <- "Cost Comparison by Method"
    > buildCostLabX <- "Gold Cost (in thousands)"
    > buildCostLimX <- c(0, 400)
    > buildCostLimY <- c(0, 5)
    > buildCostNames <- c("Fire", "Amb", "Head", "Sur")
    > buildCostColors <- rainbow(length(buildCostHeight))
    > buildCostHoriz <- TRUE
    > #use the barplot(...) function to create and display the bar chart
    graphicscreating, with multiple visuals> barplot(height = buildCostHeight, main = buildCostMain,
    xlab = buildCostLabX, xlim = buildCostLimX,
    ylim = buildCostLimY, names = buildCostNames,
    col = buildCostColors, horiz = buildCostHoriz)
    > #legend
    > legend(x = 275, y = 2,
    legend = round(buildCostHeight * 1000, 0),
    fill = buildCostColors, title = "Exact Cost", cex = 0.75)
    
  9. Your new chart will be added to the existing graphic. The final graphic will look like the following:
    Time for action - building a graphic with multiple visuals

What just happened?

We built a custom visual that was composed from a set of four individual graphics.

Note

Note that this section will only highlight the new or unique features that were encountered during this process. You should already be familiar with generating individual graphics and customizing their parameters from our previous work.

par(mfcol)

The par(mfcol) command modifies the number of visuals that are displayed in the graphic window. By default, the graphic window displays a single visual. The mfcol argument accepts a vector indicating the number of rows and columns of visuals to be displayed in the graphic window. For example:

> par(mfcol = c(3, 3))

The code would reserve space in the graphic window for nine visuals that would be displayed in a 3-row by 3-column grid. Note that the mfcol vector does not have to be symmetrical. For instance, a 5 by 1 or 2 by 10 vector would also be acceptable.

Our par(mfcol) command told our graphic window to display our visuals in a 2-row by 2-column grid:

> par(mfcol = c(2,2))

Note

When par(mfcol) is executed, a blank graphic window will open. It is important to keep this window open. As long as it remains open, all graphics generated by R will be added to the grid defined by par(mfcol). Once the graphic window is closed, it will default back to generating single visuals. At that point, par(mfcol) can be used again to redefine the space of the graphic window.

Graphics

Once the space of our graphic window was defined, we simply added new visuals one by one. Notice that this process is identical to creating individual graphics. The difference is that the graphic window will continue to add new visuals to the same space, rather than replacing the previous visual each time a new one is created. Thus, we are able to combine multiple visuals into a single graphic.

We started by building two charts from scratch, one depicting the soldiers engaged in fire attacks on a scatterplot, and one displaying the duration of fire attacks in a line chart. We then generated two highly customized charts, one depicting the result of fire attacks when successfully executed as a pie, and one comparing the cost of the battle methods on a bar chart. Ultimately, we arrived at a single graphic containing information from four separate visuals.

While creating the charts that composed our combined graphic, we encountered two notable items that deserve an explanation here.

Horizontal and vertical lines

The first occurred while making our fire attack duration line chart. You may have noticed that we drew a flat, horizontal line across the chart at the mean duration. To accomplish this, we used the abline(...) function in a new way. Previously, we used abline(...) to draw best fit lines on scatterplots in the Customizing a scatterplot section of this chapter. Here, we used the h argument to define a point where a horizontal line should be drawn across our chart. By setting h to the mean duration, we were able to visualize the average fire attack duration amidst the fluctuations experienced across each individual battle:

> abline(h = mean(lineFireDurationDataY),
lwd = lineFireDurationMeanWidth, col = lineFireDurationMeanColor)

Note

Note that the abline(...) function also has a v argument, which can be used to define a vertical line at any point along the chart. If h and v are defined together, an intersecting pair of horizontal and vertical lines will be drawn.

Nested functions

A complex code segment that we encountered while making our pie chart involved a series of nested functions:

> buildFireResultSlices <- c(length(subset(numericResultFire,
numericSuccessfullyExecutedFire == 1 & numericResultFire == 1)),
length(subset(numericSuccessfullyExecutedFire,
numericSuccessfullyExecutedFire == 1 & numericResultFire == 0)))

Here, we created our pie's slices using a combination of the c(...), length(...), and subset(...) functions. Individually, these are all familiar. When combined, they can look confusing at first glance. The key to reading nested functions is to work from the innermost function to the outermost function. The key to creating nested functions is to remember to close your parenthesis in the opposite order that they are opened. For example, while the c(...) function was the first opened in our code, it was the last one that was closed. The following example illustrates this principle:

> function1(function2(function3()))

In nested functions, the innermost function is always executed first, followed by its surrounding function, and so on.

Note

As with other programming languages, functions in R can be nested at virtually unlimited levels. On one hand, nesting makes our code more compact and efficient. On the other hand, excessive nesting makes our code unreadable and undesirably complex. Take these points into consideration when nesting functions.

Pop quiz

  1. Which of the following is not true when of the par(mfcol) command?

    a. When executed, par(mfcol) will launch a new graphic window.

    b. Closing the graphic window will cancel the effects of the most recently executed par(mfcol) command.

    c. The mfcol argument only accepts symmetrical vectors.

    d. The par(mfcol) can be executed again to redefine the space of the graphic window.

  2. What impact would the following line of code have on a visual displayed in the graphic window?
    > abline(h = 4, v = 10)
    

    a. A horizontal line would be drawn at 4 on the y-axis.

    b. A vertical line would be drawn at 10 on the x-axis.

    c. A horizontal line would be drawn at 4 on the y-axis and a vertical line would be drawn at 10 on the x-axis.

    d. No lines would be drawn.

  3. Which of the following code fragments demonstrates how to properly nest the c(...) function inside the sum(data) function inside the mean(data) function?

    a. c(sum(data), mean(data))

    b. mean(sum(c(...)))

    c. c(sum(mean(data)))

    d. mean(sum(data), c(...))

Have a go hero

Combine the visuals that you created in the previous activity into a single R graphic. Then, hold a recruitment conference with the Shu generals and convince them that your strategy is worthy of their services.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset