Chapter 15
LURN… To use the BrailleR add-on package

This chapter explains how the BrailleR add-on package can be used by blind people to get many tasks done quickly and effectively. In general, the package does three things:

  1. creates a copy of hte R console/terminal in a text file including all standard output.
  2. creates text descriptions of some graphs. These tools should help the blind user create graphs (with confidence) for the sighted world we must work in.
  3. provides convenience functions for novice users who do not know enough R commands to survive. Sighted people have the benefit of graphical user interfaces (GUI) to help them, but none of them are accessible by screen reading software.

Initially, the package was built on top of functionality I wrote to support my own work practices, but additions to meet the needs of other blind R users have been made on request.

You will need to install the BrailleR package before continuing on with the examples in this chapter. It is available from CRAN. Use the examples in Chapter 14 to help install this package. Then use the library() command to make sure the package is ready for action.

  > library(BrailleR)

This chapter was created using version 0.27.0 of the BrailleR package. This version of the package has a number of other packages that it depends on for functionality. When you make the BrailleR package available, you may see a few introduction messages that tell you about the other packages being loaded. You will be told about some default settings for the package that can be altered later to suit your needs.

15.1 Creating a copy of the R console window

In Chapter 2 I mentioned the need to save the content of the console window to a text file to be able to copy and paste its content to a report or document. One major feature of the BrailleR package is that this functionality can be done easily and efficiently.

There are three types of content printed in the console window.

  1. The commands we type,
  2. The output valid commands generate, and
  3. Any error or warning messages that arise from our commands.

The sink() command does not currently record the commands or the errors and warning messages. It is therefore a valuable tool for those R users that are confident about the validity of their scripts.

Saving the commands typed into an R session can be achieved using the savehistory() command. For example

  > savehistory("WhatIDidToday.txt")

will save all the issued commands into a text file called WhatIDidToday.txt in the working directory.

If I just want to have everything I do during a session recorded for posterity, I want all contents of the console window to be saved. A plain text file is sufficient but it is possible to use add-on packages to create other file formats.

I have included a convenience function in the BrailleR package that starts a text file with the date and time in its filename. It gets saved in the current working directory. To get this file started, just type

  > txtOut()

In fact this command starts several files, one for the complete console and one for the issued commands. The command actually runs the txtStart() command but specifies particular options for the user’s convenience. If you are happy to use the defalt filename then you just need to hit <enter>, but if you want to specify the filename, you type the name, and then hit <Enter> twice (once for your file and once to get out of the filename requesting prompt).

See the help page for the txtOut() command as it includes the history of the command and its relatives. The other related commands add comments to the text file or stop the processing entirely. Also note that the help page mentions how to get the packages needed for other file formats.

You can open the text file that is being created and modified as you work in any browser. Once you have the file open and have done some work, you must refresh your browser to see the latest changes. Keep the browser open as you work and remember to refresh often to keep on top of what is happening with complete access via your screen reader.

15.2 Text interpretation of graphs

Statistics is an inherently visual discipline. Many statistical analyses lead to a graphic representation of data that is easy for the sighted world to interpret. Through use of R we can create functions that can interpret the graphs using text descriptions. We’ll start with a histogram.

