Time for action - customizing a bar chart

To begin, we will expand our Chapter 8 bar chart using arguments specifically designed for the barplot(...) function. We will also become familiar with two different types of bar charts.

  1. Open R and set your working directory:
    > #set the R working directory
    > #replace the sample location with one that is relevant to you
    > setwd("/Users/johnmquick/rBeginnersGuide/")
    
  2. Load the Chapter 9 workspace. It contains the necessary information for this chapter:
    > #load the chapter 9 workspace
    > load("rBeginnersGuide_Ch_09_ReadersCopy.RData")
    
  3. Use the names, width, and space arguments to customize a chart's bars:
    > #modify the chapter 8 bar chart that compared the mean durations of the battle methods
    > #use the names argument to assign a text label to each bar
    > #the names argument receives a vector containing text labels for each of the chart's bars
    > barAllMethodsDurationNames <- c("Fire", "Ambush",
    "Head to Head", "Surround")
    > #use the width argument to change the width of each bar
    > #note that width can be set using a single value for all bars or by creating a vector to hold a unique value for each bar
    > #note that the xlim argument must be defined in order to use the single value approach
    > barAllMethodsDurationLimX <- c(0, 4)
    > barAllMethodsDurationWidth <- 0.25
    > #use the space argument to change the distance between each bar
    > #the space value is a ratio of the average bar width; it defaults to 0.2
    > #note that space can be set using a single value for all bars or by creating a vector to hold a unique value for each bar
    > barAllMethodsDurationSpace <- 2
    > #use barplot(...) to create and display the bar chart
    > barplot(height = barAllMethodsDurationBars,
    main = barAllMethodsDurationLabelMain,
    xlab = barAllMethodsDurationLabelX,
    ylab = barAllMethodsDurationLabelY,
    xlim = barAllMethodsDurationLimX,
    ylim = barAllMethodsDurationLimY,
    col = barAllMethodsDurationRainbowColors,
    names = barAllMethodsDurationNames,
    width = barAllMethodsDurationWidth,
    space = barAllMethodsDurationSpace)
    
  4. Your chart will be displayed in the graphic window, as shown in the following:
    Time for action - customizing a bar chart
  5. Use the horiz argument to change the chart's orientation:
    > #set a bar chart's orientation using the horiz argument
    > #if TRUE, the bars will display horizontally
    > #if FALSE (default), the bars will display vertically
    > barAllMethodsDurationHoriz <- TRUE
    > #note that you must reorient the chart for it to display properly
    > #this can be accomplished by switching the values of all arguments related to the x and y axes
    > #use barplot(...) to create and display the bar chart
    > barplot(height = barAllMethodsDurationBars,
    main = barAllMethodsDurationLabelMain,
    xlab = barAllMethodsDurationLabelY,
    ylab = barAllMethodsDurationLabelX,
    xlim = barAllMethodsDurationLimY,
    ylim = barAllMethodsDurationLimX,
    col = barAllMethodsDurationRainbowColors,
    names = barAllMethodsDurationNames,
    width = barAllMethodsDurationWidth,
    space = barAllMethodsDurationSpace,
    horiz = barAllMethodsDurationHoriz)
    
  6. Your chart will be displayed in the graphic window, as shown in the following:
    Time for action - customizing a bar chart

    Note

    Note that if your bar labels do not all appear along the y-axis, you may want to resize the graphic window. Making your window larger will provide it with enough space to display all of the chart's labels.

  7. Use the beside argument to create a stacked bar chart:
    > #create a new bar chart to demonstrate the stacking feature
    > #create a bar chart that depicts the average number of soldiers involved in each battle method with stacked bars for the Shu and Wei forces
    > #set the stacking of a chart's bars using the beside argument
    > #if TRUE (default), the bars will display next to one another
    > #if FALSE, the bars will display atop one another
    > barAllMethodsSoldiersBeside <- FALSE
    > #note that the bar values must be in matrix form for the beside argument to take effect
    > #calculate the bar values for each method
    > #fire
    > meanShuSoldiersFire <- mean(subsetFire$ShuSoldiers)
    > meanWeiSoldiersFire <- mean(subsetFire$WeiSoldiers)
    > #ambush
    > meanShuSoldiersAmbush <- mean(subsetAmbush$ShuSoldiers)
    > meanWeiSoldiersAmbush <- mean(subsetAmbush$WeiSoldiers)
    > #head to head
    > meanShuSoldiersHeadToHead <-
    mean(subsetHeadToHead$ShuSoldiers)
    > meanWeiSoldiersHeadToHead <-
    mean(subsetHeadToHead$WeiSoldiers)
    > #surround
    > meanShuSoldiersSurround <- mean(subsetSurround$ShuSoldiers)
    > meanWeiSoldiersSurround <- mean(subsetSurround$WeiSoldiers)
    > #put the bar values into matrix form using the matrix(...) function
    > #the matrix should have four columns (one for each method) and two rows (one for each kingdom)
    > #when the chart is created, the rows will be stacked within each column
    > barAllMethodsSoldiersBars <- matrix(c(meanShuSoldiersFire,
    meanWeiSoldiersFire, meanShuSoldiersAmbush,
    meanWeiSoldiersAmbush, meanShuSoldiersHeadToHead,
    meanWeiSoldiersHeadToHead, meanShuSoldiersSurround,
    meanWeiSoldiersSurround), 2, 4)
    > #customize the chart
    > barAllMethodsSoldiersMain <- "Average Number of Soldiers Engaged in Battle by Kingdom"
    > barAllMethodsSoldiersMain <- "Average Number of Soldiers Engaged in Battle by Kingdom"
    > barAllMethodsSoldiersLabX <- "Battle Method"
    > barAllMethodsSoldiersLabY <- "Number of Soldiers"
    > barAllMethodsSoldiersNames <- c("Fire", "Ambush",
    "Head to Head", "Surround")
    > #use barplot(...) to create and display the bar chart
    > barplot(height = barAllMethodsSoldiersBars,
    main = barAllMethodsSoldiersMain,
    xlab = barAllMethodsSoldiersLabX,
    ylab = barAllMethodsSoldiersLabY,
    names = barAllMethodsSoldiersNames,
    beside = barAllMethodsSoldiersBeside)
    
  8. Your chart will be displayed in the graphic window, as follows:
    Time for action - customizing a bar chart
  9. Use the density and angle arguments to change the shading of the chart's bars:
    > #use the density argument to define the thickness of the shaded lines
    > #density receives either a single nonnegative value for all matrix rows or a vector containing a value for each row
    > #density is measured in lines per inch with a default value of NULL
    > barAllMethodsSoldiersDensity <- c(10, 25)
    > #angle modifies the angle of the shaded lines
    > #angle receives either a single value for all matrix rows or a vector containing a value for each row
    > #angle is measured in degrees
    > barAllMethodsSoldiersAngle <- c(45, -45)
    > #use barplot(...) to create and display the bar chart
    > barplot(height = barAllMethodsSoldiersBars,
    main = barAllMethodsSoldiersMain,
    xlab = barAllMethodsSoldiersLabX,
    ylab = barAllMethodsSoldiersLabY,
    names = barAllMethodsSoldiersNames,
    beside = barAllMethodsSoldiersBeside,
    density = barAllMethodsSoldiersDensity,
    angle = barAllMethodsSoldiersAngle)
    
  10. Your chart will be displayed in the graphic window, as shown in the following:
    Time for action - customizing a bar chart
  11. Add a legend to the chart:
    > #add a legend to the stacked bar chart
    > #use the x and y arguments to specify the exact location of the legend
    > #note that the possible x and y values are determined by the limits of your axes
    > #add labels for the Shu and Wei armies
    > #incorporate the density and angle arguments from our barplot(...) function
    > #use cex to increase the size of the legend
    > legend(x = 0.2, y = 70000, legend = c("Shu", "Wei"),
    density = barAllMethodsSoldiersDensity,
    angle = barAllMethodsSoldiersAngle, cex = 2)
    
  12. Your legend will be added to the existing chart. The final chart looks like the following:
    Time for action - customizing a bar chart

What just happened?

We created vertical, horizontal, and stacked bar charts using the barplot(...) function and its custom arguments. We also expanded upon the legend(...) function to gain more control over its appearance. Let us reflect upon each of these steps.

names

We started by adding text labels to our bars via the names argument. This argument receives a vector containing the text label to be appended to each bar. In our case, the labels consisted of the four battle methods that follow:

barAllMethodsSoldiersNames <- c("Fire", "Ambush", "Head to Head",
"Surround")

width and space

Then, we looked at two arguments that are unique to the barplot(...) function. The width argument specifies the thickness of a chart's bars. It can be defined as a single value for all bars or a vector that contains unique values for each bar. Note that if a single value is used, the xlim argument must be defined for the width argument to take effect. In coordination with width, we also employed the space argument, which determines the distance between a chart's bars. Like width, space can be defined as a single value or a vector containing values for each bar. It is measured as a ratio of the average bar width and defaults to a value of 0.2. For example, if the average width of the bars was 5 and the space was set to 0.5, then the distance between each bar would be 2.5. For our chart, we chose a width of 0.25 and a space of 2, which had the visual effect of making our bars skinnier and spread farther apart:

> barAllMethodsDurationWidth <- 0.25
> barAllMethodsDurationSpace <- 2

We chose uniform width and space values for our bars. Had we wanted to set unique values for each bar, such as when weighting the bars according to the number of data points they include, we could have used the following code:

> barAllMethodsDurationWidth <- c(0.1, 0.25, 0.5, 0.75)
> barAllMethodsDurationSpace <- c(0.5, 1, 1.5, 2)

Lastly, the names, width, and space arguments were incorporated into our overall barplot(...) function:

> barplot(height = barAllMethodsDurationBars,
main = barAllMethodsDurationLabelMain,
xlab = barAllMethodsDurationLabelX,
ylab = barAllMethodsDurationLabelY,
xlim = barAllMethodsDurationLimX,
ylim = barAllMethodsDurationLimY,
col = barAllMethodsDurationRainbowColors,
names = barAllMethodsDurationNames,
width = barAllMethodsDurationWidth,
space = barAllMethodsDurationSpace)

horiz

To further expand our bar chart, we incorporated the horiz argument. This argument allows us to reorient our bars such that they extend horizontally, rather than vertically, across the chart. The horiz argument receives either a TRUE or FALSE value indicating whether the bars should be oriented horizontally. By default, horiz is set to FALSE and the bars are drawn vertically. We chose to reorient our bars by setting our horiz variable to TRUE:

barAllMethodsDurationHoriz <- TRUE

We then included it into our barplot(...) function:

> barplot(height = barAllMethodsDurationBars,
main = barAllMethodsDurationLabelMain,
xlab = barAllMethodsDurationLabelY,
ylab = barAllMethodsDurationLabelX,
xlim = barAllMethodsDurationLimY,
ylim = barAllMethodsDurationLimX,
col = barAllMethodsDurationRainbowColors,
names = barAllMethodsDurationNames,
width = barAllMethodsDurationWidth,
space = barAllMethodsDurationSpace,
horiz = barAllMethodsDurationHoriz)

Note that reorienting the bars of a chart is similar in effect to rotating it by 90 degrees. Therefore, to prevent a misshapen and unreadable graphic, we must also swap all arguments related to the x and y-axes. In our case, that meant exchanging our x-axis and y-axis limits and labels:

> barplot(height = barAllMethodsDurationBars,
main = barAllMethodsDurationLabelMain,
xlab = barAllMethodsDurationLabelY,
ylab = barAllMethodsDurationLabelX,
xlim = barAllMethodsDurationLimY,
ylim = barAllMethodsDurationLimX,
col = barAllMethodsDurationRainbowColors,
names = barAllMethodsDurationNames,
width = barAllMethodsDurationWidth,
space = barAllMethodsDurationSpace,
horiz = barAllMethodsDurationHoriz)

After swapping these values, the chart displays appropriately. Had we forgotten to make this exchange, we would have ended up with the following graphic:

horiz

Note

Remember to swap your x-axis and y-axis arguments when making horizontal bar charts.

beside

We then turned to developing a new chart that would make use of the beside argument. This argument tells a chart's bars to stack atop one another, rather than stand side by side. Like horiz, beside accepts a TRUE or FALSE value. If TRUE, the default setting, the bars will display side by side. If FALSE, the bars will be stacked. We chose to stack our bars by setting beside to FALSE.

barAllMethodsSoldiersBeside <- FALSE

Note that for the beside argument to take effect, the height argument must be in matrix form. To organize our data into a matrix, we used the matrix(...) function, whose basic format is as follows:

matrix(values, rows, columns)

Here, values is a vector containing the relevant data points, rows is the number of rows, and columns is the number of columns. Our matrix consisted of eight data points that were organized into two rows (Shu and Wei) and four columns (Fire, Ambush, Head to Head, and Surround). In the final chart, the four bars are formed by stacking the two rows within each column; the following is the code:

> barAllMethodsSoldiersBars <- matrix(c(meanShuSoldiersFire,
meanWeiSoldiersFire, meanShuSoldiersAmbush, meanWeiSoldiersAmbush,
meanShuSoldiersHeadToHead, meanWeiSoldiersHeadToHead,
meanShuSoldiersSurround, meanWeiSoldiersSurround), 2, 4)

Our stacked bar chart depicted the average number of soldiers that are engaged in each type of battle. By stacking our bars, we were able to specify what proportion of the soldiers came from the Shu and Wei armies. Thus, our chart was able to include more information in the same amount of space:

> barplot(height = barAllMethodsSoldiersBars,
main = barAllMethodsSoldiersMain,
xlab = barAllMethodsSoldiersLabX,
ylab = barAllMethodsSoldiersLabY,
names = barAllMethodsSoldiersNames,
beside = barAllMethodsSoldiersBeside)

density and angle

After beside, we used the density and angle arguments to define the shading of our bars. The density argument defines the closeness of the shaded lines. It receives either a single non-negative value for all matrix rows or a vector that contains values for each row. The angle argument specifies the angle at which the shaded lines are to be drawn. It also accepts a single value for all matrix rows or a vector containing values for each row.

Our stacked bar chart used a density of 10 for the Shu row and 25 for the Wei row:

> barAllMethodsSoldiersDensity <- c(10, 25)

It also featured an angle of 45 for the Shu and -45 for the Wei:

> barAllMethodsSoldiersAngle <- c(45, -45)

Hence, you will notice that the shading in the Shu portions of our bars is spread thinner and rises to the upper-right of the chart, whereas the shading in the Wei portions of the chart is thicker and declines towards the lower-right of the chart:

> barplot(height = barAllMethodsSoldiersBars,
main = barAllMethodsSoldiersMain,
xlab = barAllMethodsSoldiersLabX,
ylab = barAllMethodsSoldiersLabY,
names = barAllMethodsSoldiersNames,
beside = barAllMethodsSoldiersBeside,
density = barAllMethodsSoldiersDensity,
angle = barAllMethodsSoldiersAngle)

legend(...) with density, angle, and cex

In the final step, we added a legend to our chart. A legend is critical to a stacked bar chart, because it indicates the difference between its grouped regions. Our legend(...) function expanded upon the legends that we created in the previous chapter. We positioned the legend towards the upper-left side of the chart using the x and y arguments. We also specified the labels that we wanted to show in the legend (Shu and Wei). By default, the legend would have displayed the bar names (Fire, Ambush, Head to Head, and Surround). Since we needed to display the stacked segments of each bar instead, we had to specifically define them as a vector in the legend argument. Next, we incorporated the exact density and angle arguments from our barplot(...) function. This matched the legend's shading to that of our chart. To complete our legend, we used the cex argument to multiply its size by 2 times. The cex argument accepts a numeric value that indicates how much a legend should be scaled by. Increasing the size of our legend made it easier to read, thus enabling viewers to quickly distinguish between our chart's stacked regions:

> legend(x = 0.2, y = 70000, legend = c("Shu", "Wei"),
density = barAllMethodsSoldiersDensity,
angle = barAllMethodsSoldiersAngle, cex = 2)

Pop quiz

  1. In the barplot(...) function, what is the relationship between the width and space arguments?

    a. width sets the distance between the bars, while space sets the thickness of the bars.

    b. width sets the thickness of the bars, while space sets the distance between the bars.

    c. space sets the range of the bars on the x-axis, while width sets the length of the bars.

    d. space sets the length of the bars, while width sets the range of the bars on the x-axis.

  2. In the barplot(...) function, which of the following is not critical to note when using the horiz argument?

    a. It accepts either a TRUE (for horizontal bars) or FALSE (for vertical bars) value.

    b. It defaults to FALSE.

    c. When TRUE, all arguments related to the x and y axes must be swapped for the chart to display properly.

    d. When undefined, the barplot(...) function will draw horizontal bars.

  3. In the barplot(...) function, which of the following is not critical to note when using the beside argument?

    a. It accepts either a TRUE (for adjacent bars) or FALSE (for stacked bars) value.

    b. It defaults to FALSE.

    c. To take effect, the chart's height data must be in matrix form.

    d. When FALSE, it is advisable to include a legend with the chart.

Have a go hero

Use your soldiersByCity dataset to create a chart that depicts the total number of soldiers in the Shu and Wei armies as two separate bars. Then create a stacked bar chart with the same data, but separate the Shu and Wei bars into distinct sections for each city. Compare these two charts and reflect upon the pros and cons of using each.

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

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