In most circumstances, the user will create a histogram using the hist() command. This command takes data and creates a number of values needed to construct the histogram. We can see what has been created by storing these values in an object. For example:

  > MyHist = hist(airquality$Wind, xlab="Average wind speed (mph)", main="", plot=FALSE)

  Warning in hist.default(x = airquality$Wind, xlab = "Average wind speed (mph)", : arguments 'main', 'xlab' are not made use of

The plot argument stops the graph being plotted. We can get the graph anytime by issuing the plot() command but we are only interested in seeing what R has stored in the MyHist object at the moment.

  > MyHist

  $breaks
   [1]  0  2  4  6  8 10 12 14 16 18 20 22
  
  $counts
   [1]  1  4 11 38 27 38 10 17  4  1  2
  
  $density
   [1] 0.003268 0.013072 0.035948 0.124183 0.088235 0.124183
   [7] 0.032680 0.055556 0.013072 0.003268 0.006536
  
  $mids
   [1]  1  3  5  7  9 11 13 15 17 19 21
  
  $xname
  [1] "airquality$Wind"
  
  $equidist
  [1] TRUE
  
  $main
  [1] ""
  
  $xlab
  [1] "Average wind speed (mph)"
  
  $ExtraArgs
  $ExtraArgs$main
  [1] "Histogram of airquality$Wind"
  
  $ExtraArgs$xlab
  [1] "airquality$Wind"
  
  $ExtraArgs$ylab
  [1] "Frequency"
  
  $ExtraArgs$sub
  [1] ""
  
  
  $NBars
  [1] 11
  
  $par
  $par$xaxp
  [1] 0 1 5
  
  $par$yaxp
  [1] 0 1 5
  
  
  $xTicks
  [1] 0.0 0.2 0.4 0.6 0.8 1.0
  
  $yTicks
  [1] 0.0 0.2 0.4 0.6 0.8 1.0
  
  attr(,"class")
  [1] "Augmented" "histogram"

  > str(MyHist)

  List of 13
   $ breaks   : num [1:12] 0 2 4 6 8 10 12 14 16 18 ...
   $ counts   : int [1:11] 1 4 11 38 27 38 10 17 4 1 ...
   $ density  : num [1:11] 0.00327 0.01307 0.03595 0.12418 0.08824 ...
   $ mids     : num [1:11] 1 3 5 7 9 11 13 15 17 19 ...
   $ xname    : chr "airquality$Wind"
   $ equidist : logi TRUE
   $ main     : chr ""
   $ xlab     : chr "Average wind speed (mph)"
   $ ExtraArgs:List of 4
    ..$ main: chr "Histogram of airquality$Wind"
    ..$ xlab: chr "airquality$Wind"
    ..$ ylab: chr "Frequency"
    ..$ sub : chr ""
   $ NBars    : int 11
   $ par      :List of 2
    ..$ xaxp: num [1:3] 0 1 5
    ..$ yaxp: num [1:3] 0 1 5
   $ xTicks   : num [1:6] 0 0.2 0.4 0.6 0.8 1
   $ yTicks   : num [1:6] 0 0.2 0.4 0.6 0.8 1
   - attr(*, "class")= chr [1:2] "Augmented" "histogram"

  > class(MyHist)

  [1] "Augmented" "histogram"

The full print out has everything we need but is not in a friendly format. The str() command gives us a condensed version of the data being stored but isn’t sufficient, and the class() command just tells us that this information is stored in an object of type histogram. The class of the object is the most important as it is what tells R how to work on the object when we use the plot() command on the MyHist object. The plot() command is actually a family of commands, one of which is purposely designed for histograms. The plot.histogram() command is actually what constructs the graph when the user calls the plot() command on an object of type histogram. This family of commands is known as a method.

The BrailleR package includes a method for creating text interpretations in a similar way. The VI() command is actually a family of commands that includes the VI.histogram() command. When we issue the VI() command on the MyHist object, the VI.histogram() function does the work. Let’s see what we get:

  > VI(hist(airquality$Wind, xlab="Average wind speed (mph)", main=""))

  This is a histogram, with the title: Histogram of airquality$Wind
  "airquality$Wind" is marked on the x-axis.
  Tick marks for the x-axis are at: 0, 5, 10, 15, and 20
  There are a total of 153 elements for this variable.
  Tick marks for the y-axis are at: 0, 10, 20, and 30
  It has 11 bins with equal widths, starting at 0 and ending at 22 .
  The mids and counts for the bins are:
  mid = 1  count = 1
  mid = 3  count = 4
  mid = 5  count = 11
  mid = 7  count = 38
  mid = 9  count = 27
  mid = 11  count = 38
  mid = 13  count = 10
  mid = 15  count = 17
  mid = 17  count = 4
  mid = 19  count = 1
  mid = 21  count = 2

a histogram

link to SVG file: VIHistAirQualityWind.svg

Other functions exist for boxplots and dotplots. Try:

  > VI(boxplot(airquality$Wind, xlab="Average wind speed (mph)"))

PIC

  This graph has a boxplot printed vertically
  with the title:
  "" appears on the x-axis.
  "" appears on the y-axis.
  Tick marks for the y-axis are at: 5, 10, 15, and 20
  This variable  has 153 values.
  An outlier is marked at: 20.1 18.4 20.7
  The whiskers extend to 1.7 and 16.6 from the ends of the box,
  which are at 7.4 and 11.5
  The median, 9.7 is 56 % from the lower end of the box to the upper end.
  The upper whisker is 0.89 times the length of the lower whisker.

and

  > VI(dotplot(x))

  Error in dotplot(x): object 'x' not found

The dotplot() command is not part of base R which uses the stripchart() command instead. The hist() and boxplot() commands used here are actually commands from the BrailleR package that use the standard commands indirectly. At this point in time, I haven’t worked out how to get the stripchart() command to work as a BrailleR command so I needed to use a different name for my version. The BrailleR versions of these three commands store the additional information we need to get the text interpretation that is not possible from the standard version of the commands.

15.3 Basic descriptions of variables

The UniDesc() function is designed to quickly generate a text summary of a single variable. It also saves several graphs. It can also save the text in a file and use the VI() command from the BrailleR package to add text descriptions to the output file.

One obvious issue is that saving lots of files could become problematic. Default filenames are used and all files can be put into a folder of the user’s choosing.

An example will help. Try

  > data(airquality)
  > Ozone=airquality$Ozone
  > UniDesc(Ozone, Folder="AirQuality")

Take a look in the AirQuality folder that has been created in your working directory. It has a number of files that all start with “Ozone" — the name of the variable being analysed. You will also have three files stored in the current working directory which have the filename Ozone-UniDesc.* where the star is for the extension which is one of html, R, and Rmd.

The most useful one at first is the Ozone-UniDesc.html file. Open this file in a browser to see what analyses have been included. This file is specifically formatted for use with screen readers. I hope you find it valuable. If you are reading this document on the web, then the link Ozone-UniDesc.html will open it in your browser. The link will not work if you are using the pdf version of LURN.

The commands used to generate parts of this HTML document are given in the R script file; the third file is called an R markdown document. This is the file that gets converted into the other two files. It might prove useful to learn how to write this kind of file for yourself one day.

In the airquality subfolder you will find that graphs have been saved in a variety of formats. They each have their uses and hopefully the filetype you need is there. Special attention is made for those users of LATEX who need specific formats for graphics. Some more advanced information is presented in LATEX formatted tables and put into files with the tex extension. For example, the content of Table 15.1 were presented in the Ozone-UniDesc.html document and included in this document using the LATEXversion of that table.





StatisticP Value



Shapiro-Wilk 0.8787 0.0000
Anderson-Darling 4.5211 0.0000
Cramer-von Mises 0.8033 0.0000
Lilliefors (Kolmogorov-Smirnov) 0.1480 0.0000
Pearson chi-square 73.7241 0.0000
Shapiro-Francia 0.8786 0.0000




Table 15.1: Tests for normality: Variable is Ozone.

Whenever the VI() function is employed on an object that does not yet have an explicit function tied to it, then you will be told that this is the case. This package is a work in progress after all. Please feel free to send an email if you’d like any extra functionality.

15.4 Altering R output to make it easier to read

Some R output is arranged in nice tables that are easy for the sighted user to read, but are difficult to understand if using synthesised speech to read the information back to you. The VI() command is used again here but is now employed on a data.frame object. We’ll compare it with the summary() command used frequently.

  > summary(airquality)

       Ozone          Solar.R         Wind
   Min.   :  1.0   Min.   :  7   Min.   : 1.70
   1st Qu.: 18.0   1st Qu.:116   1st Qu.: 7.40
   Median : 31.5   Median :205   Median : 9.70
   Mean   : 42.1   Mean   :186   Mean   : 9.96
   3rd Qu.: 63.2   3rd Qu.:259   3rd Qu.:11.50
   Max.   :168.0   Max.   :334   Max.   :20.70
   NA's   :37      NA's   :7
        Temp          Month           Day
   Min.   :56.0   Min.   :5.00   Min.   : 1.0
   1st Qu.:72.0   1st Qu.:6.00   1st Qu.: 8.0
   Median :79.0   Median :7.00   Median :16.0
   Mean   :77.9   Mean   :6.99   Mean   :15.8
   3rd Qu.:85.0   3rd Qu.:8.00   3rd Qu.:23.0
   Max.   :97.0   Max.   :9.00   Max.   :31.0
  

  > VI(airquality)

  
  The summary of each variable is
  Ozone: Min. 1   1st Qu. 18   Median 31.5   Mean 42.1293103448276   3rd Qu. 63.25   Max. 168   NA's 37
  Solar.R: Min. 7   1st Qu. 115.75   Median 205   Mean 185.931506849315   3rd Qu. 258.75   Max. 334   NA's 7
  Wind: Min. 1.7   1st Qu. 7.4   Median 9.7   Mean 9.95751633986928   3rd Qu. 11.5   Max. 20.7
  Temp: Min. 56   1st Qu. 72   Median 79   Mean 77.8823529411765   3rd Qu. 85   Max. 97
  Month: Min. 5   1st Qu. 6   Median 7   Mean 6.99346405228758   3rd Qu. 8   Max. 9
  Day: Min. 1   1st Qu. 8   Median 16   Mean 15.8039215686275   3rd Qu. 23   Max. 31

The output generated by the summary() command is difficult to follow as variables are represented in columns while rows that are read aloud by a screen reader are for the sample statistics.

The VI() method has given us a summary of the variables one by one. This should prove easier to navigate and interpret as either a braille or screen reader user.

15.5 Reading a scatter plot

One challenge facing blind people is the inability to glance at a graph and understand what is intended just as sighted people can. The most difficult graphs to deal with are multidimensional representations of data. Two dimensional scatter plots are the first example of such graphs.

When a sighted person looks at a scatter plot, they are looking for a number of things. A relationship between the variables is the most common thing to look for, but there is also a need to identify points that are unusual in the context of the data presented.

One possible way to describe how the data points are summarised at a glance is that the graphing window is broken up into areas and a rough guess at the density of points within each region is evaluated. If this evaluation of density can be guessed, it can be counted more exactly by a purposely written function. The WhereXY() function does this counting for us. It assumes equal-sized rectangular regions in the graph window. We can choose how many regions but the illustrations here all use a 5×5 grid.

Let’s work with a number of examples, all based on a set of predetermined x-values and various possible y-values.

  > x=(0:100)/100
  > y1=5*x+rnorm(101)
  > y2=(2*x-1)^2+rnorm(101)/6
  > y3=11*x+rnorm(101)
  > y4=y3; y4[100]=0

What we might guess from the above is that a graph of (x,y1) pairs would show quite a lot of noise; (x,y2) pairs are a parabola with some noise; (x,y3) pairs are for a straight line with some noise; and, (x,y4) pairs are the same as the previous straight line, but one point is some distance from the line.

The WhereXY() command for each plot is now given.

  > WhereXY(x,y2, grid=c(5,5))

       1  2  3  4  5 Sum
  5    6  0  0  0  3   9
  4    3  1  0  0 12  16
  3   11  6  0  6  5  28
  2    1 11 13 12  0  37
  1    0  2  7  2  0  11
  Sum 21 20 20 20 20 101

  > WhereXY(x,y2, grid=c(5,5))

       1  2  3  4  5 Sum
  5    6  0  0  0  3   9
  4    3  1  0  0 12  16
  3   11  6  0  6  5  28
  2    1 11 13 12  0  37
  1    0  2  7  2  0  11
  Sum 21 20 20 20 20 101

  > WhereXY(x,y3, grid=c(5,5))

       1  2  3  4  5 Sum
  5    0  0  0  3 12  15
  4    0  0  4 13  8  25
  3    0  7 15  4  0  26
  2   14 12  1  0  0  27
  1    7  1  0  0  0   8
  Sum 21 20 20 20 20 101

  > WhereXY(x,y4, grid=c(5,5))

       1  2  3  4  5 Sum
  5    0  0  0  3 11  14
  4    0  0  4 13  8  25
  3    0  7 15  4  0  26
  2   14 12  1  0  0  27
  1    7  1  0  0  1   9
  Sum 21 20 20 20 20 101

We might also alter the number of cells in the grid to see how sensitive we want to make our investigation. Personal preferences will determine which combination of rows and columns works best.

15.6 Creation of graphs with an accessible interactive tool for exploration

New functions have been added to the BrailleR package in order to make accessible tools for interactive exploration of graphs. The standard commands for creation of histograms, boxplots, scatter plots and time series plots do not return the extra information needed to get the exploration tool to work. Each of the following commands creates the same graph as would be created using the commands in previous chapters. Refer to the examples found in the help pages for each of these commands to see the standard base R commands that these BrailleR functions replicate.

N.B. You must store the graph in a named object for later use.

  > attach(airquality)
  > MyScatter = ScatterPlot(Wind, Ozone)

PIC

  > MyFLP = FittedLinePlot(Temp, Ozone, line.col=4)

PIC

  > MyHist = hist(Ozone)

PIC

  > MyBoxplot = boxplot(Wind)

PIC

  > detach(airquality)

15.7 What else?

Future developments in the BrailleR package will be made to meet demand. If you do want some additional functionality that you think is likely to be wanted by others then please do add to the wish list. Current ideas on the wish list include: