info macro ) File of MacAnova macros related to graphs ) Many use features available only in MacAnova4.11 or later ) ) bargraph Macro do draw a bar graph ) colplot Make a line plot of each column of a matrix vs row ) number ) contour Trace a level curve from surface values previously ) computed on a rectangular grid ) contourplot Make a contour plot of surface values previously ) computed on a rectangular grid ) findcontour Interactively find a contour line near a point selected ) with the mouse ) labelcontour Interactively find and label a contour line near a point ) selected with the mouse ) hist Draw histogram ) panelhist Draw histogram in pane of panel graph ) panelplot Draw point, line or impulse plot in pane of panel graph ) plotmatrix Draw a scatter plot matrix, that is a panel graph with ) plots of each column of a matrix against all other ) columns or against all columns of another matrix ) plotpanes Draw point, line or impulse plots in several panes of a ) panel graph ) ellipse Compute the outline of an ellipse and optionally draw it ) piechart Draw a pie chart of positive data ) rowplot Make a line plot of each row of a matrix vs column ) number ) boxplot5num Macro to do a simple boxplot using 5 number summary ) vboxplot Macro to make a vertical boxplot ) A panel graph is a rectangular array of panes, each of which may ) contain a complete graph, but omitting tick marks, a title and axis ) labels. ) ) Help for these macros follows the last macro )) Copyright 2002 by Christopher Bingham and Gary Oerlert )) This file may be freely distributed but is not public domain. )) 010125 made improvements to boxplot5num, including new keyword )) excludeM )) 010425 fixed bug in plotmatrix )) 010801 added () to macro names in help where appropriate )) 011109 Fixed bugs in contour() and _Follow() )) 020126 Added usage bargraph(x,y,widths ...) )) 020223 Fixed bug and changed ticks and labelling in boxplot5num() )) 021022 Modified colplot() and rowplot() to ensure x-axis ticks )) are at equally spaced integers starting with 1 )) File version 031204 )) 030814 added subtopic titles to help )) 031009 'xticks' now recognized on rowplot() and colplot() )) 031204 Bugfix in hist() for case when all data are the same )) 040112 Bugfix in panelplot(); cases with MISSING values were squeezed )) out )) New keyword phrase 'gridlines:F' in panel plotting macros )) 050329 Added labelcontour(), modified contourplot() to use )) labelcontour() %info% colplot MACRO ) Macro to make a line plot of each column of a matrix vs row number ) usage: ) colplot(y [, graphics keyword phrases]) ) y REAL matrix )) 021022 x tick labels now just equally spaced integers )) 031008 xticks:vals in argument now recognized #$S(y [,title:\"Title of your choice\"][other graphics keywords]) if($v < 1){ error("$S() needs at least 1 non-keyword argument",macroname:F) } @y <- argvalue($1,"argument 1","real matrix") @n <- nrows(@y) chplot(1,@y,yaxis:F,lines:T,$K,xticks:run(1,@n,floor((@n-1)/15+1)),\ xlab:"Row Number",title:"Plot of columns vs row number") delete(@y,@n) %colplot% rowplot MACRO ) Macro to make a line plot of each row of a matrix vs column number ) usage: ) rowplot(y [, graphics keyword phrases]) ) y REAL matrix )) 021022 x tick labels now just equally spaced integers )) 031008 xticks:vals in argument now recognized #$S(y [,title:\"Title of your choice\"][other graphics keywords]) if($v < 1){ error("$S() needs at least 1 non-keyword argument",macroname:F) } @y <- argvalue($1,"argument 1","real matrix")' @n <- nrows(@y) chplot(1,@y,yaxis:F,lines:T,$K,xticks:run(1,@n,floor((@n-1)/15+1)),\ xlab:"Column Number",title:"Plot of rows vs column number") delete(@y,@n) %rowplot% boxplot5num MACRO DOLLARS ) Macro to make simplified box plot reflecting only the 5 number ) summary (min, Q1, Median, Q3, max) with no information on ) outliers ) Note: it uses a different definition of quartiles from describe() and ) boxplot(). They are the medians of the upper and lower halves ) *excluding* the median, when n is odd. describe() and boxplot() ) include the median in both halves ) NOTE: This is now more or less obsolete since keyword boxplot() ) with keyword phrase 'boxtype:2' gives this kind of plot, albeit with ) the quartiles being the medians of the upper and lower halves ) *including* the median when n is odd. ) Usage: ) boxplot5num(x [,names:Names] [excludeM:F] [,keep:T] \ ) [,graphics keyword phrases]) ) x REAL vector or a structure of REAL vectors ) Names CHARACTER scalar (x a vector) or vector (x a structure) ) When x is a structure and Names is a scalar it is ) expanded to vector("Name 1", "Name 2", ...). ) Names[i] will be printed below box i ) excludeM:T Median is excluded from upper and lower halves when computing ) quartiles with odd n; default is value of option 'excludeM'. ) keep:T Return vector or structure of vector containing 5 number ) summaries ) The form of the boxplot and the default definition of quartiles follows ) follows Moore and McCabe, Introduction to the Practice of Statistics ) and Moore, The Basic Practice of Statistics )) 010125 added keywords names, excludeM and keep )) 010327 fixed bug, made option the default value of excludeM )) 020223 fixed bug, added default title and labels )) Version of 020223 by C. Bingham, kb@stat.umn.edu # $S(x [,names:Names, graphics keyword phrases]), x a structure or REAL vector @x <- argvalue($1,"$1") if (isstruc(@x)){ @nboxes <- ncomps(@x) for(@i,1,@nboxes){ argvalue(@x[@i],paste("component",@i,"of $1"),"real vector") } }else{ @x <- structure(argvalue(@x,"$1","real vector")) @nboxes <- 1 } @excludeM <- keyvalue($K,"excludeM","TF",default:getoptions(excludeM:T)) @keep <- keyvalue($K,"keep","TF",default:F) @names <- keyvalue($K,"name*","character vector") @xticks <- 1 + run(0,@nboxes-1, 1 + floor((@nboxes-1)/20)) if (!isnull(@names)){ if (!isscalar(@names) && length(@names) != @nboxes){ error("wrong number of names supplied") } if (@nboxes > 20){ @names <- @names[@xticks] } } else { @names <- paste(@xticks,multiline:T) } if (@nboxes > 1 && isscalar(@names)){ @names <- getlabels(vector(run(@nboxes),labels:@names)) } @d <- .33 # half width of boxes @add <- F @result <- if (!@keep) { NULL } else { if (@nboxes > 1) { @cnames <- @names for (@j,1,@nboxes){ if (!isname(@names[@j])){ @cnames <- getlabels(vector(run(@nboxes),labels:"Box_")) break } } split(matrix(rep(?,5*@nboxes),5),compnames:delete(@cnames,return:T)) } else { structure(rep(?,5)) } } for (@i,1,@nboxes){ @y <- @x[@i] @y <- sort(@y[!ismissing(@y)]) @n <- length(@y) if (@n == 0) { if (@nboxes == 1){ error("No non-MISSING data; can't make boxplot") } print(paste("WARNING: no non-MISSING data for box",@i),macroname:T) } else { if (@n == 1) { @J <- 1 } else { @J <- run(floor(@n/2)) if (!@excludeM && @n/2 - floor(@n/2) > .1) { # odd n @J <- run((@n+1)/2) } } @fn <- vector(min(@y),describe(@y[@J],median:T), describe(@y,median:T),\ describe(@y[@n+1 - @J],median:T), max(@y)) # 5 number summary lineplot(vector(@i-@d,@i+@d,?,\ @i,@i,?,\ @i-@d,@i+@d,@i+@d,@i-@d,@i-@d,?,\ @i-@d,@i+@d,?,\ @i,@i,?,\ @i-@d,@i+@d),\ vector(@fn[1],@fn[1],?,\ @fn[1],@fn[2],?,\ @fn[2],@fn[2],@fn[4],@fn[4],@fn[2],?,\ @fn[3], @fn[3],?,\ @fn[4], @fn[5],?,\ @fn[5],@fn[5]), add:@add,xticks:NULL,yticks:NULL,show:F) @add <- T if (@keep) { @result[@i] <- @fn } } } if (!@add) { print("WARNING: no data to plot",macroname:T) } else { @x <- vector(@x) @x <- @x[!ismissing(@x)] @ymin <- min(@x) @ymax <- max(@x) @r <- @ymax - @ymin # range @ymin <-- .05*@r # adjust y extremes @ymax <-+ .05*@r @pad <- if (@nboxes > 5){ 1 }else{ (6 - @nboxes)/2 } showplot(notakey:NULL,$K,xmin:1-@pad,xmax:@nboxes+@pad,\ ymin:@ymin,ymax:@ymax,yaxis:F,xlab:"Box Number",title:"5 Number Box Plot",\ xticks: @xticks,xticklen:0,yticks:?,xticklabs:@names) delete(@ymin, @ymax, @r, @pad,@J, @d, @fn) } delete(@x,@y,@i,@add,@excludeM, @xticks) if (delete(@nboxes,return:T) == 1 && delete(@keep, return:T)){ @result <- @result[1] } delete(@result, return:T) %boxplot5num% vboxplot MACRO ) Macro to make vertically oriented box plots ) usage: vboxplot(x1,x2,...[optional graphics keywords]) or ) vboxplot(struc [optional graphics keywords]) ) Arguments are the same as for boxplot )) Version of 000830 #usage: $S(x1,x2, ... [,keywords] or $S(struct [,keywords]) if ($v == 0){ error("no data provided") } if($k>0){ boxplot($V,$K,vertical:T) }else{ boxplot($V,vertical:T) } %vboxplot% contourplot MACRO DOLLARS ) Macro to make contour plot of surface values on a rectangular ) grid. ) Usage: ) contourplot(x,y,values,levels [,label:T] [,linefrom:T] [,save:T]\ ) [,draw:T] [,graphics keywords]) ) x, y REAL vectors containing distinct non-MISSING values ) for gridlines ) values REAL nx by ny matrix, nx = nrows(x), ny = nrows(y), ) with values[i,j] = F(x[i],y[j]), where z = F(x,y) ) is the surface to be plotted. values[i,j] should ) be MISSING if F(x[i],y[j]) is not defined ) levels REAL vector of distinct non-MISSING contour levels ) label:T enables interactive labeling of contours with ) contour levels; you select one position for a label ) for each contour drawn ) linefrom:T Like label:T, except you specify the ends of a line ) starting at the contour and ending at the label ) draw:F suppresses drawing contours, but returns contour ) coordinates; see 'save'. default is T ) save:T returns a structure with a component for each level; ) each component is either structure(x:NULL, y:NULL, ) lines:T, level:level) when the contour is empty ) or structure(x:xvals, y:yvals, lines:T, level:level), ) otherwise. The default is T with draw:F, F otherwise ) ) Requires macros contour(), findcontour(), labelcontour() and _Follow() ) which are based on Fortran routines by Dan LaLiberte, implementing ) methods in ) Crane, C.M.(1972). Contour plotting algorithm, 'The Computer ) Journal', Vol. 15, pp.382-384. ) Cottafava, G., Andle Moli, G. (1969). Automatic Contour Map, ) 'comm. ACM', Vol. 12, pp.386-391. )) Written by C. Bingham, kb@stat.umn.edu )) Version 001001 surface array can contain MISSING values )) 050329 now uses new macro labelcontour() to add labels # $S(x,y,vals,contours [,label:T] [,save:T][graphics keywords]) @x <- vector(argvalue($1,"x coordinates","nonmissing real vector")) @y <- vector(argvalue($2,"y coordinates","nonmissing real vector")) @f <- matrix(argvalue($3,"surface values","real matrix")) @levels <- vector(argvalue($4,"contour levels","nonmissing real vector")) @keys <- strconcat($K,notakey:NULL,silent:T) @draw <- keyvalue(@keys,"draw","TF",default:T) @save <- keyvalue(@keys,"save","TF",default:!@draw) @linefrom <- keyvalue(@keys,"linefrom","TF",default:F) @label <- keyvalue(@keys,"label*","TF",default:@linefrom) if (!@save && !@draw){ error("you can't use 'save:F' with 'draw:F'") } if ((@label || @linefrom) && !@draw) { print("WARNING: 'label:T' and 'linefrom:T' ignored when not drawing",\ macroname:T) @label <- @linefrom <- F } if (!@label && @linefrom) { print("WARNING: 'linefrom:T' ignored with 'label:F'",macroname:T) @linefrom <- F } @linetype <- keyvalue(@keys,"linetype","positive count",default:1) @show <- keyvalue(@keys,"show","TF",default:T) @add <- keyvalue(@keys,"add","TF",default:F) if (!@show && @label) { print("WARNING: 'label' and/or 'linefrom' ignored with show:F",macroname:T) @label <- @linefrom <- F } @keynames <- compnames(@keys) @J <- match(vector("notakey","save","draw","linefrom","label*","add"),\ @keynames,0,exact:F) # not wanted graph keywords if (@save) { @grkeys <- if (sum(@J > 0) == length(@keynames)){ NULL } elseif (max(@J) == 0) { @keys } else { @J <- @J[@J > 0] strconcat(@keys[-@J],compnames:@keynames[-@J]) } delete(@J) } @nx <- nrows(@x) @ny <- nrows(@y) @ncn <- nrows(@levels) @errormsg <- if (nrows(@f) != @nx || ncols(@f) != @ny){ "lengths of x and y don't match dimensions of surface values" } elseif (@nx < 3 || @ny < 3) { "both x and y must have length >= 3" } elseif (length(unique(@x)) != @nx || length(unique(@y)) != @ny) { "elements of x and/or y not all different" } elseif (length(unique(@levels)) != @ncn){ "elements of contour levels not all different" } elseif (sum(!ismissing(vector(@f))) == 0) { "all surface heights are MISSING" } else { NULL } if (!isnull(@errormsg)) { error(@errormsg) } delete(@nx,@ny, @errormsg) @Jx <- grade(@x) @Jy <- grade(@y) @x <- @x[@Jx] # reorder @x in increasing order @y <- @y[@Jy] # reorder @y in increasing order @f <- @f[@Jx,@Jy] # rearrange @f to match delete(@Jx,@Jy) if (@save){ @result <- split(rep(0,@ncn)',compnames:"Contour_") } @ncontours <- 0 if (!ismacro(contour)) { getmacros(contour,silent:T) } for (@i,1,@ncn) { @contour <- contour(@x,@y,@f,@levels[@i],F) if (@save) { @result[@i] <- if (isnull(@grkeys)){ @contour } else { strconcat(@contour,@grkeys) } } if (!isnull(@contour$x)) { lineplot(@contour,linetype:@linetype,add:@add,show:F) @ncontours <-+ 1 @add <- T } } delete(@ncn) @exclkeys <- vector("linetype","linefrom","lines","label*","save",\ "add", "draw") @J <- unique(match(@exclkeys,@keynames,0,exact:F)) @J <- @J[@J != 0] if (!isnull(@J)){ @keys <- strconcat(@keys[-@J],compnames:@keynames[-@J]) } if (@draw) { showplot(key:strconcat(@keys,xmin:min(@x),xmax:max(@x),\ ymin:min(@y),ymax:max(@y))) } if (delete(@label,return:T) && @ncontours > 0) { if (!ismacro(labelcontour)) { getmacros(labelcontour,silent:T) } labelcontour(@x,@y,@f,@levels,@ncontours,linefrom:@linefrom,check:F) } delete(@x,@y,@f,@levels,@i,@ncontours) if (delete(@save,return:T)) { delete(@result, return:T) } else { NULL } %contourplot% contour MACRO DOLLARS ) Macro to find contour path for a surface z = F(x,y) from ) values at a rectangular grid ) Usage: ) contour(x,y,f,level [,checkargs] [,graphics keyword phrases]) ) x, y REAL vectors containing distinct non-MISSING values ) for gridlines ) f REAL nrows(x) by nrows(y) matrix, where f[i,j] = ) F(x[i], y[i]), where z = F(x,y) is the surface being ) contoured. If F(x[i],y[j]) is not defined, f[i,j] ) should be MISSING ) level non MISSING REAL scalar, normally between the minimum ) and maximum value of F(x,y) ) checkargs optional LOGICAL scalar, default F. When checkargs ) is F, x, y, and f are assumed OK with x and y in ) increasing order ) ) Value: ) structure(x:xc,y:yc,level:level [, graphics keyword phrases]) ) xc, yc REAL vectors with the same length providing the ) coordinates of the intersections of the contour with ) the gridlines. Disconnected segments are separated by ) MISSING. When level is outside the range of values, xc ) and yc are both NULL. ) ) Graphics keyword phrases such as add:T and lines:T are directly passed ) through to the output structure. ) ) Provided it is not NULL, a contour can be plotted by, e.g., ) lineplot(contour(x,y,f,level) [, add:T]) ) or ) GRAPHWINDOWS[i] <- contour(x,y,f,level,lines:T [, add:T]) ) ) x, y and f are copied to arrays __X__, __Y__ and __F__, respectively ) Status information used in following contours is in array __MET__ ) ) __MET__[i,j] codes information about the left and bottom borders of ) the "cell" with lower left corner at __X__[i] and __Y__[j]. ) ) __MET__[i,j] = a + 2*b, with a and b either 0 or 1. ) a = 1 (__MET__[i,j] = 1 or 3) only if the left border (vertical ) from corner has been crossed. ) b = 1 (__MET__[i,j] >= 2) if and only if the bottom border ) (horizontal from corner) has been crossed. ) When f[i,j] is MISSING, __MET__[i,j] is set to 3, __MET__[i-1,j] ) is incremented by 1 and __MET__[i,j-1] is incremented by 2 ) ) Adapted by C. Bingham (kb@stat.umn.edu) from a Fortran program by ) Dan LaLiberte written on the basis of the following: ) Crane,C.M.(1972). Contour plotting algorithm, The Computer Journal, ) Vol. 15, pp.382-384. ) Cottafava,G., Andle Moli,G. (1969). Automatic contour map, Comm. ACM, ) Vol. 12, pp.386-391. ) ) Requires macro _Follow )) 001001 modified so that it behaves correctly when there are )) MISSING values in F. All edges adjacent to a MISSING value )) are treated as having been crossed )) 011109 Fixed serious bugs in scanning boundaries for possible )) entrance point; also fixed similar problem in _Follow )) Version 011109 #$S(x,y,values,level [,checkargs] [,keyword phrases]) if (!ismacro(_Follow)){ getmacros(_Follow,quiet:T,printname:F) if (!ismacro(_Follow)){ error("macro _Follow not available") } } __X__ <- vector(argvalue($1,"x coordinates","nonmissing real vector")) __Y__ <- vector(argvalue($2,"y coordinates","nonmissing real vector")) __F__ <- matrix(argvalue($3,"surface values","real matrix")) @checkargs <- if ($v > 4){ argvalue($5,"argument 5","TF") }else{ T } @level <- argvalue($4,"contour level","number") @n1 <- nrows(__X__) @n2 <- nrows(__Y__) if (@checkargs) { @errmsg <- if (nrows(__F__) != @n1 || ncols(__F__) != @n2){ "length of x and/or y doesn't match dimension of surface values" } elseif (@n1 < 3 || @n2 < 3) { "both x and y must have length >= 3" } elseif (length(unique(__X__)) != @n1 || length(unique(__Y__)) != @n2) { "elements of x and/or y not all different" } elseif (sum(!ismissing(vector(__F__))) == 0) { "all surface heights are MISSING" } else { NULL } if (!isnull(@errmsg)) { delete(__X__,__Y__,__F__) error(@errmsg) } delete(@errmsg) } @warnopt <- getoptions(warning:T) setoptions(warning:F) if (@level < min(vector(__F__)) || @level > max(vector(__F__))) { @contour <- structure(x:NULL,y:NULL) } else { if (@checkargs){ # Sort __X__ and __Y__ and rearrange __F__ to match @Jx <- grade(__X__) @Jy <- grade(__Y__) __X__ <- __X__[@Jx] __Y__ <- __Y__[@Jy] __F__ <- __F__[@Jx,@Jy] # rearrange __F__ to match delete(@Jx,@Jy) } __MET__ <- matrix(rep(0,@n1*@n2),@n1) @anymiss <- anymissing(__F__) if (@anymiss){ # mark all edges adjacent to missing as having been crossed @J <- ismissing(__F__) __MET__[vector(@J)] <- 3 @J1 <- vector(hconcat(@J[,-1],rep(F,@n2)))# shift down __MET__[@J1] <- 2 @J1 <- vector(hconcat(@J[-1,]',rep(F,@n1))') __MET__[@J1] <- __MET__[@J1] + 1 __MET__[vector(@J)] <- 3 #print(format:"2.0f",__MET__',1*@J') delete(@J1) } @xc <- @yc <- NULL #scan border and interior points for start of contour # first scan left edge, bottom to top @f <- __F__[1,]' @J <- (@level >= @f[-@n2] && @level < @f[-1]) || \ (@level < @f[-@n2] && @level >= @f[-1]) if (@anymiss){ @J[ismissing(@J)] <- F } if (sum(@J && __MET__[1,-@n2]' < 2) != 0) { for(@j,1,@n2-1) { if (alltrue(@J[@j],__MET__[1,@j] < 2)) { @s <- _Follow(1,@j,1,@level) if (length(@s$x) > 1) { @xc <- vector(@xc,@s$x,?) @yc <- vector(@yc,@s$y,?) } } } } #scan top edge left to right @f <- __F__[,@n2] @J <- @level >= @f[-@n1] && @level < @f[-1] || \ @level < @f[-@n1] && @level >= @f[-1] if (@anymiss){ @J[ismissing(@J)] <- F } if (sum(@J && __MET__[-@n1,@n2] %% 2 == 0) != 0) { for(@i,1,@n1-1) { if (alltrue(@J[@i], __MET__[@i,@n2] %% 2 == 0)){ @s <- _Follow(@i,@n2,2,@level) if (length(@s$x) > 1) { @xc <- vector(@xc,@s$x,?) @yc <- vector(@yc,@s$y,?) } } } } #scan right edge, bottom to top @f <- __F__[@n1,]' @J <- @level >= @f[-1] && @level < @f[-@n2] || \ @level < @f[-1] && @level >= @f[-@n2] if (@anymiss){ @J[ismissing(@J)] <- F } if (sum(@J && __MET__[@n1,-@n2]' < 2) != 0) { for(@j,1,@n2-1) { if (alltrue(@J[@j], __MET__[@n1,@j] < 2)) { @s <- _Follow(@n1,@j,3,@level) if (length(@s$x) > 1) { @xc <- vector(@xc,@s$x,?) @yc <- vector(@yc,@s$y,?) } } } } # scan bottom edge, left to right and interior by rows for (@j,1,@n2-1) { @f <- __F__[,@j] @J <- @level >= @f[-1] && @level < @f[-@n1] || \ @level < @f[-1] && @level >= @f[-@n1] if (@anymiss){ @J[ismissing(@J)] <- F } if (sum(@J && __MET__[-@n1,@j] %% 2 == 0) != 0) { for(@i,1,@n1-1) { if (alltrue(@J[@i],__MET__[@i,@j] %% 2 == 0)){ @s <- _Follow(@i,@j,4,@level) if (length(@s$x) > 1) { @xc <- vector(@xc,@s$x,?) @yc <- vector(@yc,@s$y,?) } } } } } if (isnull(@xc)) { @contour <- structure(x:NULL,y:NULL,level:@level) } else { @contour <- structure(x:@xc[-length(@xc)], y:@yc[-length(@yc)],\ level:@level) } delete(@i,@j,@xc,@yc,@s,@J,@f,__MET__,silent:T) } setoptions(warning:@warnopt) delete(@n1,@n2,@level,__X__,__Y__,__F__) if ($k > 0) { @contour <- strconcat(@contour,$K,notakey:NULL,silent:T)[-($k+4)] } delete(@contour,return:T) %contour% findcontour MACRO DOLLARS ) Macro using Mouse() to locate nearest contour and estimated value ) for the purpose of adding a label ) Usage: ) info <- findcontour(x,y,f,levels [,linefrom:T] [,check:F]) ) x, y REAL vectors with distinct values associated with ) gridlines ) f REAL nrows(x) by nrows(y) matrix, with f[i,j] = ) F(x[i],y[j]), where F(x,y) is function being contoured ) levels REAL vector of distinct contour levels ) ) no linefrom:T you use mouse to select one point in contour plot ) linefrom:T you use the mouse to select two points specifying the ) line from the curve to another location, usually where ) a label is to be printed ) check:F Do not check arguments for validity ) ) info structure(x:x0,y:y0, level:lev0, value:val0) ) x0, y0 REAL scalars (no linefrom:T) or REAL vectors of length 2 ) (linefrom:T) selected using Mouse() ) val0 Interpolated value at (x0[1],y0[1]) ) lev0 Element of levels whose value is closest to val0 ) ) findcontour is designed to allow interactive labelling of contour levels ) Cmd> info <- findcontour(levels,x,y,f) ) Cmd> addstrings(info$x,info$y,string:paste(info$level)) ) or ) Cmd> info <- findcontour(levels,x,y,f,linefrom:T) ) Cmd> addlines(info$x,info$y,show:F) ) Cmd> addstrings(info$x[2],info$y[2],string:paste(info$level)) ) ) Adapted by C. Bingham (kb@stat.umn.edu) from a Fortran program by ) Dan LaLiberte written on the basis of the following: ) Crane,C.M.(1972). Contour plotting algorithm, The Computer Journal, ) Vol. 15, pp.382-384. ) Cottafava,G., Andle Moli,G. (1969). Automatic contour map, Comm. ACM, ) Vol. 12, pp.386-391. )) Version 000822 ))050329 corrected comments ))050331 added keyword 'check' #$S(x,y,values,levels [,linefrom:T]) if (keyvalue($K,"check*","TF",default:T)) { @x <- argvalue($1,"x","nonmissing real vector") @y <- argvalue($2,"y","nonmissing real vector") @f <- argvalue($3,"surface values","real matrix") @contours <- sort(vector(argvalue($4,"contour levels",\ "nonmissing real vector"))) } else { @x <- $1 @y <- $2 @f <- $3 @contours <- sort(vector($4)) } @linefrom <- keyvalue($K,"linefrom","TF",default:F) @nx <- nrows(@x) @ny <- nrows(@y) @ncn <- nrows(@contours) @errmsg <- if (nrows(@f) != @nx || ncols(@f) != @ny){ "lengths of x and y don't match dimensions of surface values" } elseif (@nx < 3 || @ny < 3) { "both x and y must have length >= 3" } elseif (length(unique(@x)) != @nx || length(unique(@y)) != @ny) { "values of x and/or y not all different" } else { NULL } if (!isnull(@errmsg)) { error(@errmsg) } delete(@errmsg) @Jx <- grade(@x) @Jy <- grade(@y) @x <- @x[@Jx] # reorder @x in increasing order @y <- @y[@Jy] # reorder @y in increasing order @f <- @f[@Jx,@Jy] # rearrange @f to match delete(@Jx,@Jy) @where <- if(@linefrom){ # get two points Mouse(getline:T,cancelok:T) } else { # get one points Mouse(getpoints:T,cancelok:T) } if (isnull(@where)) { # cancelled by 'q' return(delete(@where,return:T)) } @x0 <- @where$x[1] @y0 <- @where$y[1] # find which contour the point (@x0,@y0) is closest to @i <- if(@x0 <= @x[1]) { 1 } elseif(@x0 > @x[@nx]) { @nx - 1 } else { # min(run(@nx-1)[@x0 <= @x[-1]]) } @j <- if(@y0 <= @y[1]) { 1 } elseif(@y0 > @y[@ny]) { @ny - 1 } else { min(run(@ny-1)[@y0 <= @y[-1]]) } delete(@nx,@ny) # point is in square @i,@j # find approximate F(@x0,@y0) by interpolation @a <- vector(@f[@i + run(0,1),@j + run(0,1)]) @nmissing <- sum(ismissing(@a)) if (@nmissing < 4){ @warnopt <- getoptions(warnings:T) setoptions(warnings:F) @suma <- sum(@a) setoptions(warnings:@warnopt) if (@nmissing == 3){ @a[] <- @suma } elseif (@nmissing == 2) { if (ismissing(@a[1])) { if (ismissing(@a[2])) { @a[1] <- @a[3] @a[2] <- @a[4] } elseif (@ismissing(@a[3])) { @a[1] <- @a[2] @a[3] <- @a[4] } else { @a[1] <- @a[4] <- @suma/2 } } else { if (!ismissing(@a[2])){ @a[3] <- @a[1] @a[4] <- @a[2] } elseif (!ismissing(@a[3])) { @a[2] <- @a[1] @a[4] <- @a[3] } else { @a[2] <- @a[3] <- @suma/2 } } } elseif (@nmissing = 1) { if (ismissing(@a[1])) { @a[1] <- @suma - 2*@a[4] } elseif (ismissing(@a[2])) { @a[2] <- @suma - 2*@a[3] } elseif (ismissing(@a[3])) { @a[3] <- @suma - 2*@a[2] } else { @a[4] <- @suma - 2*@a[1] } } @w1 <- (@x0 - @x[@i])/(@x[@i+1] - @x[@i]) @w2 <- (@y0 - @y[@j])/(@y[@j+1] - @y[@j]) @value <- (1-@w1)*((1-@w2)*@a[1] + @w2*@a[3]) +\ @w1*((1-@w2)*@a[2] + @w2*@a[4]) delete(@w1,@w2) #find index of contour with value nearest to @value @k <- if(@value <= @contours[1]) { 1 } elseif(@value > @contours[@ncn]) { @ncn - 1 } else { min(run(@ncn-1)[@value <= @contours[-1]]) } if (abs(@value - @contours[@k+1]) < abs(@value - @contours[@k])) { @k <-+ 1 } @level <- @contours[@k] delete(@k) } else { @level <- @value <- ? } delete(@a) delete(@i,@j,@contours,@x0,@y0,@x,@y,@f,@ncn) strconcat(delete(@where,return:T), value:delete(@value,return:T),\ level:delete(@level,return:T)) %findcontour% labelcontour macro dollars ) Macro to label contours in contour plot ) Usage: ) labelcontour(x,y,values,levels [,n] [,linefrom:T] [,check:F]) ) x, y nonMISSING REAL vectors of lengths nx and ny ) values REAL nx by ny matrix ) levels nonMISSING REAL vector, usually with elements between ) the minimum and maximum elements in values ) n positive integer, default 1 ) linefrom:T Draw line to contour ) check:F No checking of arguments (use only when arguments known ) to be OK ))050329 written by C. Bingham, kb@umn.edu if (keyvalue($K,"check*","TF",default:T)) { @x <- argvalue($1,"x","nonmissing real vector") @y <- argvalue($2,"y","nonmissing real vector") @values <- matrix(argvalue($3,"values","real matrix")) @levels <- sort(argvalue($4,"levels","nonmissing real vector")) @nx <- nrows(@x) @ny <- nrows(@y) @ncn <- nrows(@levels) @errormsg <- if (nrows(@values) != @nx || ncols(@values) != @ny){ "lengths of x and y don't match dimensions of surface values" } elseif (@nx < 3 || @ny < 3) { "both x and y must have length >= 3" } elseif (length(unique(@x)) != @nx || length(unique(@y)) != @ny) { "elements of x and/or y not all different" } elseif (length(unique(@levels)) != @ncn){ "elements of contour levels not all different" } elseif (sum(!ismissing(vector(@values))) == 0) { "all surface heights are MISSING" } else { NULL } if (!isnull(@errormsg)) { error(@errormsg) } delete(@nx,@ny, @errormsg, @ncn) } else { @x <- $1 @y <- $2 @values <- $3 @levels <- $4 } @n <- if ($v > 4) { argvalue($5,"n","positive count") } else { 1 } @linefrom <- keyvalue($K,"linefrom*","TF",default:F) if (!ismacro(findcountour)){ getmacros(findcontour,silent:T) } for (@i,1,@n) { @where <- findcontour(@x,@y,@values,@levels,linefrom:@linefrom,check:F) if (isnull(@where)) { # Mouse() cancelled by pressing 'q' break } @ch <- paste(@where$level,missing:"?") if (!@linefrom) { GRAPHWINDOWS[@where$window] <-\ strconcat(@where,string:@ch,just:"l",add:T) } else { addlines(GRAPHWINDOWS[@where$window],@where[run(2)],show:F) @just <- if (@where$x[2] >= @where$x[1]) { "l" }else { "r" } addstrings(@where$x[2],@where$y[2],string:@ch,just:@just,show:F) GRAPHWINDOWS[@where$window] <- LASTPLOT delete(@just) } } delete(@x,@y,@values,@levels,@n,@linefrom,@i,@ch) %labelcontour% _Follow MACRO DOLLARS ) Macro used by contour to follow a contour of a surface z = F(x,y) ) from values defined by matrix __F__ at a rectangular grid of points ) (__X__[i],__Y__[j]) with __F__[i,j] = F(__X__[i],__Y__[j]) ) Usage: ) _Follow(i,j,in,level) ) i integer, 1 <= i <= length(__X__) ) j integer, 1 <= j <= length(__Y__) ) in integer, 1 <= in <= 4 ) level non-MISSING REAL scalar ) ) The contour starts at an edge of the square indexed by i and j, ) in = 1 entrance is on left edge of overall rectangle ) in = 2 entrance is on top edge of overall rectangle ) in = 3 entrance is on right edge of overall rectangle ) in = 4 entrance is on bottom edge of one of the strips parallel ) the bottom edge of the overall rectangle ) ) Adapted by C. Bingham (kb@stat.umn.edu) from a Fortran program by ) Dan LaLiberte written on the basis of the following: ) Crane,C.M.(1972). Contour plotting algorithm, The Computer Journal, ) Vol. 15, pp.382-384. ) Cottafava,G., Andle Moli,G. (1969). Automatic contour map, Comm. ACM, ) Vol. 12, pp.386-391. )) 001001 modified so that it behaves correctly when there are )) MISSING values in F. All edges adjacent to a MISSING value )) are treated as having been crossed )) 011108 Fixed serious bug in finding whether level was between two )) values )) Version 011108 # $S(i, j, in, level) @i <- $1 @j <- $2 @in <- $3 @level <- $4 @n1 <- length(__X__) @n2 <- length(__Y__) @xp <- @yp <- rep(0,@n1*@n2) # provide plenty of room # compute starting position @a <- __F__[@i,@j] @N <- 1 if (@in == 1 || @in == 3) { # entrance is on left (1) or right (2) edges of overall rectangle @y1 <- __Y__[@j] @y2 <- __Y__[@j+1] @b <- __F__[@i,@j+1] @xp[@N] <- __X__[@i] @yp[@N] <- @y1 + (@level - @a)*(@y2 - @y1)/(@b - @a) if (@in == 3) { @i <-- 1 } @lin <- 4 - @in #swap 1 & 3 } else { # entrance is on top (2) or bottom (4) edges of overall rectangle @b <- __F__[@i+1,@j] @x1 <- __X__[@i] @x2 <- __X__[@i+1] @xp[@N] <- __X__[@i] + (@level - @a)*(@x2 - @x1)/(@b - @a) @yp[@N] <- __Y__[@j] if (@in == 2) { @j <-- 1 } @lin <- 6 - @in #swap 2 & 4 } # search the cell that was entered for an exit @done <- F while (!@done) { for(@in,1,3) { #start from entrance side and go clockwise @nin <- 1 + (@in + @lin - 1) %% 4 if (@nin == 1) { # look at side 3 for entrance to side 1 of next cell @i1 <- @i + 1 @met <- __MET__[@i1,@j] if (@met < 2) { @a <- __F__[@i1,@j] @b <- __F__[@i1,@j+1] if (anytrue((@level - @a)*(@level - @b) < 0,\ @level == min(@a,@b))){ @N <-+ 1 @i <-+ 1 @xp[@N] <- __X__[@i] @y1 <- __Y__[@j] @y2 <- __Y__[@j+1] @yp[@N] <- @y1 + (@level - @a)*(@y2 - @y1)/(@b - @a) __MET__[@i,@j] <- @met + 2 if (@i == @n1) { @done <- T } else { @lin <- 3 } break # from for loop } } } elseif (@nin == 2) { # look at side 4 for entrance to side 2 of next cell @met <- __MET__[@i,@j] if (@met %% 2 == 0){ @a <- __F__[@i,@j] @b <- __F__[@i+1,@j] if (anytrue((@level - @a)*(@level - @b) < 0,\ @level == min(@a,@b))){ @N <-+ 1 @x1 <- __X__[@i] @x2 <- __X__[@i+1] @xp[@N] <- @x1 + (@level - @a)*(@x2 - @x1)/(@b - @a) @yp[@N] <- __Y__[@j] __MET__[@i,@j] <- @met + 1 if (@j == 1) { @done <- T } else { @j <-- 1 @lin <- 4 } break # from for loop } } } elseif (@nin == 3) { # look at side 1 for entrance to side 3 of next cell @met <- __MET__[@i,@j] if (@met < 2) { @a <- __F__[@i,@j+1] @b <- __F__[@i,@j] if (anytrue((@level - @a)*(@level - @b) < 0,\ @level == min(@a,@b))){ @N <-+ 1 @xp[@N] <- __X__[@i] @y1 <- __Y__[@j+1] @y2 <- __Y__[@j] @yp[@N] <- @y1 + (@level - @a)*(@y2 - @y1)/(@b - @a) __MET__[@i,@j] <- @met + 2 if (@i == 1) { @done <- T } else { @i <-- 1 @lin <- 1 } break # from for loop } } } else { # look at side 2 for entrance to side 4 of next cell @j1 <- @j + 1 @met <- __MET__[@i,@j1] if (@met %% 2 == 0) { @a <- __F__[@i+1,@j1] @b <- __F__[@i,@j1] if (anytrue((@level - @a)*(@level - @b) < 0,\ @level == min(@a,@b))){ @N <-+ 1 @j <-+ 1 @x1 <- __X__[@i+1] @x2 <- __X__[@i] @xp[@N] <- @x1 + (@level - @a)*(@x2 - @x1)/(@b - @a) @yp[@N] <- __Y__[@j] __MET__[@i,@j] <- @met + 1 if (@j == @n2) { @done <- T } else { @lin <- 2 } break # from for loop } } } @done <- @in == 3 } # for(@in,1,3) } # while(!@done) delete(@done,@i,@j,@i1,@j1,@nin,@in,@n1,@n2,@met,@x1,@x2,Xy1,@y2,silent:T) structure(x:padto(delete(@xp,return:T),@N),y:padto(delete(@yp,return:T),@N)) %_Follow% plotpanes MACRO dollars ) Macro to combine several scatter plots in a rectangular ) array of small graphs. No value information such as labelled ) ticks is added to the small graphs ) ) Usage: ) plotpanes(x,y [,addlabels:F or labels:labs] [,names:vector(xname,yname)]\ ) [,hstrips:h, vstrips:v] [,gridlines:F] [,graphics keyword phrases]) ) x, y REAL matrices or vectors. If neither are vectors ) they must have the same number of columns; a vector ) argument is replicated to the same number of columns ) as the other argument ) When nrows(x) <= 2, each column is "expanded" to equally ) spaced values like the first argument to plot(); otherwise, ) nrows(x) = ncols(y) is required ) labs structure(labx,laby), where labx and laby are CHARACTER ) scalars or vectors ) xname,yname CHARACTER scalars used to construct x-axis and y-axis ) labels and a title. ) h, v integer scalars > 0 such that h*v > max(ncols(x),ncols(y)) ) specifying the number of horizontal and vertical strips in ) the plot. ) gridlines:F Suppress gridlines between panes ) ) Legal graphics keywords ) window, show, title, xlab, ylab, xmin, xmax, ymin, ymax, xaxis, ) yaxis, lines, linetype, impulses and keywords having to do with ) files ) NOTE: ) xlab, ylab and title override labels constructed from xname and yname. ) The values for xmin, xmax, ymin and ymax should either be scalars ) to be used in all graphs, or vectors with lengths matching ncols(x) ) or ncols(y). As usual, a MISSING value means it should be ) computed from the data ) Illegal graphics keywords ) add, logx, logy, and any keywords having to do with tick marks. ) ) Without addlabels:F or with labels:labs, you interactively ) position max(ncolx(x),ncols(y)) labels in each small plot ) Without 'labels:labs', labels are taken from the column labels ) of x and/or y if they exist or are "X1", "X2", ... and "Y1", "Y2", ) ... if not. ) ) When labels:structure(labx,laby) is an argument and labx and/or laby ) is not a scalar, their lengths must match ncols(x) and ncols(y), ) respectively. When labx is a scalar and ncol(x) > 1, labx is ) expanded by appending "1", "2", ..., and similarly for laby ) ) Written by C. Bingham (kb@stat.umn.edu) ) Version of 000818 uses panelplot )) 040112 modified descriptive comments to include gridlines:F which is passed )) on to panelplot() #$S(x, y [graphics keywords]) @x <- matrix(argvalue($1,"argument 1","real matrix")) @y <- matrix(argvalue($2,"argument 2","real matrix")) if (sum(vector(ismissing(@x))) == length(@x)) { error("no non-MISSING data in x") } if (sum(vector(ismissing(@y))) == length(@y)) { error("no non-MISSING data in y") } @ncx <- ncols(@x) @ncy <- ncols(@y) @nrx <- nrows(@x) @nry <- nrows(@y) if ($k > 0){ @keys <- structure($K,notakey:NULL,silent:T) } else { @keys <- structure(notakey:NULL) } @keynames <- compnames(@keys) @key <- keyvalue(@keys,"key*","structure") if (!isnull(@key)){ if ($k > 1) { @j <- match("key*",@keynames,0,exact:F) error(paste("you can't use any other keywords with '",\ @keywords[@j],"'",sep:"")) } @keys <- delete(@key,return:T) @keynames <- compnames(@keys) } @namex <- if(@ncx > 1){ "Cols of X" } elseif (@nrx == @nry) { "X" } else { "Index" } @namey <- if(ncols(@y) > 1){ "Cols of Y" } else { "Y" } @names <- keyvalue(@keys,"name*","character vector",\ default:vector(@namex,@namey)) if (length(@names) != 2) { error("values for 'names' not CHARACTER vector of length 2") } delete(@namex,@namey) @labels <- keyvalue(@keys,"label*","structure") @addlabels <- keyvalue(@keys,"addlabel*","TF",default:!isnull(@labels)) @show <- keyvalue(@keys,"show","TF",default:T) @xmin <- keyvalue(@keys,"xmin","real vector",default:?)' @xmax <- keyvalue(@keys,"xmax","real vector",default:?)' @ymin <- keyvalue(@keys,"ymin","real vector",default:?)' @ymax <- keyvalue(@keys,"ymax","real vector",default:?)' @hstrips <- keyvalue(@keys,"hstrip*","count",default:0) @vstrips <- keyvalue(@keys,"vstrip*","count",default:0) # check for illegal plot keywords @badkeys <- vector("add","logx","logy", "xtick*","ytick*") @J <- match(@badkeys,@keynames,0,exact:F) @J <- @J[@J != 0] if (!isnull(@J)) { error(paste("Keyword '",@keynames[@J[1]],"' is illegal on $S",sep:""),\ macroname:F) } delete(@badkeys) if (@nrx != @nry) { if (@nrx > 2) { error("nrows(x) > 2 and nrows(x) != nrows(y)") } if (anymissing(@x)) { error("MISSING values in x with nrows(x) != nrows(y)") } } if (!isvector(@x) && !isvector(@y) && @ncx != @ncy) { error("matrices x and y have different numbers of columns") } @ncols <- max(@ncx,@ncy) if (@ncols > 100) { error("number of columns of x or y > 100") } if (isscalar(@xmin)){ @xmin <- rep(@xmin,@ncx)' } elseif (length(@xmin) != @ncx) { error("length(xmin) != ncols(x)") } if (isscalar(@xmax)){ @xmax <- rep(@xmax,@ncx)' } elseif (length(@xmax) != @ncx) { error("length(xmax) != ncols(x)") } if (isscalar(@ymin)){ @ymin <- rep(@ymin,@ncy)' } elseif (length(@ymin) != @ncy) { error("length(ymin) != ncols(y)") } if (isscalar(@ymax)){ @ymax <- rep(@ymax,@ncy)' } elseif (length(@ymax) != @ncy) { error("length(ymax) != ncols(y)") } if (@addlabels && !@show) { print("WARNING: 'addlabels:T' ignored with 'show:F'",macroname:T) @addlabels <- F } if (!isnull(@labels)) { if (!@addlabels || !@show) { print("WARNING: 'labels' ignored with 'addlabels:F' or 'show:F'",\ macroname:T) @labsx <- @labsy <- NULL } else { if (ncomps(@labels) != 2) { error("value for 'labels' not structure of length 2") } @labsx <- argvalue(@labels[1],"component 1 of 'labels'","char vec") @labsy <- argvalue(@labels[2],"component 2 of 'labels'","char vec") if (isscalar(@labsx)) { @labsx <- getlabels(vector(run(@ncx),labels:@labsx)) } elseif (length(@labsx) != @ncx) { error("number of x-labels != ncols(x)") } if (isscalar(@labsy)) { @labsy <- getlabels(vector(run(@ncy),labels:@labsy)) } elseif (length(@labsy) != @ncy) { error("number of y-labels != ncols(y)") } } } elseif(@addlabels) { @labsx <- getlabels(@x, 2, silent:T) if (isnull(@labsx)) { @labsx <- if (@ncols > 1 || @nry == @nrx) { getlabels(vector(run(@ncx),labels:"X")) } else { "index" } } @labsy <- getlabels(@y, 2,silent:T) if (isnull(@labsy)) { @labsy <- getlabels(vector(run(@ncy),labels:"Y")) } } delete(@labels) @symbols <- keyvalue(@keys,"symbol*","vector") if(!ischar(@symbols) && !isreal(@symbols) && !isnull(@symbols)){ error("value for 'symbols' must be CHARACTER or integer") } if (isreal(@symbols)){ if(min(@symbols) < 0 || max(@symbols) > 999 ||\ sum(@symbols != floor(@symbols)) != 0){ error("REAL value for 'symbols' must be integers >= 0 and < 1000") } } delete(@symbols) # symbols will be passed to panelplot through @keys if (@hstrips == 0 || @vstrips == 0) { if (@hstrips > 0) { @vstrips <- ceiling(@ncols/@hstrips) } elseif (@vstrips > 0) { @hstrips <- ceiling(@ncols/@vstrips) } else { @hstrips <- ceiling((-1 + sqrt(1+8*ceiling(@ncols/2)))/2) @vstrips <- ceiling(sqrt(@ncols)) } } elseif (@hstrips * @vstrips < @ncols) { error("hstrips*vstrips too small (< ",@ncols,")",sep:"") } # may be overridden by graphics keywords @title <- paste("Panel plot of",@names[2],"vs",@names[1]) @xlabs <- @names[1] @ylabs <- @names[2] delete(@names) # keys to exclude @exclkeys <- vector("notakey","dumb","file","epsf","ps", "wind*","label*") @J <- unique(match(@exclkeys,@keynames,0,exact:F)) @J <- @J[@J != 0] if (isnull(@J)){ # no excluded keys @keys1 <- @keys } else { @keys1 <- @keys[-@J] # remove them if (isnull(@keys1)) { # all keywords excluded @keys1 <- structure(notakey:NULL) } elseif (!isstruc(@keys1)){ # all but 1 keyword excluded @keys1 <- structure(@keys1,compnames:compnames(@keys)[-@J]) } } delete(@J,@exclkeys) @keys1 <- strconcat(pos:NULL,add:NULL,hstrips:@hstrips,vstrips:@vstrips,\ show:F, keep:T,@keys1,title:@title,xlab:@xlabs,ylab:@ylabs) delete(@xlabs,@ylabs,@title) if (!ismacro(panelplot)){ getmacros(panelplot, quiet:T,printname:F) if (!ismacro(panelplot)){ error("macro panelplot not available") } } @k <- @kx <- @ky <- 1 @incx <- 1*(@ncx > 1) @incy <- 1*(@ncy > 1) @found <- F for(@i,1,@hstrips){ for(@j,1,@vstrips){ @x1 <- @x[,@kx] @y1 <- @y[,@ky] if (sum(!ismissing(@x1) && !ismissing(@y1)) != 0){ @keys1[1] <- vector(@i,@j) # pos; @keys1[2] <- @k > 1 # add panelplot(@x1,@y1,keys:@keys1) @found <- T } if (@k == @ncols){ break 2 # done plotting } @k <-+ 1 @kx <-+ @incx @ky <-+ @incy } # for(@j,1,@vstrips) } # for(@i,1,@hstrips) delete(@x, @y, @x1, @y1) # now display plot if (!@found) { print("WARNING: no non-MISSING data to plot",macroname:T) }elseif (@show){ # display plot @exclkeys <- vector("notakey","symbol*","add",\ "lines","linetype","thickness", "impulse",\ "just*","xmin","ymin","xmax","ymax","label*",\ "xaxis", "yaxis","x","y") # keys to exclude from showkey() @J <- unique(match(@exclkeys,@keynames,0,exact:F)) @J <- @J[@J != 0] if (!isnull(@J)) { @keys <- strconcat(@keys[-@J],@keynames[-@J]) } if (isnull(@keys)){ showplot() } else { showplot(keys:@keys) } } delete(@keynames) if (delete(@addlabels,return:T) &&\ delete(@found,return:T) && delete(@show,return:T)) { @k <- @kx <- @ky <- 1 for(@i,1,@hstrips) { for(@j,1,@vstrips) { @stuff <- Mouse(cancelok:T,strings:paste(@labsy[@ky],"vs",\ @labsx[@kx]), just:"l") if (isnull(@stuff)) { break 2 # cancelled } addstrings(key:@stuff) if (@k == @ncols) { break 2 } @k <-+ 1 @kx <-+ @incx @ky <-+ @incy } } delete(@stuff, @labsx,@labsy) } delete(@i,@j,@k,@kx,@ky,@incx,@ncols,@ncx,@ncy) delete(@hstrips,@vstrips) %plotpanes% plotmatrix MACRO dollars ) Macro to draw a scatter plot matrix of data in a data matrix x, that ) is plots are drawn of column j vs column i of x in a rectanglular ) array of small graphs ) With two REAL arguments x and y plots are drawn of every column of y vs ) every column of x ) ) Usage: ) plotmatrix(x [, symbols:syms] [,upper:T or lower:T] \ ) [,nolabels:T or labels:labsx] [,name:namex]\ ) [,gridlines:F] [,other graphics keyword phrases]) ) x REAL matrix. Every column of x is plotted against ) every other column, omitting any column that is all ) MISSING ) labsx CHARACTER scalar or a vector with length(labsx) == ) ncols(x) (default is "X") ) namex CHARACTER scalar (default is quoted arg 1) ) upper:T only an upper triangle of plots is drawn ) lower:T only an lower triangle of plots is drawn ) or ) plotmatrix(x, y, [, symbols:syms] \ ) [,labels:structure(labsx,labsy)] [,names:vector(namex,namey)]\ ) [,other graphics keyword phrases]) ) x, y REAL matrices with the same number of rows. Every column ) of y is plotted against every column of x, omitting any ) column that is all MISSING ) labsx, labsy CHARACTER scalars or vectors with length(labsx) = ) ncols(x), length(labsy) = ncols(y) ) namex, namey CHARACTER scalars (defaults are quoted args 1 and 2) ) ) syms CHARACTER vector or integer vector with 0 <= syms[i] <= ) 999 which specifies plotting symbols. The default is ) "\7", a dot. Small CHARACTER symbols (ascii codes ) 9 - 24 ("\11" - "\30") are recommended ) ) labsx and labsy provide variable names (default "X" and "Y"). A ) scalar label is expanded by appending "1", "2", .... ) ) namex and namey are used in constructing the default title and axis ) labels. ) ) Addional keyword phrases that may be arguments ) bottomup:T variable numbers increase up the y axis ) vstrips:v integer v >= ncols(x), number of vertical strips ) hstrips:h integer h >= ncols(x) or >= ncols(y), number of ) horizontal strips ) gridlines:F no lines separating panes are drawn ) ) Legal graphics keywords ) window, show, title, xlab, ylab, xaxis, yaxis, lines, linetype, ) impulses, xmin, xmax, ymin, ymax, and keywords having to do with ) files ) Illegal graphics keywords ) add, logx, logy and any keywords having to do with tick marks. ) ) NOTE: ) The values for xmin, xmax, ymin and ymax should either be scalars ) to be used in all graphs, or vectors with lengths matching ncols(x) ) or ncols(y). As usual, a MISSING value means it should be ) computed from the data )) )) Each column of x (and y) is rescaled to )) scaledValue = (value - midrange)/(1.05*range) )) and plotted at position (column number - 1) + value. )) Written by C. Bingham (kb@stat.umn.edu) )) 000818 uses panelplot )) 010425 fixed upper:T and lower:T bug #$S(x [, symbols:syms] [,upper:T or lower:T or bottomup:T]\ # [,labels:labs or nolabs:T] [,diaglabs:F] [,name:xname]\ # [other graphics keywords]) #$S(x, y [, symbols:syms] [,labels:structure(Labsx,Labsy) or nolabs:T] \ # [, bottomup:T] [,name:vector(namex,namey)] [other graphics keywords]) if ($v > 2 || $v == 0) { error("usage: $S(x [,symbols:syms], ...) or $S(x,y [,symbols:syms' ...") } @twoarg <- $v == 2 @x <- argvalue($1,"$1","real matrix") @ncx <- ncols(@x) @keys <- if ($k > 0) { structure($K,notakey:NULL,silent:T) } else { structure(notakey:NULL) } @upper <- keyvalue(@keys,"upper","TF",default:F) @lower <- keyvalue(@keys,"lower","TF",default:F) @bottomup <- keyvalue(@keys,"bottomup","TF",default:F) @nolabels <- keyvalue(@keys,"nolab*", "TF",default:F) @diaglabs <- keyvalue(@keys,"diaglab*", "TF",\ default:!(@twoarg || @upper || @lower)) @labels <- keyvalue(@keys, "label*") if (!isnull(@labels)){ if (isstruc(@labels)){ if (ncomps(@labels) != $v){ error("ncomps(labels) != $v)") } } elseif (@twoarg) { error("'labels' not structure on $S(x ...)", macroname:F) } elseif (!isvector(@labels, char:T)) { error("'labels' not structure or CHARACTER vector on $S(x ...)",\ macroname:F) } if (@nolabels) { print("WARNING: labels ignored with 'nolabels:T'",macroname:T) @labels <- NULL } } if (@twoarg) { @y <- argvalue($02,"$2","real matrix") @ncy <- ncols(@y) if (@upper || @lower || @diaglabs) { error("upper:T, lower:T and diaglabs:T cannot be used with $S(x,y...)",\ macroname:F) } if (!isnull(@labels)) { @labsx <- argvalue(@labels[1],"column labels for x","character vector") @labsy <- argvalue(@labels[2],"column labels for y","character vector") } else { @labsx <- @labsy <- NULL } @names <- keyvalue(@keys,"name*","character vector",\ default:vector("$1","$2")) if (length(@names) != 2) { error("value _for_ 'names' not vector(name_for_x,name_for_y)") } @namex <- @names[1] @namey <- @names[2] delete(@names) } else { @labsy <- @labsx <- @labels @namey <- @namex <- keyvalue(@keys,"name*","string",default:"$1") if (@ncx < 2){ error("x must have at least two columns in $S(x,...)",macroname:F) } if(@upper && @lower){ error("You can't use both 'upper:T' and 'lower:T'") } if ((@upper || @lower) && @diaglabs) { print("WARNING: diaglabs:T ignored with upper:T or lower:T",\ macroname:T) @diaglabs <- F } @ncy <- @ncx } delete(@labels) @symbols <- keyvalue(@keys,"symbols*","vector",default:"\7") if (isreal(@symbols)){ @symbols <- argvalue(@symbols,"REAL value for 'symbols'",\ "positive integer vector") if (max(@symbols) > 999) { error("max(symbols) > 999") } } elseif (!ischar(@symbols)) { error("value for 'symbols' not CHARACTER or integer vector") } delete(@symbols) if (sum(vector(!ismissing(@x))) == 0) { error("all elements of x are MISSING in $S(x [,y] ... ") } if (alltrue(@twoarg, sum(vector(!ismissing(@y))) == 0)) { error("all elements of y are MISSING in $S(x,y ... ") } @show <- keyvalue(@keys,"show","TF",default:T) @xmin <- keyvalue(@keys,"xmin","real vector",default:?)' @xmax <- keyvalue(@keys,"xmax","real vector",default:?)' @ymin <- keyvalue(@keys,"ymin","real vector") @ymax <- keyvalue(@keys,"ymax","real vector") if (@twoarg && (!isnull(@ymin) || !isnull(@ymax))) { print("WARNING: 'ymin' and 'ymax' ignored on $S(x ...)", macroname:F) } if (isscalar(@xmin)){ @xmin <- rep(@xmin,@ncx)' } elseif (length(@xmin) != @ncx) { error("length(xmin) != ncols(x)") } if (isscalar(@xmax)){ @xmax <- rep(@xmax,@ncx)' } elseif (length(@xmax) != @ncx) { error("length(xmax) != ncols(x)") } if (@twoarg) { if (isnull(@ymin)) { @ymin <- ? } if (isscalar(@ymin)){ @ymin <- rep(@ymin,@ncy)' } elseif (length(@ymin) != @ncy) { error("length(ymin) != ncols(y)") } if (isnull(@ymax)) { @ymax <- ? } if (isscalar(@ymax)){ @ymax <- rep(@ymax,@ncy)' } elseif (length(@ymax) != @ncy) { error("length(ymax) != ncols(y)") } } else { @ymin <- @xmin @ymax <- @xmax } @hstrips <- keyvalue(@keys,"hstrip*","count",default:0) @vstrips <- keyvalue(@keys,"vstrip*","count",default:0) # check for illegal plot keywords @badkeys <- vector("add","logx","logy","xtick*","ytick*") @keynames <- compnames(@keys) @J <- match(@badkeys,@keynames,0,exact:F) @J <- @J[@J != 0] if (!isnull(@J)) { error(paste("Keyword '",@keynames[@J[1]],"' is illegal on $S",sep:""),\ macroname:F) } delete(@J,@badkeys) if (!@nolabels){ # set up and check variable labels if (isnull(@labsx)){ @labsx <- getlabels(@x,2,silent:T) if (isnull(@labsx)) { @labsx <- "X" } } if (isscalar(@labsx)) { @labsx <- getlabels(vector(rep(0,@ncx),labels:@labsx)) } elseif (length(@labsx) != @ncx){ error("number of labels doesn't match number of columns of $1") } if (@twoarg) { if (isnull(@labsy)){ @labsy <- getlabels(@y,2,silent:T) if (isnull(@labsy)) { @labsy <- "Y" } } if (isscalar(@labsy)) { @labsy <- getlabels(vector(rep(0,@ncy),labels:@labsy)) } elseif (length(@labsy) != @ncy){ error("number of labels doesn't match number of columns of $2") } } else { @labsy <- @labsx } } # Note @title, @xlab, @ylab may be overridden by keywords @title <- if (@twoarg) { paste("Matrix plot of",@namey,"vs",@namex) } else { paste("Matrix plot of",@namex) } @xlab <- @namex @ylab <- @namey @ystrips <- if(@upper || @lower){@ncy-1}else{@ncy} # number of strips for y @xstrips <- if (@twoarg) { # number of strips for x @ncx } else { @ystrips } if (@hstrips > 0) { if (@hstrips < @ystrips) { error(paste("value for 'hstrips' too small ( < ",@ystrips,")",sep:"")) } } else { @hstrips <- @ystrips } if (@vstrips > 0) { if (@vstrips < @xstrips) { error(paste("value for 'vstrips' too small ( < ",@xstrips,")",sep:"")) } } else { @vstrips <- @xstrips } # calculate number of plots @nplots <- if (@twoarg) { @ncx*@ncy } elseif (@upper || @lower) { @ncx*(@ncx-1)/2 } else { @ncx*(@ncx-1) } @ilast <- if (@upper || @lower) { @ncx - 1 } else { @ncy } @exclkeys <- vector("notakey","dumb","file","epsf","ps","wind*","label*",\ "add","xmin","xmax","ymin","ymax") @J <- unique(match(@exclkeys,@keynames,0,exact:F)) @J <- @J[@J != 0] if (isnull(@J)){ # no excluded keys @keys1 <- @keys } else { @keys1 <- @keys[-@J] # remove them @keys1 <- if (isnull(@keys1)) { structure(notakey:NULL) } else { strconcat(@keys1,compnames:compnames(@keys)[-@J]) } } delete(@J,@exclkeys) # 1st 6 components NULL since they will be substituted for in loop @keys1 <- strconcat(pos:NULL,add:NULL,xmin:NULL,xmax:NULL,ymin:NULL,ymax:NULL,\ hstrips:@hstrips,vstrips:@vstrips,show:F,keep:T,@keys1,\ title:@title,xlab:@xlab,ylab:@ylab) if (!ismacro(panelplot)){ getmacros(panelplot, quiet:T,printname:F) if (!ismacro(panelplot)){ error("macro panelplot not available") } } # with $v == 1 and upper:T or lower:T, # for(i,1,nx-1) {for(j,i+1,nx){}} (traversing lower triangle) # with $v == 1 and neither upper:T nor lower:T # for(i,1,nx) {for(j,1,nx){}} # with $v == 2 # for(i,1,ny) {for(j,1,nx){}} @k <- 0 # count of plots made @found <- F for(@i,1,@ilast){ # loop over horizontal strips @jfirst <- if (@upper || @lower) { @i+1 } else { 1 } for(@j,@jfirst,@ncx){ # loop over vertical strips if (!@twoarg && @i == @j) { next # skip diagonal } @k <-+ 1 # @i1 & @j1 are variables to plot on y and x axes # @i2 & @j2 are strip numbers in vertical and horizontal directions if (@upper && @bottomup || @lower && !@bottomup) { @i1 <- @j @i2 <- @j - 1 @j2 <- @j1 <- @i } elseif (@lower || @upper) { @i1 <- @i2 <- @i @j1 <- @j @j2 <- @j - 1 } else { @i1 <- @i2 <- @i @j1 <- @j2 <- @j } @x1 <- @x[,@j1] @y1 <- if (@twoarg) { @y[,@i1] } else { @x[,@i1] } if (sum(!ismissing(@x1) && !ismissing(@y1)) != 0){ @keys1[1] <- vector(@i2,@j2) # pos; @keys1[2] <- @k > 1 # add @keys1[3] <- @xmin[@j1] # xmin @keys1[4] <- @xmax[@j1] # xmax @keys1[5] <- @ymin[@i1] # ymin @keys1[6] <- @ymax[@i1] # ymax panelplot(@x1,@y1,keys:@keys1) @found <- T } } # for(@j,@jfirst,@ncx) } # for(@i,1,@ilast) # now display plot if (!@found) { print("WARNING: no non-MISSING data to plot",macroname:T) }else { # time to add labels if (!@nolabels){ #label diagonal boxes or margins @x1 <- run(@xstrips) - .5 @y1 <- run(@ystrips) - .5 if (!@bottomup) { @y1 <- reverse(@y1) + @hstrips - @ystrips } if (@diaglabs){ # diagonal will be labelled stringplot(@x1,@y1,string:@labsx,justify:"c",show:F,add:T) } else { if (@lower && @bottomup || @upper && !@bottomup){ @labsx <- @labsx[-1] @labsy <- @labsy[-@ncx] }elseif(@upper || @lower){ @labsx <- @labsx[-@ncx] @labsy <- @labsy[-1] } # label horizontal margin stringplot(@x1,rep(-.02*@hstrips, @xstrips),string:@labsx,\ justify:"c",show:F,add:T) # label vertical margin addstrings(rep(-.01*@vstrips,@ystrips),@y1,string:@labsy,\ justify:"r",show:F,add:T) } delete(@x1,@y1) } if (@show){ # display plot @exclkeys <- vector("symbol*","add",\ "lines","linetype","thickness", "impulse",\ "just*","xmin","ymin","xmax","ymax","label*",\ "xaxis", "yaxis","x","y") # keys to exclude from showkey() @J <- unique(match(@exclkeys,@keynames,0,exact:F)) @J <- @J[@J != 0] if (!isnull(@J)){ @keys <- strconcat(@keys[-@J],compnames:@keynames[-@J]) } if (isnull(@keys)){ showplot() } else { showplot(keys:@keys) } } } delete(@labsx,@labsy,@diaglabs) # all done with labels delete(@upper,@lower,@bottomup,@hstrips,@vstrips) delete(@i,@j,@k,@i1,@j1,@i2,@j2,@jfirst,@ilast,@nplots,@title) delete(@xlab,@ncx,@xstrips,@ylab,@ncy,@ystrips,@x) if (delete(@twoarg,return:T)) { delete(@y) } %plotmatrix% panelplot MACRO dollars ) Basic macro to fill one slot in an array of small graphs ) ) Usage: ) panelplot(x,y, pos:k or pos:vector(r,c), hstrips:h, vstrips:v [,add:T],\ ) [nolabels:T or labels:vector(labx,laby)] [,gridlines:F] \ ) [,graphics keyword phrases]) ) x, y REAL vectors. If nrows(x) <= 2, it is "expanded" to an ) equally spaced vector like the first argument to plot(); ) otherwise, nrows(x) = nrows(y) is required ) h, v integers > 0, the numbers of horizontal and vertical strips. ) pos:k 1 <= k <= h*v, integer specifies the plot will be in panel ) k, counting across rows, starting at the left end of the top ) horizontal strip. ) pos:vector(r,c), 1 <= r <= h, 1 <= c <= v integers, specifies the ) plot will be at intersection of horizontal strip r and ) vertical strip c. ) labx, laby CHARACTER scalars, you interactively position the label ) paste(laby,"vs", labx); defaults are args 2 and 1 ) gridlines:F don't draw lines between planes; the default = T unless ) add:T is an argument, when the default is F ) ) nolabels:T no labels wanted; incompatible with use of 'labels' ) ) Legal graphics keywords ) window, show, title, xlab, ylab, xmin, xmax, ymin, ymax, xaxis, ) yaxis, lines, linetype, impulses and keywords having to do with files ) Illegal graphics keywords ) add, logx, logy and any keywords having to do with tick marks. ) Written by C. Bingham (kb@stat.umn.edu) ) Version of 040112 )) 040112 gridlines:F suppresses lines delimiting panes )) Bug fix MISSING values no longer squeezed out with lines:T #$S(x, y, pos:k or pos:vector(i,j), hstrips:h,vstrips:v,\ # [,label:structure(labx,laby)] [,graphics keywords]) @x <- argvalue($1,"$1","real vector") @y <- argvalue($2,"$2","real vector") @nry <- nrows(@y) @nrx <- nrows(@x) if (@nrx != @nry){ if(@nrx > 2){ error("nrows(x) > 2 and nrows(x) != nrows(y)") } @inc <- if(@nrx == 2){ @x[2] } else { 1 } @x <- @x[1] + delete(@inc,return:T)*run(0,@nry-1) } delete(@nrx) if ($k != 0) { @keys <- structure($K,notakey:NULL,silent:T) } else { @keys <- structure(notakey:NULL) } @key <- keyvalue(@keys,"key*","structure") if (!isnull(@key)){ if ($k > 1) { @keynames <- compnames(@keys) @j <- match("key*",@keynames,0,exact:F) error(paste("you can't use any other keywords with '",\ @keynames[@j],"'",sep:"")) } @keys <- @key } delete(@key) @add <- keyvalue(@keys,"add","TF",default:F) @show <- keyvalue(@keys,"show","TF",default:T) @labels <- keyvalue(@keys,"label*","character vector") @nolabels <- keyvalue(@keys,"nolab*","TF",default:isnull(@labels)) @gridlines <- keyvalue(@keys,"grid*","TF",default:!@add) @symbols <- keyvalue(@keys,"symbol*","vector") @hstrips <- keyvalue(@keys,"hstrip*","positive count") @vstrips <- keyvalue(@keys,"vstrip*","positive count") if (isnull(@hstrips) || isnull(@vstrips)){ error("'hstrips:h, vstrips:v' is required") } @npanels <- @hstrips * @vstrips @pos <- keyvalue(@keys,"pos*","positive integer vector",default:1) if (isscalar(@pos)){ if (@pos > @npanels){ error("'pos:k' with k > h*v'") } @pos <- vector((@pos-1) %% @vstrips,floor((@pos-1)/@vstrips)) + 1 }elseif(length(@pos) > 2){ error("value for 'pos' must be a scalar or a vector of length 2") }else{ if (@pos[1] > @hstrips || @pos[2] > @vstrips){ error("pos:vector(r,c) with r > h and/or c > v") } @pos <- reverse(@pos) } @pos[2] <- @hstrips + 1 - @pos[2] @lines <- keyvalue(@keys, "lines","TF",default:F) @linetype <- -abs(keyvalue(@keys,"linetype","integer scalar",default:-1)) @impulse <- keyvalue(@keys,"impulse*","TF",default:F) @xaxis <- keyvalue(@keys,"xaxis","TF",default:T) @yaxis <- keyvalue(@keys,"yaxis","TF",default:T) @xmin <- keyvalue(@keys,"xmin","real scalar",default:?) @xmax <- keyvalue(@keys,"xmax","real scalar",default:?) @ymin <- keyvalue(@keys,"ymin","real scalar",default:?) @ymax <- keyvalue(@keys,"ymax","real scalar",default:?) if (alltrue(!ismissing(@xmin),!ismissing(@xmax),@xmin >= @xmax)){ @xmin <- @xmax <- ? } if (alltrue(!ismissing(@ymin),!ismissing(@ymax),@ymin >= @ymax)){ @ymin <- @ymax <- ? } @badkeys <- vector("logx","logy", "xtick*","ytick*") @keynames <- compnames(@keys) @J <- unique(match(@badkeys, @keynames, 0, exact:F)) @J <- @J[@J != 0] if (!isnull(@J)) { error(paste("Keyword '",@keynames[@J[1]],"' is illegal on $S",sep:""),\ macroname:F) } delete(@J,@badkeys) if (isnull(@labels) && !@nolabels && @show) { @labels <- vector("$1","$2") } if (!@nolabels) { if (length(@labels) != 2) { error("value for 'labels' not vector of length 2") } elseif (!@show) { print("WARNING: labels ignored with 'show:F'",macroname:T) @nolabels <- T } elseif (sum(@labels == "") == 2) { @nolabels <- T } else { @labsx <- @labels[1] @labsy <- @labels[2] } } delete(@labels) if (!isnull(@symbols)){ if(!ischar(@symbols) && !isreal(@symbols)){ error("value for 'symbols' must be CHARACTER or integer") } } else { @symbols <- if (@lines || @impulse){ "" } else { "\7" # dot } } if (isreal(@symbols)){ if(min(@symbols) < 0 || max(@symbols) > 999 ||\ sum(@symbols != floor(@symbols)) != 0){ error("REAL value for 'symbols' must be integers >= 0 and < 1000") } } @J <- !ismissing(@x) && !ismissing(@y) @nvalues <- sum(@J) if (@nvalues == 0) { if (!keyvalue(@keys,"silent","TF",default:F)){ print("WARNING: no non-MISSING data to plot", macroname:T) } } elseif (@nvalues < @nry) { @x1 <- @x[@J] @y1 <- @y[@J] } else { rename(@x,@x1) rename(@y,@y1) } if (@nvalues > 0) { if (ismissing(@xmin)){ @xmin <- min(@x1) } if (ismissing(@xmax)){ @xmax <- max(@x1) } if (ismissing(@ymin)){ @ymin <- min(@y1) } if (ismissing(@ymax)){ @ymax <- max(@y1) } @xmid <- (@xmin + @xmax)/2 @xscale <- 1.05*(@xmax - @xmin) @ymid <- (@ymin + @ymax)/2 @yscale <- 1.05*(@ymax - @ymin) # scale x and y between -.5 and .5 @x1 <- (@x1 - @xmid)/@xscale @y1 <- (@y1 - @ymid)/@yscale if (@impulse || @xaxis){ @yzero <- if (-@ymid <= -@yscale/2){ -1 } elseif (-@ymid >= @yscale/2) { 1 } else { -@ymid/@yscale } } if (@yaxis) { @xzero <- if (-@xmid <= -@xscale/2){ -1 } elseif (-@xmid >= @xscale/2) { 1 } else { -@xmid/@xscale } } } delete(@xmin,@xmax,@ymin,@ymax) if (!delete(@add,return:T)){ # create gridlines if (@vstrips > 1 && @gridlines){ @xticks <- run(@vstrips-1) @xticklen <- 3 @xticklabs <- rep("",@vstrips-1) }else{ @xticks <- @xticklen <- 0 @xticklabs <- "" } if (@hstrips > 1 && @gridlines){ @yticks <- run(@hstrips-1) @yticklen <- 3 @yticklabs <- rep("",@hstrips-1) }else{ @yticks <- @yticklen <- 0 @yticklabs <- "" } # This draws only grid lines and frame plot(-1, -1,xaxis:F,yaxis:F,\ xmin:.019*@vstrips,xmax:.981*@vstrips,\ ymin:.019*@hstrips,ymax:.981*@hstrips,\ xticks:@xticks,yticks:@yticks,xticklen:@xticklen,yticklen:@yticklen,\ xticklab:@xticklabs,yticklab:@yticklabs,show:F,add:F) delete(@xticks,@yticks,@xticklen,@yticklen,@xticklabs,@yticklabs) } delete(@hstrips,@vstrips,@gridlines) if (@nvalues > 0) { @xoffset <- @pos[1] - .5 @xlower <- @xoffset - .5 @xupper <- @xoffset + .5 @yoffset <- @pos[2] - .5 @ylower <- @yoffset - .5 @yupper <- @yoffset + .5 @x1 <-+ @xoffset @y1 <-+ @yoffset if (@impulse || @xaxis){ @J1 <- @y1 >= @yupper @J2 <- @y1 <= @ylower @yzero <- if (@yzero == 1){ @yupper } elseif (@yzero == -1) { @ylower } else { @yoffset + @yzero } if (@impulse) { @x2 <- vector(hconcat(@x1,@x1,rep(?, @nry))') @y2 <- @y1 @y2[@y1 > @yupper] <- @yupper @y2[@y1 < @ylower] <- @ylower @y2 <- vector(hconcat(@y2,rep(@yzero,@nry),rep(?,@nry))') lineplot(delete(@x2,return:T),delete(@y2,return:T), add:T, show:F) } if (alltrue(@xaxis,\ @yzero < @yupper && @yzero > @ylower)){ # draw xaxis lineplot(vector(@xlower,@xupper),rep(@yzero,2),linetype:7,\ add:T,show:F) } delete(@yzero) } # if (@impulse || @xaxis) if (alltrue(@yaxis,abs(@xzero) != 1)) { # draw yaxis @xzero <-+ @xoffset lineplot(rep(@xzero,2),vector(@ylower,@yupper),linetype:7,\ add:T,show:F) delete(@xzero) } @J1 <- @x1 > @xupper || @x1 < @xlower || @y1 > @yupper || @y1 < @ylower @x1[@J1] <- ? @y1[@J1] <- ? delete(@xoffset,@yoffset,@xlower,@xupper,@ylower,@yupper,@J1) @keys <- strconcat(symbols:@symbols,add:T,lines:@lines,impulses:F,silent:T,\ @keys) # remove unwanted keywords @exclkeys <- vector("xmin","xmax","ymin","ymax") if (!keyvalue(@keys,"show","TF",default:T) &&\ !isnull(keyvalue(@keys,"wind*","count"))){ @exclkeys <- vector(@exclkeys,"wind*") } @J1 <- match(@exclkeys, compnames(@keys),0,exact:F) @J1 <- @J1[@J1 != 0] if (!isnull(@J1)){ @keys <- @keys[-@J1] } delete(@J1,@exclkeys) if (@nvalues < @nry) { @x[@J] <- delete(@x1,return:T) @y[@J] <- delete(@y1,return:T) } else { rename(@x1,@x) rename(@y1,@y) } plot(@x,@y,keys:@keys) } delete(@keys,@keynames,@x,@y) if (!delete(@nolabels,return:T)){ @labels <- if (@labsx == "") { @labsy } elseif (@labsy == "") { @labsx } else { paste(@labsy,"vs",@labsx) } @where <- Mouse(cancelok:T,strings:@labels, just:"l") if (!isnull(@where)){ addstrings(key:@where) } delete(@where,@labels,@labsx,@labsy) } %panelplot% panelhist MACRO dollars ) Macro to a histogram in a pane in a panel graph ) ) Usage: ) panelhist(x, panel keywords [,hist keywords] [,graphics keywords]) ) panelhist(x, nbars, panel keywords [,hist keywords]\ ) [,graphics keywords]) ) panelhist(x, vector(anchor,width), panel keywords [,hist keywords]\ ) [,graphics keywords]) ) panelhist(x, edges ,panel keywords [,hist keywords]\ ) [,graphics keywords]) ) x REAL vector of data ) nbars integer > 0 specifying the number of equal width bars ) width, anchor REAL scalars, width > 0, specifying that the edges of ) the bars are of the form anchor + j*width, where j is ) an integer. ) edges REAL vector of distinct values in increasing order ) specifying histogram bar edges (class limits) ) lab CHARACTER scalar to label panel containing histogram ) ) A histogram of x is drawn in the pane specified by panel keyword 'pos' ) When labels:lab is an argument, you can then use the mouse to ) specify a point where the label is drawn. ) ) panel keyword phrases (some required) ) hstrip:h, vstrip:v h > 0, v > 0 integers sets number of rows ) and columns of panes in panel (required) ) pos:k or pos:vector(r,c) integer k > 0, r > 0, c > 0 specifies which ) pane to draw in (default is pos:vector(1,1)) ) label:lab lab CHARACTER scalar to be added interactively ) gridlines:F Suppress lines separating panes; with add:F ) default is F; otherwise default is T ) ) hist keyword phrases (all optional) ) freq:T or relfreq:T Bar heights are frequencies or relative ) frequencies; otherwise the density scale is used ) leftendin:T Value exactly on edge assigned to bar to right ) instead of to the left ) outsideok:T It's not an error if a value is outside all ) bars ) Legal graphics keywords ) window, show, title, xlab, ylab, add, xmax, xmin, ymax, ymin, yaxis, ) With 'add:T', it is assumed you are adding to an existing panel ) graph with the same number of rows and columns. ) ) Illegal graphics keywords ) lines, linetype, impulse, thickness, xaxis, logx, logy and keywords ) having to do with tick marks. ) ) Written by C. Bingham (kb@stat.umn.edu) )) Version of 000828 uses new version of hist )) 040112 aware of new panelplot() keyword phrase 'gridlines:F' #$S(x, edges, pos:k or pos:vector(i,j), hstrips:h,vstrips:v [,gridlines:F]\ # [freq:T or relfreq:T] [,label:labx] [,graphics keywords]) if ($v > 2) { error("usage: $S(x, nbars or edges [,keyword phrases])",macroname:F) } @keys <- if ($k > 0) { structure($K,save:T,silent:T) } else { structure(save:T) } @label <- keyvalue(@keys,"label*","string") @hstrips <- keyvalue(@keys,"hstrip*","positive count") @vstrips <- keyvalue(@keys,"vstrip*","positive count") if (isnull(@hstrips) || isnull(@vstrips)){ error("'hstrips:h, vstrips:v' is required") } @gridlines <- keyvalue(@keys,"grid*","TF") @npanels <- @hstrips * @vstrips @pos <- keyvalue(@keys,"pos*","positive integer vector", default:1) if (isscalar(@pos)){ if (@pos > @npanels){ error("'pos:k' with k > h*v'") } }elseif(length(@pos) > 2){ error("value for 'pos' must be a scalar or a vector of length 2") }else{ if (@pos[1] > @hstrips || @pos[2] > @vstrips){ error("pos:vector(r,c) with r > hstrips and/or c > vstrips") } } delete(@pos,@hstrips,@vstrips,@gridlines) # values passed in @keys # check for illegal plot keywords @badkeys <- vector("logx","logy","line*","xtick*","ytick*",\ "thickness","impulse*","symbol*","xaxis*") @keynames <- compnames(@keys) @J <- match(@badkeys, @keynames, 0, exact:F) @J <- @J[@J != 0] if (!isnull(@J)) { error(paste("Keyword '",@keynames[@J[1]],"' is illegal on $S",sep:""),\ macroname:F) } if (!isnull(@label)){ @J <- match("label*",@keynames,0,exact:F) @keys <- strconcat(@keys[-@J],compnames:@keynames[-@J]) @keynames <- compnames(@keys) if (!keyvalue(@keys,"show","TF",default:T)){ print("WARNING: 'label' ignored with 'show:F'",macroname:T) @label <- NULL } } delete(@J, @badkeys) if (!ismacro(panelplot)){ getmacros(panelplot, quiet:T,printname:F) if (!ismacro(panelplot)){ error("macro panelplot not available") } } @histnames <- vector("freq*","relfreq*","outsideok","leftendin","save") @Jhist <- match(@histnames,@keynames,0,exact:F) @Jhist <- @Jhist[@Jhist > 0] @histkeys <- strconcat(@keys[@Jhist],compnames:@keynames[@Jhist]) @result <- hist($V,keys:@histkeys) @keys <- strconcat(@keys,lines:T) @keys <- @keys[-@Jhist] panelplot(@result$x,@result$y,key:@keys) delete(@keys,@keynames,@histkeys,@Jhist,@result) if (!isnull(@label)){ @where <- Mouse(xyonly:T) if (!isnull(@where)){ addstrings(@where$x,@where$y,@label,just:"l") } delete(@where) } delete(@label) %panelhist% sampcdf MACRO DOLLARS ) Macro to compute and plot the CDF of a sample ) ) Usage: ) sampcdf(x [,quiet:T, keep:T, draw:T] [graphics keywords]) ) ) x REAL vector ) keep:T return computed sample CDF structure(x:xvals,y:cdfvals\ ) [graphics keywords],lines:T) where REAL vectors xvals and ) cdfvals are the coordinates of the "corners" of the ) sample CDF. ) draw:T sample CDF of x is computed and plotted. Default is ) T unless keep:T is an argument when default is F ) quiet:T suppress warning messages ) ) You can also include as arguments any of the standard graphics ) keyword phrases such as xlab:"X variable" or linetype:n. ) ) When there are MISSING values they are removed and a warning message ) printed unless quiet:T is an argument. ) ) With save:T, no plot is made without 'draw:T'. The output is such that ) either lineplot(sampcdf(x)) or GRAPHWINDOWS[I] <- sampcdf(x) will ) draw the sample CDF, although they may have different axis labels or ) title. You can force a plot to be made with 'draw:T'. ) )) 000207 Gary W. Oehlert (gary@stat.umn.edu) )) & Christopher Bingham (kb@umn.edu) )) 000216 With save:T, graphics keywords are part of result )) 000829 Changed 'keep' to 'save' and 'plot' to 'draw' )) 040112 Redid comments in header @x <- argvalue($1,"argument 1","real vector") @keys <- if ($k > 0) { structure($K,notakey:NULL) } else { structure(notakey:NULL) } @save <- keyvalue(@keys,"save","TF",default:F) @draw <- keyvalue(@keys,"draw","TF",default:!@save) @quiet <- keyvalue(@keys,"quiet","TF",default:F) if(anymissing(@x)) { if(sum(!ismissing(@x)) == 0) { error("argument 1 has no non-MISSING values") } if (!@quiet){ print(paste("WARNING:",sum(ismissing(@x)), "MISSING values deleted"),\ macroname:T) } @x <- @x[!ismissing(@x)] } @x <- sort(@x) @n <- nrows(@x) @del <- if (@x[@n] > @x[1]){ (@x[@n] - @x[1])/20 }elseif(@x[1] != 0){ abs(@x[1])/20 }else{1} @x <- vector(@x[1] - @del,rep(@x,rep(2,length(@x))), @x[@n] + @del) @y <- rep(run(0,@n)/@n, rep(2,@n+1)) @value <- structure(x:@x,y:@y) @keynames <- compnames(@keys) @J <- match(vector("save","draw","quiet","notakey"),@keynames,0) @J <- @J[@J != 0] @keys <- if (length(@J) < ncomps(@keys)){ strconcat(@keys[-@J],compnames:@keynames[-@J]) } else { NULL } delete(@J) if(@draw){ lineplot(keys:strconcat(@value,@keys,ymax:1.05,ylab:"Sample CDF",\ xlab:"Data",yaxis:F)) } if (@save){ if (!isnull(@keys)) { @value <- strconcat(@value,@keys) } if (match("lines",@keynames,0) == 0){ @value <- strconcat(@value,lines:T) } } delete(@x,@n,@del,@quiet,@draw,@keys,@keynames) delete(@value, return:delete(@save,return:T)) %sampcdf% hist MACRO DOLLARS ) Macro to draw histogram of data in REAL vector x ) Usage: ) hist(x,nbins [,freq:T or relfreq:T] [,save:T] [,draw:T]) ) nbins integer > 0 ) Uses nbins equal width classes that include all the data; class ) limits are not "neat" ) ) hist(x [,freq:T or relfreq:T] [,save:T] [,draw:T]) ) Like preceding with nbins = floor(log(length(x))/log(2)) + 1 ) ) hist(x,vector(anchor,width) [,freq:T or relfreq:T] [,save:T] [,draw:T]) ) anchor a REAL scalar, width > 0 a scalar ) Uses equal width classes with edges of the form anchor + j*width so ) as to include all the data. ) ) hist(x,edges [,freq:T or relfreq:T] [,outsideok:T] [,save:T] [,draw:T]) ) REAL vector edges, length(edges) > 2, edges[i+1] - edges[i] > 0 ) min(edges) <= min(x), max(edges) >= max(x) without 'outsideok:T' ) ) hist(x [,arg2] keys:structure(keyword phrases)) ) ) With freq:T, the bar heights are frequencies (counts in classes) ) With relfreq:T, bar heights are relative frequencies (frequencies/n) ) Otherwise, the heights of the bars are in the "density" scale so the ) total area is 1 ) ) With outsideok:T, it is not an error for data values to be outside all ) defined bars; only a warning message is printed ) ) With save:T hist returns ) structure(x:xvalues,y:yvalues,lines:T [,graphics keywords]) ) where lineplot(xvalues,yvalues) would draw the histogram, but ) does not draw a histogram unless draw:T is also an argument ) ) With keyword 'keys', there can be no other keywords (except those ) defining components of the structure value of 'keys') ) ) With all usages you can use standard graphics keywords including ) 'title', 'xlab', 'ylab', 'xmin', and 'xmax', and bin() keyword ) 'leftendin' ) These are included in the result with 'save:T' ) )) Version of 000520 added 'relfreq' and 'freq' and allows boundaries )) specified as vector(anchor, width); also check as to whether )) the edges include the data, takes into account 'leftendin' )) new keyword phrase outsideok:T )) Version of 000823 added 'save:T' and 'draw:T'; with save:T returns )) structure )) 031204 Fixed bug when all values are the same # usage: $S(x,vector(anchor, width)[,keywords]), $S(x,nbins[,keywords]) # $S(x,edges [,outsideok:T] [,keywords]), or $S(x[,keywords]) if($v < 1 || $v > 2){ error("usage: $S(x), $S(x,nbins), $S(x,edges) or $S(x,vector(anchor,width)",\ macroname:F) } @x <- argvalue($1, "$1", "real vector") if(anymissing(@x)){ @x <- @x[!ismissing(@x)] if (isnull(@x)){ error("all values of $1 are MISSING") } } if (alltrue(ndims(@x) == 2, !isnull(getlabels(@x,silent:T)))) { @xname <- getlabels(@x,2) if (match("@*",@xname,0,exact:F) != 0){ @xname <- "$1" } } else { @xname <- "$1" } @keys <- if ($k > 0) { structure($K,notakey:NULL,silent:T) } else { structure(notakey:NULL) } @keys1 <- keyvalue(@keys,"key*","structure") if (!isnull(@keys1)){ if ($k > 1) { error("you can't use other keywords with 'keys'") } @keys <- @keys1 } delete(@keys1) @leftin <- keyvalue(@keys,"leftendin","TF",default:F) @freq <- keyvalue(@keys, "freq*", "TF", default:F) @relfreq <- keyvalue(@keys, "relfreq*", "TF", default:F) if (@freq && @relfreq){ error("both 'freq:T' and 'relfreq:T' illegal") } @outsideok <- keyvalue(@keys,"outsideok","TF",default:F) @save <- keyvalue(@keys,"save","TF",default:F) @draw <- keyvalue(@keys,"draw","TF",default:!@save) if (!@save && !@draw) { error("you can't use 'draw:F' with 'save:F'") } @keynames <- compnames(@keys) @exclkeys <- vector("leftendin","freq*","relfreq*","outsideok","draw","save") @Jexcl <- match(@exclkeys,@keynames,0,exact:F) @Jexcl <- @Jexcl[@Jexcl > 0] if (!isnull(@Jexcl)){ @keys <- if (length(@Jexcl) < ncomps(@keys)){ strconcat(@keys[-@Jexcl],compnames:@keynames[-@Jexcl]) } else { structure(notakey:T) } } delete(@Jexcl,@exclkeys,@keynames) @xmin <- min(@x) @xmax <- max(@x) if($v == 2){ @nbins <- argvalue($2, "$2", "real nonmissing") if(!isvector(@nbins)){ error("$2 is not a REAL scalar or vector") } @nbins <- if (isscalar(@nbins)){ @bins <- NULL argvalue(@nbins, "number of bars", "positive integer scalar") }elseif(length(@nbins) > 2){ @bins <- @nbins length(@bins) - 1 }else{ # arg 2 of form vector(anchor, width) @anchor <- @nbins[1] @w <- @nbins[2] if (@w <= 0){ error("bar width <= 0") }else{ if (@xmin == @xmax){ @xmin <-- @w/2 @xmax <-+ @w/2 } @anchor <-- ceiling((@anchor - @xmin)/@w)*@w if (@anchor > @xmin || @anchor == @xmin && !@leftin){ @anchor <-- @w } @bins <- run(@anchor, @xmax, @w) @maxbins <- max(@bins) if (@maxbins < @xmax || @maxbins == @xmax && @leftin){ @bins <- vector(@bins,@maxbins + @w) } delete(@w, @anchor, @maxbins) length(@bins) - 1 } } } else{ @nbins <- floor(log2(length(@x))) + 1 @bins <- NULL } if(isnull(@bins)){ if (@xmin == @xmax){ if (@xmin == 0){ @xmin <- -(@xmax <- .5) }else{ @xmin <-- .1*abs(@xmin) @xmax <-+ .1*abs(@xmax) } } @min <- 1.05*@xmin - .05*@xmax @max <- 1.05*@xmax - .05*@xmin @widths <- (@max - @min)/@nbins @bins <- run(@min,@max+.1*@widths,@widths) delete(@min, @max) } else { @minbins <- min(@bins) @maxbins <- max(@bins) @nleft <- sum(@x < @minbins) @nright <- sum(@x > @maxbins) if (@leftin){ @nright <-+ sum(@x == @maxbins) }else{ @nleft <-+ sum(@x == @minbins) } if (@nleft + @nright > 0){ if (!@outsideok){ error(paste("data min =",@xmin, "or max =",@xmax,\ "outside of bars")) } @msg <- "WARNING:" if (@nleft > 0){ @msg <- paste(@msg,@nleft,"value(s) omitted on left") if (@nright > 0){@msg <- paste(@msg,"and")} } if (@nright > 0){ @msg <- paste(@msg,@nright,"value(s) ommitted on right") } print(delete(@msg,return:T)) } delete(@minbins,@maxbins,@nleft,@nright) } delete(@xmax,@xmin) @widths <- movavg(1,@bins)[-1] if(min(@widths) < 0){ error("bin boundaries are not monotonic") } @n <- length(@x) @denom <- if (@freq || @relfreq){ if (describe(@widths, stddev:T) > 1e-5 * sum(@widths)){ print("WARNING: 'freq:T' or 'relfreq:T' used with unequal class widths",\ macroname:T) } if (@freq){ 1 }else{ @n } }else{ @widths*@n } @warning <- getoptions(warnings:T) setoptions(warnings:F) @hts <- bin(delete(@x, return:T), @bins,\ leftendin:delete(@leftin,return:T))$counts/@denom setoptions(warnings:delete(@warning,return:T)) @xpts <- rep(@bins,rep(3, @nbins+1))[-1] @ypts <- vector(0,hconcat(@hts,@hts,0*@hts)',0) if (delete(@draw,return:T)){ @ylab <- if(@freq) { "Frequency" } elseif(@relfreq) { "Relative frequency" } else { "Density" } @title <- if(@freq) { paste("Frequency histogram of",@xname) } elseif(@relfreq) { paste("Relative frequency histogram of",@xname) } else { paste("Histogram of", @xname, "with total area 1") } lineplot(@xpts,@ypts,\ keys:strconcat(@keys,xlab:@xname,ylab:@ylab,title:@title)) delete(@ylab,@title) } delete(@bins,@nbins,@hts,@widths,@denom,@xname) if (delete(@save,return:T)) { @result <- structure(x:@xpts,y:@ypts,lines:T) if (ncomps(@keys) > 1) { @keynames <- compnames(@keys) @J <- match("notakey",@keynames,0) @keys <- strconcat(@keys[-@J],compnames:@keynames[-@J]) @result <- strconcat(@result,@keys) delete(@J,@keynames) } } else { @result <- NULL } delete(@xpts,@ypts,@keys) delete(@result,return:T) %hist% bargraph MACRO DOLLARS ) usage: ) bargraph(edges,y [,save:T] [,draw:T] [,graphics keyword phrases]) ) bargraph(x, y, widths [,save:T] [,draw:T] ...) ) bargraph(structure(edges,y), widths [,save:T] [,draw:T] ...) ) bargraph(structure(x, y, widths), [,save:T] [,draw:T] ...) ) Draw a bar graph of y ) y REAL vector with no MISSING values specifies ) heights of bars ) ) Two non-keyword arguments: edges and y: bar graph with touching bars ) edges REAL vector with no MISSING values and edges[i+1] > ) edges[] and nrows(edges) = nrows(y) + 1 specifies ) a complete set of bar edges ) or ) vector(first, second), second > first specifies ) equally spaced edges starting at first with width ) second - first; ) or ) REAL scalar first: same as vector(first,first+1) ) ) Three non-keyword arguments x, y, and widths: bar graph with bars ) of specified width, not necessarily touching ) x REAL vector with no MISSING values and with ) nrows(x) = nrows(y) specifying bar centers ) widths REAL scalar or vector the same length as y with ) speciying width of bars centered at x. A scalar ) widths is interpreted as rep(widths,nrows(y)) ) ) Graphics keywords title, xlab, ylab, xmin, xmax, etc. may be used ))000219 stripped $$, use argvalue(), other changes ))000519 argument can be structure(edges,y) ))000829 added keyword phrases draw:T and save:T ))020125 added usage bargraph(x,y,widths) # usage: $S(edges,y), $S(structure(edges,y)), # $S(x,y,widths) or $S(structure(x,y,widths)) if($v > 3){ error("usage: $S(edges,y), $S(structure(edges,y)), $S(x,y,widths) or $S(structure(x,y,widths))",\ macroname:F) } @keys <- if ($k > 0) { structure($K,notakey:NULL,silent:T) } else { structure(notakey:NULL) } @save <- keyvalue(@keys,"save","TF",default:F) @draw <- keyvalue(@keys,"draw","TF",default:!@save) if (!@save && !@draw){ error("you can use 'draw:F' without 'save:T'") } @keynames <- compnames(@keys) @J <- unique(match(vector("draw","save","notakey"),@keynames,0)) @J <- @J[@J != 0] if (!isnull(@J)) { @keys <- if (length(@J) != ncomps(@keys)){ strconcat(@keys[-@J],compnames:@keynames[-@J]) } else { NULL } } delete(@J, @keynames) if ($v == 1){ @arg1 <- argvalue($1,"single non-keyword argument","structure") @nargs <- ncomps(@args) if (@nargs < 2){ error("structure argument must have at least 2 components") } @what <- if (@nargs == 2) { "bar edges" } else { @widths <- argvalue(@arg1[3], "bar widths","real vector nonmissing") "bar centers" } @x <- argvalue(@arg1[1], @what, "real nonmissing") @y <- argvalue(@arg1[2], "bar heights","real nonmissing vector") delete(@arg1) }else{ @nargs <- $v @what <- if (@nargs == 2) { "bar edges" } else { @w <- argvalue($3, "bar widths","positive real vector nonmissing") "bar centers" } @x <- argvalue($1, @what, "real nonmissing") @y <- argvalue($2, "bar heights","real nonmissing vector") } delete(@what) @nx <- nrows(@x) @nvals <- nrows(@y) @nvars <- ncols(@y) if (delete(@nargs,return:T) == 2) { if(@nx == 1){ @x <- @x + run(0, @nvals) }elseif(min(movavg(1,@x)[-1]) <= 0){ error("bar edges not strictly increasing") } elseif (@nx == 2) { @x <- @x[1] + run(0,@nvals)*(@x[2] - @x[1]) } elseif(@nx != @nvals + 1) { error("number of bar edges != length(y) + 1") } @x <- rep(@x,rep(3,length(@x)))[-1] @y <- vector(0,hconcat(@y,@y,0*@y)',0) } else { if(@nx != @nvals) { error("number of bar centers != length(y)") } if (isscalar(@w)) { @w <- rep(@w, @nvals) } elseif (nrows(@w) != @nvals) { error("number of bar widths != length(y)") } @w <-* rep(.5,2)' @x <- vector(hconcat(rep(?,@nvals),@x - @w, @x + @w)')[-1] delete(@w) @y <- vector(vector(0,0,1,1,0) * @y')[-1] } @result <- structure(x:@x,y:@y) if (!isnull(@keys)){ @result <- strconcat(@result,@keys) } if (@draw) { lineplot(keys:strconcat(@result,yaxis:F,title:"Barplot of $2")) } @result <- if (@save) { strconcat(@result, lines:T) } else { NULL } delete(@nx,@nvals,@x,@y,@keys) delete(@result, return:T) %bargraph% ellipse macro DOLLARS ) Macro to compute and optional draw ellipse defined by Q and K ) centered ) Usage: ) ellipse(K, Q [,x0] [,npoints:m] [method:j] [,draw:T] \ ) [,graphics keyword phrases]) ) where ) K > 0 is a scalar ) Q is a 2 by 2 positive definite symmetric matrix, ) x0 is a REAL vector of length 2, default vector(0, 0) ) m specifies the number of points to use, default 200 ) ) The ellipse is defined by ) (x - x0)' %*% solve(Q) %*% (x - x0) = K^2 ) ) With draw:T, lineplot() will be used to draw the ellipes ) Without draw:F, no graphing is done and ellipse() returns ) strconcat(x:xvalues,y:yvalues,lines:T [,graphics keyword phrases] ) ) Three methods are available as selected by method:j (default 3) ) All three compute m+1 unit vectors u(theta) for theta equally spaced ) from 0 to 360 degrees, where ) u(theta) = vector(cos(theta), sin(theta)) ) Method 1 (Pure polar coordinates): ) x = x0 + K * u(theta)/r1(theta), ) r1(theta) = sqrt(u(theta)' %*% solve(Q) %*% u(theta)) ) Method 2 ) x = x0 + K * Q %*% u(theta)/r2(theta), where ) r2(theta) = sqrt(u(theta)' %*% Q %*% u(theta)) ) Method 3 (default) ) x = x0 + K*cholesky(Q)' %*% u(theta) ) Version of 000822 # usage: $S(K, Q, [,x0], [,npoints:m] [graphics keywords] @k <- argvalue($1,"K","positive scalar") @q <- argvalue($2,"Q","square real nonmissing") @x0 <- if($v > 2){ argvalue($3,"x0","nonmissing vector") }else{ rep(0,2) } if (nrows(@q) != 2){ error("Q not 2 by 2 matrix") } if (nrows(@x0) != 2){ error("x0 is not vector with two elements") } if (@q[1,2] != @q[2,1]) { @q12 <- @q[2,1] <- .5*(@q[1,2] + @q[2,1]) if (abs(@q[1,2] - @q[2,1]) > 1e-12*abs(@q12)) { error("Q is not symmetric") } @q[1,2] <- @q[2,1] <- delete(@q12,return:T) } if (@q[1,1] <= 0 || @q[2,2] <= 0 || det(@q) <= 0) { error("Q is not positive definite") } @keys <- if ($k > 0){ strconcat($K,notakey:NULL) } else { structure(notakey:NULL) } @method <- keyvalue(@keys,"method","positive count",default:3) @m <- keyvalue(@keys,"npoint*","positive integer scalar",default:200) @draw <- keyvalue(@keys,"draw","TF",default:F) @angles <- run(@m+1)/@m @x <- hconcat(cos(@angles,cycles:T),sin(@angles,cycles:T)) delete(@angles,@m) if (@method > 3){ error("value for 'method' must be <= 3") } @x <- @k * (if (@method == 1){ sqrt(vector(1/sum(solve(@q) %C% @x * @x'))) * @x } elseif (@method == 2) { sqrt(vector(1/sum(@q %C% @x * @x'))) * @x %*% @q } else { @x %*% cholesky(@q) }) + @x0' delete(@k,@x0,@q) @exclkeys <- if (@draw && !keyvalue(@keys,"show","TF",default:T)){ vector("wind*","screend*","file","epsf","ps") } else { NULL } @exclkeys <- vector("draw","method","npoint*",@exclkeys) @keynames <- compnames(@keys) @J <- unique(match(@exclkeys,@keynames,0,exact:F)) @J <- @J[@J != 0] if (!isnull(@J)){ @keys <- strconcat(@keys[-@J],compnames:@keynames[-@J]) } delete(@J,@exclkeys) if (@draw) { lineplot(@x[,1],@x[,2],key:@keys) @result <- NULL } else { @result <- strconcat(x:@x[,1],y:@x[,2]) @keys <- @keys[-match("notakey",compnames(@keys),0)] if (!isnull(@keys)){ @result <- strconcat(@result, @keys) } } delete(@keys,@keynames,@x) delete(@result,return:T) %ellipse% piechart MACRO DOLLARS ) Macro to draw a pie chart with angles proportional to its first ) argument ) Usage: ) piechart(p [,start:p0] [,labels:labs] [,rlab:r1 [, rval:r2]\ ) [, xwidth:w] [,graphics keyword phrases]) ) where ) p REAL vector with p[i] >= 0 usually with sum(p) = 1 or ) sum(p) = 100 ) p0 positive REAL scalar, default = 0, interpreted as ) a proportion when p0 <= 1 and as a percent p0 > 1, ) which determines the angle (as of a fraction of a ) full cycle) of the first spoke drawn ) labs CHARACTER vector with length(labs) = length(p); the ) default is vector("1","2",...) ) r1, r2 positive scalars, usually < 1 specifying radial ) distances; default for r1 is .9; r2 has no default ) w positive scalar, default 3.2; the graph is drawn ) using graphics keyword phrases xmin:-w/2,xmax:w/2, ) chosen so that the pie is a circle and not an ellipse ) ) Segment[i] of the piechart with angular extent proportional to p is ) labeled with labs[i] at radius r1. ) ) To suppress labels, use labels:"" ) ) When rval:r2 is an argument, segment[i] is also labelled with p[i] at ) radius r2. Default is no labelling by value )) Version 000821 C. Bingham, kb@stat.umn.edu )) 010216 p can be row or column vector; change in default labels # $S(p [,labels:labs, start:p0, rlab:r1, rval:r2, xwidth:w]\ # [,showplot() keywords]) @p <- argvalue($1,"proportions","nonnegative") if (!isvector(@p)){ @p <- @p' if (!isvector(@p)){ error("$1 is not a row or column vector") } } @n <- length(@p) @keys <- structure($K,notakey:T,silent:T) @labs <- keyvalue(@keys,"label*","character vector") if (isnull(@labs)){ @labs <- if (haslabels(@p)){ getlabels(@p,1) } else { paste(run(@n),multiline:T) } } @start <- keyvalue(@keys,"start","real scalar nonmiss",default:0) @rlab <- keyvalue(@keys,"rlab*","positive scalar",default:.9) @rval <- keyvalue(@keys,"rval*","positive scalar") @show <- keyvalue(@keys,"show","TF",default:T) @linetype <- keyvalue(@keys,"linetype","positive count",default:1) @xwidth <- keyvalue(@keys,"xwidth","positive scalar",default:3.2) @xmin <- keyvalue(@keys,"xmin","real scalar",default:-@xwidth/2) @xmax <- keyvalue(@keys,"xmax","real scalar",default:@xwidth/2) @ymin <- keyvalue(@keys,"ymin","real scalar",default:?) @ymax <- keyvalue(@keys,"ymax","real scalar",default:?) @xlab <- keyvalue(@keys,"xlab","string",default:" ") @ylab <- keyvalue(@keys,"ylab","string",default:" ") @title <- keyvalue(@keys,"title","string",default:"Pie chart of $1") if (!@show && !isnull(keyvalue(@keys,"wind*","count"))) { print("WARNING: 'window:n' ignored with 'show:F'") } if (keyvalue(@keys,"add","TF",default:F)){ print("WARNING: 'add:T' ignored by $S") } @showvals <- !isnull(@rval) if (keyvalue(@keys,"xaxis","TF",default:F) || \ keyvalue(@keys,"yaxis","TF",default:F)) { print("WARNING: 'xaxis:T and/or 'yaxis:T' ignored by $S") } @nolabs <- sum(@labs != "") == 0 if (!@nolabs) { if (isscalar(@labs) && @n > 1) { @labs <- getlabels(vector(@p,labels:@labs)) # use labs as root } else { if (length(@labs) != @n){ error("length(labels) != length(data)") } } } @J <- @p != 0 if (sum(@J) == 0) { error("cannot make pie chart of all-zero data") } elseif (sum(@J) != @n) { print("WARNING: zero data values ignored",macroname:T) @n <- sum(@J) @p <- @p[@J] @labs <- @labs[@J] } @p1 <- @p @p <-/ sum(@p) # turn into proportions if (abs(@start) > 1){@start <-/ 100} @angles <- autoreg(1,vector(@start,@p[-@n])) #angles of spokes in cycles @x <- vector(hconcat(rep(0,@n),sin(@angles,cycles:T),rep(?,@n))') @y <- vector(hconcat(rep(0,@n),cos(@angles,cycles:T),rep(?,@n))') lineplot(@x,@y,linetype:delete(@linetype,return:T),show:F) # draw spokes if (!@nolabs || @showvals){ # calculate midlines of sectors @angles <- @angles + .5 * movavg(1,vector(@angles,@angles[1]+1))[-1] if (!@nolabs){ addstrings(@rlab*sin(@angles,cycles:T),@rlab*cos(@angles,cycles:T),\ strings:@labs,show:F) } if (@showvals){ addstrings(@rval*sin(@angles,cycles:T),@rval*cos(@angles,cycles:T),\ strings:paste(@p1,multiline:T,format:".3g"),show:F) } } # now draw circle @angles <- run(0,150)/150 #cycles lineplot(sin(@angles,cycles:T),cos(@angles,cycles:T),thickness:2,\ add:T,show:F,xaxis:F,yaxis:F,xticks:NULL,yticks:NULL,\ xmin:@xmin,xmax:@xmax,ymin:@ymin,ymax:@ymax,\ xlab:@xlab,ylab:@ylab,title:@title) if (@show) { @exclkeys <- vector("linetype","line*","show","xlab","ylab","title",\ "xmin","xmax","ymin","ymax","label*","add") @keynames <- compnames(@keys) @J <- unique(match(@exclkeys,@keynames,0,exact:F)) @J <- @J[@J != 0] if (!isnull(@J)){ @keys <- strconcat(@keys[-@J],@keynames[-@J]) } delete(@keynames) showplot(key:@keys) } delete(@x,@y,@p,@n,@rlab,@rval,@labs,@showvals,@angles,@xwidth,@keys) %piechart% graphicshelp MACRO ) Macro to get help on macros in graphics.mac # usage $S(topic1 [, topic2 ...] [help keywords]) if(!ismacro(_gethelp)){ getmacros(_gethelp,quiet:T,printname:F) } ___HELPFILE_ <- "graphics.mac" ___INDEXTOP_ <- "graph_index" ___MACRO_ <- "$S" _gethelp($0) %graphicshelp% _E_N_D_O_F_M_A_C_R_O_S_ Help file for graphics.mac for MacAnova (C) 2001, 2002, 2003, 2004 by Gary W. Oehlert and Christopher Bingham Updated 050331 CB !!!! Starting marker for message of the day !!!! Ending marker for message of the day ???? Starting marker for list of up to 32 comma/newline separated keys Bar graphs Contour graphs Distribution graphs General Interaction graphs Line graphs Multivariate graphs Panel graphs Shapes ???? Ending marker for keys This file is read by commands help() and usage() and macro graphicshelp. Each topic starts with '====topicName' in column 1, followed by an unlimited number of lines of information. It is helpful, but not required, that topics be in alphabetical order. Topic names should, if possible, be no longer than 12 characters, since otherwise they must be quoted in a help() command. The convention is used that when referring to functions, but not macros, by name, '()' is appended. If the next line after '====topicName' starts with '%%%%', all following lines up to a matching '%%%%' are skipped by help() but are printed by usage(). usage() skips the lines following the second '%%%%'. Each topic name that refers to a function or a pre-defined macro has '()' appended to it. This does not affect output but is intended to useful in semi-automatic generation of the reference manual from the help file. Names of topics that are not to be included in the Reference Manual are followed by '*'. This does not affect help() output. Names of topics whose usages are not to be included in the Reference Manual are followed by '%'. This does not affect help() output. Keys separated by commas can follow the topic name (and trailing '()', '*' or '%') if separated from it by '#'. These should be selected from up to 32 keys listed between lines starting with '????' somewhere before the first help topic. Case is ignored. ====bargraph()#bar graphs %%%% bargraph(edges,y [,save:T] [,draw:T] [,graphics keyword phrases]), REAL vectors edges and y, length(edges) <= 2 or = length(y) + 1 bargraph(vector(firstedge [,secondedge]), y, [,save:T] [,draw:T] ...), firstedge < secondedge REAL scalars, default for secondedge = firstedge + 1 bargraph(x,y,widths [,save:T] [,draw:T] ...), REAL vectors x, y with same length and width a positive vector of same length as x or a positive scalar, interpreted as rep(widths,nrows(x) %%%% @@@@usage#Usage bargraph(edges, y [,graphics keyword phrases]) draws a bar graph with touching bars and bar heights y. Arguments edges and y are REAL vectors with edges[j+1] - edges[j] > 0 and length(edges) = length(y) + 1. Bar j has height y[j] and boundaries edges[j] and edges[j+1]. The graphics keyword may include 'xlab', 'ylab', 'title', keywords having to do with tick marks and so on. bargraph(vector(edge1, edge2), y [,graphics keyword phrases]), where edge1 < edge2 are REAL scalars does the same except the bar edges are edge1, edge1 + width, ...,edge1 + length(y)*width, where width = edge1 - edge1. bargraph(edge1, y [, ...]) is the same a bargraph(vector(edge1,edge1+1), y, ...). bargraph(x, y, w [,...]) draws a bar graph with bars centered at x, with heights y and widths w. x, y and w must be REAL vectors with no MISSING values and nrows(x) = nrows(y), and w vector of the same length or a scalar equivalent to rep(w,nrows(x)). @@@@keep_keyword#Keyword keep bargraph(edges,y, keep:T [,draw:T] [,graphics keyword phrases]) or bargraph(x,y,w, keep:T [,draw:T] [,graphics keyword phrases]) returns structure(x:xvals, y:yvals [,graphics keyword phrases], lines:T) where xvals and yvals are REAL vectors such that lineplot(xvals,yvals) would draw the bars. With draw:T, the graph also is drawn. The structure can be assigned to GRAPHWINDOWS[j] to draw the bar graph in window j or used with panelplot() to draw the bar graph in a panel graph (see topics panelplot() and 'panel_graphs'). @@@@see_also#Cross references See also hist(), lineplot(), 'graph_keys'. @@@@______ ====boxplot5num()#distribution graphs %%%% boxplot5num(x [,names:Names][,excludeM:T] [,keep:T] \ [,graphics keyword phrases]), x a REAL vector or a structure with REAL vector components, Names a CHARACTER scalar or vector %%%% @@@@usage boxplot5num(x), where x is a REAL vector or a structure whose components are REAL vectors, draws a simplified boxplot of a vector or side-by-side simplified boxplots of the components of x. These reflect only the 5 number summary (minimum, lower quartile, median, upper quartile and maximum) and display no information on outliers. The upper and lower quartiles are the medians of the upper and lower halves of the data as computed by describe(). When the sample size is odd, the median is included in both halves unless the value of option 'excludeM' is True. See setoptions() and keyword 'excludeM' below. The plot drawn is based on what is presented in David S. Moore, The Basic Practice of Statistics. To replicate plots in the book, you should set option 'excludeM' to True or use keyword phrase 'excludeM:T' as an argument. See below. boxplot5num(x,names:Names), where Names is a CHARACTER scalar or vector, does the same, except Names is used to label the boxes. If Names is a scalar, say "School ", the plots will be labelled "School 1", "School 2",... . If Names is vector, than x must be a structure with ncomps(x) = length(Names). boxplot5num(x,excludeM:T [,names:Names]), does the same except the quartiles are computed as the medians of the lower and upper halves *excluding* the median. This matches the definition in Moore's book. boxplot5num(x, keep:T [,excludeM:T, names:Names]) does the same, but also returns a vector or structure containing the 5 number summaries (Min, Q1, Median, Q3, Max) for each box plot drawn. You can also use most of the usual graphics keywords such as 'title', 'ylab', 'show', and 'window'. @@@@see_also#Cross references See also boxplot() and vboxplot() which draw more elaborate boxplots. @@@@______ ====colplot()#line graphs,interaction graphs %%%% colplot(x [, graphics keyword phrases]), x a REAL matrix %%%% @@@@usage colplot(x) makes an "interaction" plot of the data in the REAL matrix x. The plotting positions are the row numbers and the values in x. Points within each column are joined by lines. Any keywords useable in chplot may follow x. When option 'dumbplot' has been set False (see options), the plot will be a low resolution plot unless 'dumb:F' is an argument. See topic 'graph_keys', 'graph_border' and 'graph_ticks' for information on other keywords that can be used with colplot(). @@@@example Example: Cmd> colplot(run(20)^(.2*run(5)'),xlab:"X",\ title:"X^.2, X^.4, X^.6, X^.8, X") @@@@______ colplot() is implemented as a pre-defined macro. @@@@see_also#Cross reference See also topic rowplot(). @@@@______ ====contour()#contour graphs %%%% contour(x,y,vals,level [,checkargs] [,keyword phrases]), REAL vectors x, y, REAL scalar level, all with no MISSING, REAL matrix vals, optional LOGICAL scalar checkargs %%%% @@@@usage contour(x,y,vals,level) determines coordinates of a polygonal curve (curve made up of line segments) that approximates a contour of constant height of a surface whose height at (x[i], y[i]) is vals[i,j]. x and y must be REAL vectors of unique non-MISSING values. vals must be a REAL nrows(x) by nrows(y) matrix, which may have MISSING elements. level must be a non-MISSING REAL scalar, preferably between the extreme values in vals. Most commonly, vals[i,j] = F(x[i],y[j]) for some function F(x,y) of two variables. When the surface is not defined or is infinite at (x[i],y[j]), vals[i,j] should be MISSING. contour(x,y,vals,levels,T) does the same, except that the arguments are not checked for correctness. In particular, x and y are assumed to be increasing order, which is not ordinarily required. This usage is designed for use in macro contourplot() which has already checked arguments and reordered x and y before calling contour(). @@@@value_returned The value returned is structure(x:xc, y:yc, level:level). When level is outside the range of vals, xc and yc are both NULL. Otherwise xc and yc are REAL vectors of the same length. The points (xc[k],yc[k]), k = 1,..., nrows(xc), are either intersections of the contour with gridlines, or (MISSING,MISSING). When a contour consists of two or more disjoint curves, they are separated by MISSING in both xc and yc. contour(x,y,vals,level, graphics keyword phrases) does the same except the result is structure(x:xc, y:yc, level:level, graphics keyword phrases) in which all the keyword phrases in the argument are appended to the result. @@@@example Example: Cmd> curve <- contour(x,y,vals,level,title:"Sample contour curve") Cmd> if(!isnull(curve$x)){ lineplot(keys:curve) } @@@@method During execution of contour(), x, y and vals are copied to invisible arrays __X__, __Y__ and __F__, respectively and macro _Follow() traces out the contour, keeping status information in invisible matrix __MET__. __X__, __Y__, __F__ and __MET__ are deleted before contour() is finished. @@@@credits#Credits Contour and associated macros are based on Fortran routines by Dan LaLiberte, implementing methods in Crane, C.M.(1972), Contour plotting algorithm, 'The Computer Journal', Vol. 15, pp. 382-384 and Cottafava, G., Andle Moli, G. (1969). Automatic Contour Map, 'Comm. ACM', Vol. 12, pp. 386-391. @@@@see_also#Cross reference See also contourplot(). @@@@______ ====contourplot()#contour graphs %%%% contourplot(x,y,vals,levels [,label:T] [,linefrom:T] [,draw:F]\ [,save:T] [,graphics keywords]), REAL vectors x, y, levels, with no MISSING values, REAL matrix vals %%%% @@@@usage contourplot(x,y,vals,levels [,graphics keywords]) draws unlabelled contours of a surface whose height z is known at points on a rectangular grid defined by REAL vectors x and y. The desired contour levels are defined by REAL vector levels. The height at (x[i],z[j]) is z = vals[i,j]. The values of x and y must be distinct and non-MISSING. vals must be a nrows(x) by nrows(y) REAL matrix and may have MISSING elements. Most commonly, vals[i,j] = F(x[i],y[j]) for some function F(x,y) of two variables. If the surface is not defined or is infinite at (x[i],y[j]), vals[i,j] should be MISSING. You can use most of the usual graphics keywords such as 'xlab', 'ylab', 'title', 'add' and 'show'. In particular, you can use 'linetype' to control the type of line drawn. See topic 'graph_keys'. @@@@labeling_contours contourplot(x,y,vals,levels, label:T [,graphics keywords]) does the same except that you use the mouse to position labels for each contour line that was actually drawn (some levels may be outside the minimum and maximum values in vals). A simple algorithm is used to find the contour line whose level is nearest the interpolated value at the point you click. Then this level is printed at that point. You can end labelling by pressing 'q' when the crosshairs are in the graphics window. contourplot(x,y,vals,levels, linefrom:T [,graphics keywords]) is another way to label points. You use the mouse to draw a line starting at the contour and ending where the label is then printed. contour() uses macro findcontours() to locate and label contours. You can use findcontours() directly to label contours in a contour plot that was previously drawn. @@@@save_keyword#Keyword save result <- contourplot(x,y,vals,levels,save:T [,other keywords]) sets result to structure(Contour_1:comp1,Contour_2:comp2 ...). Component I of result is structure(x:xvals, y:yvals,level:levels[I]). When level[I] is outside the range of values, xvals and yvals are NULL. Otherwise they are the x- and y-values defining the intersections of the contour with gridlines. You could use this returned structure to add the same contour curves to another graph. The following example might be appropriate when the contours were those of an estimated bivariate density function based on a bivariate sample hconcat(xvals, yvals), where xvals and yvals are REAL vectors. Cmd> chplot(xvals, yvals, symbols:"\7",show:F) #scatter plot of sample Cmd> for(i,1,levels){ @comp <- result[i] if (!isnull(@comp$x)){ lineplot(keys:strconcat(@comp,add:T,show:F)) } } Cmd> showplot(xmin:?,ymin:?,xmax:?,ymax:?) # display the plot @@@@draw_keyword#Keyword draw In place of 'save:T' you could use 'draw:F'. With both 'save:T' and 'draw:T' the contours are both drawn and returned in a structure. @@@@other_macros_needed contourplot() requires macros contour(), findcontour() and _Follow(). They are read in automatically if necessary and possible. @@@@see_also#Cross references See also contour() and findcontour(). @@@@______ ====ellipse()#shapes,line graphs %%%% ellipse(K, Q [,x0] [,npoints:m] [method:j] [,draw:T] \ [,graphics keyword phrases]), REAL scalar K > 0, 2 by 2 positive definite symmetric REAL matrix Q, REAL vector x0 or length 2, integer j, 1 <= j <= 3 %%%% @@@@usage You can use ellipse() to compute and optionally draw an ellipse with shape defined by a specified positive definite matrix and centered at a specified point ellipse(K, Q [,x0] [,graphics keywords]) computes xvals and yvals, the x- and y-coordinates of points on the ellipse defined by the equation (x - x0)' %*% solve(Q) %*% (x - x0) = K^2 The value returned is structure(x:xvals,y:yvals [,graphics keywords]). K > 0 must be a REAL scalar and Q must be a 2 by 2 REAL positive definite symmetric matrix. If x0 is an argument, it must be a REAL vector of length 2. Otherwise, rep(0,2) is used for x0. @@@@plotting_ellipse The ellipse can be plotted by Cmd> result <- ellipse(K, Q [,x0] [,graphics keywords]) Cmd> lineplot(keys:result) ellipse(K, Q [,x0], draw:T [,graphics keywords]) draws the ellipse directly and doesn't return the coordinates as a value. If the ellipse is to be added to an existing graph, include add:T as an argument. @@@@npoints_keyword#Keyword npoints ellipse(K, Q [,x0], npoints:m ...) computes m + 1 points on the ellipse, with the first and last being identical. The default value for m is 200. @@@@method_keyword#Keyword method There are several ways to select points on an ellipse. Macro ellipse() allows you to use any of three methods. ellipse(K, Q [,x0], method:k ...), where 1 <= k <= 3, does the same, except the way xvals and yvals are computed depends on k (default is k = 3). All three methods compute unit vectors u(theta) for m+1 equally spaced values of theta from 0 to 360 degrees, where u(theta) = vector(cos(theta), sin(theta)) Method 1 (Pure polar coordinates): x(theta) = x0 + K * u(theta)/r1(theta), r1(theta) = sqrt(u(theta)' %*% solve(Q) %*% u(theta)) Method 2 x(theta) = x0 + K * Q %*% u(theta)/r2(theta), where r2(theta) = sqrt(u(theta)' %*% Q %*% u(theta)) Method 3 (default) x(theta) = x0 + K*cholesky(Q)' %*% u(theta) The default method (3) seems to do the best job, but you may want to try one of the others to see if they produce a better looking ellipse. @@@@see_also#Cross references See also 'graph_keys', lineplot(), cholesky(), solve(), 'matrices' @@@@______ ====findcontour()#contour graphs %%%% info <- findcontour(x,y,vals,levels [,linefrom:T]), REAL vectors x, y, and levels, all with no MISSING values, REAL matrix vals %%%% @@@@usage After drawing a contour plot of a surface by contourplot() or plotting the results from repeated calls to contour(), you can use findcontour() to identify contours with the mouse so that they can be labeled with the contour level. info <- findcontour(x,y,vals,levels) attempts to identify the contour line (level curve) nearest the point (x0,y0) you select using the mouse. x and y are non-MISSING REAL vectors defining a grid of points and levels is a non-MISSING vector defining the levels of contours in the plots. vals is a nrows(x) by nrows(y) REAL matrix, possibly with MISSING values, of surface heights with vals[i,j] = height of the surface at (x[i],y[i]). If the surface is not defined or is infinite at (x[i],y[j]), vals[i,j] should be MISSING. Normally, findcontour(x,y,vals,levels) is used after contourplot(x,y, vals,levels). @@@@value_returned info is set to structure(x:x0, y:y0, value:val0, level:level0), where (x0, y0) is the point selected, val0 is the interpolated height of the surface at (x0,y0), and level0 is the element of levels closest to val0. If the point selected is close to a contour, level0 should be the level of the contour. If the point selected is in the rectangle defined by x[i], x[i+1] and y[j], y[j+1] and v[i,j], v[i+1,j], v[i,j+1] and v[i+1,j+1] are all MISSING, val0 and level0 will both be MISSING. @@@@labelling_a_contour You can label a contour by Cmd> info <- findcontour(x,y,vals,levels) Cmd> addstrings(info$x,info$y,paste(info$level,format:".3f")) info <- findcontour(x,y,vals,levels,linefrom:T) does the same except you use Mouse() to define a line to be drawn from a contour to a label. First select a point (x0,y0) close to the contour and then the point (x1,y1) where the label should be. With linefrom:T, info is set to structure(x:vector(x0,x1), y:vector(y0,y1), value:val0, level:level0) where val0 is the interpolated surface height at (x0,y0) and level0 is the contour level nearest to val0. You can label a contour using a line by Cmd> info <- findcontour(x,y,vals,levels,linefrom:T) Cmd> addlines(info$x,info$y, show:F) Cmd> addstrings(info$x[2],info$y[2],paste(info$level,format:".3f") Alternatively you can use macro labelcontour() to label contours. You can avoid direct use of findcontour() or labelcontour() by using 'label:T' on contourplot(). This results in labelcontour() being called once for every contour actually drawn, omitting contours whose levels are outside the range of val. @@@@see_also#Cross references See also contourplot(), contour(), labelcontour(), Mouse(). @@@@______ ====graphicshelp()#general %%%% graphicshelp(topic1 [, topic2 ...] [,usage:T]) graphicshelp(index:T) %%%% @@@@usage graphicshelp(topicname) prints help on a topic related to file graphics.mac. Usually topicname is the name of a macro in the file. When quoted, topicname may contain "wildcard" characters "*" and "?". You can also use help keyword 'key'. See help() for details. graphicshelp(topicname1, topicname2, ...) prints help on more than one topic. graphicshelp(topicname1 [, topicname2 ...], usage:T) prints just a brief summary of usage for the each topic. @@@@______ ====graph_index*# %%%% Topics in this file: bargraph(), boxplot5num(), colplot(), contour(), contourplot(), ellipse(), findcontour(), graphicshelp(), hist(), panelhist(), panelplot(), panel_graphs, piechart(), plotmatrix(), plotpanes(), rowplot(), sampcdf(), vboxplot() %%%% @@@@help_entries_available Help entries in this file bargraph() Macro do draw a bar graph boxplot5num() Macro to draw simplified boxplot based only on extremes and quartiles colplot() Macro to plot matrix colums vs row number contour() Macro to trace a level curve of a surface defined on a rectangular grid contourplot() Macro to make a contour plot of a surface defined on a rectangular grid ellipse() Macro to compute the outline of an ellipse and optionally draw it findcontour() Macro to interactively find a contour line near a point selected with the mouse graphicshelp() Macro to read help on macros in Graphics.mac hist() Macro to draw histogram labelcontour() Macro to interactively find and label contour lines near points selected with the mouse panelhist() Macro to draw histogram in pane of panel graph panelplot() Macro to draw point, line or impulse plot in pane of panel graph panel_graphs() Brief description of a panel graph. piechart() Macro to draw a pie chart of positive data plotmatrix() Macro to draw a scatter plot matrix, that is a panel graph with plots of each column of a matrix against all other columns or against all columns of another matrix plotpanes() Macro to draw point, line or impulse plots in several panes of a panel graph rowplot() Macro to plot matrix rows vs column number sampcdf() Macro to plot a sample CDF vboxplot() Macro to make a vertical boxplot @@@@______ ====hist()#distribution graphs,bar graphs %%%% hist(x [, nbars] [,keyword phrases]), REAL vector x, integer nbars >= 2 hist(x, vector(anchor,width) [,keyword phrases]), anchor REAL scalar, width > 0 scalar hist(x, edges [,keyword phrases]), edges REAL vector with increasing elements Keyword phrases are relfreq:T, freq:T, leftendin:T, outsideok:T, draw:T, save:T plus most graphics keywords %%%% @@@@usage hist(x, nbars) draws a histogram of the data in REAL vector x using with nbars equal-width bars which include all data. The bar edges are not "neat". For example, 1,1.5,2,2.5,3.0, ... are "neat", 2.71,3.82, 4.93, 6.04, ... are not "neat". The default bar heights are in the so called "density scale" with height = (M/N)/W, where M is the number of values in a bar with width W and N is the number of non-MISSING values in x. This choice makes the total area of the bars = 1. You can use keywords 'freq' and 'relfreq' (see below) to get other bar heights. A value x is included in bar i when L[i] < x <= R[i], where L and R are vectors of the left and right edges of the bars. hist(x, nbars, leftendin:T) does the same, except a value x is included in bar i when L[i] <= x < R[i]. 'leftendin:T' can be used with any variant of hist() arguments and other keywords. @@@@freq_and_relfreq_keywords hist(x, nbars, freq:T) and hist(x, nbars, relfreq:T) do the same except that bar heights are frequencies (M) or relative frequencies (M/N) with no adjustment for bar width. 'freq:T' and 'relfreq:T' can be used with any variant of hist() arguments. @@@@default_number_of_classes hist(x [,keyword phrases]) does the same using floor(log2(N)) + 1 bars. @@@@specifying_class_boundaries hist(x, vector(anchor, width) [,keyword phrases]) does the same, except the edges of the bars are of the form anchor + j*width, with the lowest and highest bar edges chosen to include all the data. hist(x, Edges [,keyword phrases]) draws a histogram whose bar boundaries are the elements of REAL vector Edges with length(Edges) > 2 and satisfying Edges[i] < Edges[i+1]. The number of bars is nbars = length(Edges) - 1. A warning message is printed when bar widths are not all equal and 'relfreq:T' or 'freq:T' is an argument. @@@@outsideok_keyword#Keyword outsideok It is normally an error when extreme data values are outside the bars defined by Edges. Without 'leftendin:T' this occurs when min(x) <= Edges[1] or max(x) > Edges[nbars+1]. With 'leftendin:T', this occurs when min(x) < Edges[1] or max(x) >= Edges[nbars+1]. hist(x, Edges, outsideok:T) does the same, except it is not an error when some extreme values are outside the bars defined by Edges. When values are outside, a warning message is printed. All of the usual plotting related keywords, including 'dumb', 'xlab', 'ylab', and 'title', may be used with hist(). See also topics 'graphs', 'graph_keys', 'graph_borders' and 'graph_files'. @@@@save_keyword#Keyword save result <- hist(x [, bar info] [,hist keywords] [,graphics keywords], save:T) returns structure(x:xvals, y:yvals, line:T [,graphics keywords]) instead of drawing the histogram. REAL vectors xvals and yvals are such that lineplot(xvals,yvals) draws the histogram. You can force the histogram to be drawn by also including 'draw:T' as an argument. @@@@keys_keyword#Keyword keys An alternate way to specify keyword values is to create a structure keyValues of keyword values and use 'keys:keyValues' as the only keyword phrase argument. For example Cmd> keyvals <- structure(xlab:"Bone length",relfreq:T,\ title:"Bone histogram", ylab:"Relative frequency",save:T) Cmd> stuff <- hist(bones,vector(0,.25),keys:keyvals) does the same as Cmd> stuff <- hist(bones,vector(0,.25),xlab:"Bone length",relfreq:T,\ title:"Bone histogram", ylab:"Relative frequency",save:T) @@@@see_also#Cross reference See also topic panelhist(). @@@@______ ====labelcontour()#contour graphs %%%% info <- labelcontour(x,y,vals,levels [,n] [,linefrom:T] [,check:F]), REAL vectors x, y, and levels, all with no MISSING values, REAL matrix vals %%%% @@@@usage You can use labelcontour() to identify and label contours after drawing a contour plot by contourplot() or plotting the results from repeated calls to contour(), . labelcontour(x,y,vals,levels) attempts to identify the contour line (level curve) nearest the point (x0,y0) you select using the mouse. Once found, the level of the contour line is added to the plot at (x0,y0). See below for the method used. x and y are REAL vectors defining a grid of points (x[i],y[j]) and levels is a REAL vector defining the levels of contours in the plots. The values of x, y and levels must be non-MISSING, and the values of x and y must be distinct. vals is a nrows(x) by nrows(y) REAL matrix, possibly with MISSING values, of surface heights with vals[i,j] = height of the surface at (x[i],y[i]). If the surface is not defined or is infinite at (x[i],y[j]), vals[i,j] should be MISSING. labelcontour(x,y,vals,levels,linefrom:T) does the same except you use the mouse to draw a line from the selected contour to the location where you want the label added. This can be useful when contour levels are close together. labelcontour(x,y,vals,levels [,linefrom:T],check:F) does the same except most checking of arguments is suppressed. This is appropriate in a macro where the arguments have already been checked. labelcontour(x,y,vals,levels,n [,linefrom:T] [,check:F]) does the same, except you can label up to n contours, where n > 0 is an integer. You can terminate plotting by pressing "q" while selecting a point with the mouse. Normally, you use labelcontour(x,y,vals,levels...) after contourplot(x,y,vals,levels). @@@@method#Method labelcontour() uses bilinear interpolation to find an approximate value v0 at the point selected. It then returns levels[i] where abs(v0 -levels[i]) = min(abs(v0-levels). @@@@see_also#Cross references See also contourplot(), contour(), findcontour(), Mouse(). @@@@______ ====news#general %%%% %%%% @@@@march_2005 050329 New macro labelcontour() to simplify labeling contours after use of contour(). @@@@november_2001 011109 Fixed bugs in contour() and _Follow() which caused contour() to fail to find certain contours. @@@@march_2001 010327 Fixed bug in boxplot5num() and made the value of option 'excludeM' the default for keyword 'excludeM'. Added keyword phrase 'printname:F' to all invocations of getmacros. @@@@february_2001 010216 Enhancements to piechart: p can be row or column vector; change in default labels @@@@january_2001 010125 New keyword phrases on macro boxplot5num(): names:Names provides labels for boxplots to be put in margin keep:T returns 5 number summaries after drawing boxplots. excludeM:F includes median in upper and lower halves when computing quartiles. @@@@______ ====panelhist()#panel graphs,bar graphs %%%% panelhist(x, edges or nbars, pos:k or pos:vector(r,c), hstrips:h,\ vstrips:v [,label:lab] [,gridlines:F] [,hist keyword phrases]\ [,graphics keyword phrases]), REAL vectors x and edges, positive integers k, r, c, h and v, CHARACTER scalar lab %%%% @@@@usage panelhist(x, nbars, pos:position, hstrips:h, vstrips:v) draws a histogram with nbars equal width bars in a pane of an h by v panel graph, an rectangular array of small graphs, where h and v are positive integers. See topic 'panel_graphs'. When position is of the form vector(r, c) where 1 <= r <= h and 1 <= c <= v are integers, the histogram is drawn in row r and column c. When position = k, with positive integer k <= h*v, the histogram is drawn in pane k, counting across rows starting in row 1. @@@@specifying_class_boundaries panelhist(x, vector(anchor,w), pos:position, hstrips:h, vstrips:v [,label:lab]) does the same, except the bars all have width w, with the edges all of the form anchor + j*w, where j is an integer. For example, vector(-.5, 1) specifies unit width bars centered on integers. panelhist(x, edges, pos:position, hstrips:h, vstrips:v [,label:lab]) does the same, except the edges of the bars are taken from the elements of REAL vector edges. They must be in strictly increasing order. @@@@freq_and_relfreq_keywords With all usages, you can include keyword phrases 'freq:T', 'relfreq:T', 'leftendin:T' and 'outsideok:T' as used with macro hist(). See topic hist() @@@@label_keyword#Keyword label With all usages you can include 'label:lab', where lab is a CHARACTER scalar. After the histogram is drawn you then use the mouse to specify a place where lab should be added to the graph. @@@@gridlines_keyword#Keyword gridlines With all usages, you can include keyword phrase 'gridlines:F' as an argument to suppress drawing lines delimiting the panes in the panel plot. This has no effect when adding histograms to a panel graph with such lines. The default is 'gridlines:T' unless 'add:T' is an argument. @@@@graphics_keywords#Graphics keywords You can use graphics keywords 'window', 'show', 'title', 'xlab', 'ylab', 'add', 'yaxis', 'xmin', 'xmax', ymin', and 'ymax' plus keywords having to do with files. See topic 'graph_keys'. With show:T, label:lab is ignored. You should use 'add:T' when drawing in a pane in an existing panel graph. You cannot use graphics keywords 'lines', 'linetype', 'impulse', 'thickness', 'xaxis', 'logx', and 'logy' and keywords having to do with tick marks. @@@@example Example: Cmd> irisdata <- matread("macanova.dat","irisdata") #Fisher data Cmd> # column 1 is variety number; columsn 2 - 5 are data Cmd> colnames <- vector("SepLen","SepWid","PetLen","PetWid") Cmd> plotmatrix(irisdata[,-1],name:"Iris Data",diaglabs:F, show:F,\ symbols:vector("\21","\22","\23")[irisdata[,1]], labels:colnames) Cmd> for(i,1,4) { # add 16 bar histograms to diagonal panelhist(irisdata[,i+1],16,pos:rep(i,2),hstrips:4,vstrips:4,\ add:T,show:i==4) } This uses plotmatrix() to create a scatter plot matrix of the Fisher iris data, and then adds histograms of each variable to the diagonal, displaying the plot only when the last histogram has been drawn. @@@@see_also#Cross references See also plotmatrix(), panelplot(), hist(), 'graph_keys'. @@@@______ ====panelplot()#panel graphs %%%% panelplot(x,y, pos:k or pos:vector(i,j), hstrips:h, vstrips:v,\ [,gridlines:F] [label:structure(labx,laby)]\ [,graphics keyword phrases]), k, i, j, h, v > 0 integers, labx, laby CHARACTER scalars panelplot(x,y, keys:structure(keyword phrases) %%%% @@@@usage#Usage panelplot(x,y,pos:position,hstrips:h,vstrips:v [,graphics keywords]) plots REAL vector y against REAL vector x in a pane of a "panel graph", an h by v array of small graphs, where h and v are positive integers. See topic 'panel_graphs' for information about such graphs. When position is of the form vector(r, c) where 1 <= r <= h and 1 <= c <= v are integers, the graph is drawn in the pane in row (horizontal strip) r and column (vertical strip) c. When position = n, with integer n satisfying 1 <= n <= h*v, the graph is drawn in pane n, counting across rows starting in row 1 and row 1. When nrows(x) <= 2, x is "expanded" to a vector of equally spaced spaced as happens with plot(), lineplot() and most other graphing commands. Otherwise, nrows(x) = nrows(y) is required. panelplot() differs from plot() and most other other graphic commands, in that y can have only one column. Another difference is that the graph has no tick marks or other information about actual values except possibly the x- or y-axis. @@@@graphics_keywords#Graphics keywords Legal graphics keywords are 'symbols', 'add', 'window', 'show', 'title', 'xlab', 'ylab', 'xmin', 'xmax', 'ymin', 'ymax', 'xaxis', 'yaxis', 'lines', 'linetype', 'impulses' and keywords having to do with files. 'title', 'xlab' and 'ylab' apply to the panel graph as a whole, not to the pane being drawn. You should use 'add:T' when drawing a pane in an existing panel graph. If you use 'symbols', you should probably choose small symbols, ASCII codes 7 and 9 - 24 ("\7" and "\11" - "\30" or "\07" and "\x09\ - "\x18". The default is symbols:"\7" (dot) except with lines:T, when the default is "". You may not use graphics keywords 'logx', 'logy' or any keywords having to do with tick marks. @@@@gridlines_keyword#Keyword gridlines panelplot(x,y,pos:position,hstrips:h,vstrips:v,gridlines:F ...) does the same, but no lines separating the panes are drawn. The default for 'gridlines' is True unless 'add:T' is an argument, in which case the default is False. @@@@labels_keyword#Keyword labels panelplot(x,y,pos:position,hstrips:h,vstrips:v,labels:vector(labsx, labsy) [,graphics keywords]), where labsx and labsy are CHARACTER scalars, allows you interactively to position a label of the form paste(labsy,"vs",labsx) on the graph. 'labels' is ignored with keyword phrase 'nolabels:F' or graphics keyword phrase 'show:F'. @@@@example Example: Cmd> irisdata <- matread("macanova.dat","irisdata") #Fisher data Cmd> # col 1 is variety number, 2 - 5 are data Cmd> colnames <- vector("SepLen","SepWid","PetLen","PetWid") Cmd> first <- T;for (i,1,4){ for (j,1,4) { if (i != j) { panelplot(y[,i],y[,j], pos:vector(i,j),hstrips:4,vstrips:4,\ title:"Scatter plot matrix of Fisher Iris data",\ symbols:vector("\21","\22","\23")[irisdata[,1]],\ show:F,add:!first) first <- F } } } Cmd> showplot() This plots every column of the Fisher iris data against every other in a 4 by 4 panel graph similar to that produced by plotmatrix(). @@@@see_also#Cross references See also topics plotmatrix(), 'graphics', 'graph_keys', plot(), lineplot(), chplot(). @@@@______ ====panel_graphs#panel graphs %%%% panelplot(x,y,...) draw a plot in a pane of a panel graph panelhist(x,...) draw a histogram in a pane of a panel graph plotmatrix(x [,y], ...) draw a panel graph containing a scatter plot matrix plotpanes(x, y, ...) draw a panel graph containing plots of columns of y against the corresponding column of x. panel graph keywords phrases hstrips:h, vstrips:v h > 0, v > 0 integers pos:k or pos:vector(i,j) k > 0, i > 0, j > 0 ingegers gridlines:F suppress lines separating panes %%%% @@@@description#Description A panel graph is a rectagular array of "panes", each of which may contain a small graph. The small graphs lack tick marks and any information as to the actual values plotted other than axes (x = 0 and/or y = 0 lines). A panel graph consists of h horizontal strips (rows) and v vertical strips (columns). These are usually delimited by lines, but that can be suppressed by keyword phrase 'gridlines:F' A panel graph is scaled so the left edge is the line x = 0, the bottom edge is the line y = 0, the right edge is the line x = v and the top edge is the line y = h. x and y values for each plot are transformed by x -> (x - (max(x)+min(x))/2)/(1.05*(max(x)-min(x))) and y -> (y - (max(y)+min(y))/2)/(1.05*(max(y)-min(y))) and then centered in a pane. This leaves a little space between the plotted points and the edges of the pane. @@@@panel_graph_macros#Panel graph macros There are several macros that draw panel graphs. panelplot(x,y,...) draw a plot in a pane of a panel graph panelhist(x,...) draw a histogram in a pane of a panel graph plotmatrix(x [,y], ...) draw a panel graph containing a scatter plot matrix plotpanes(x, y, ...) draw a panel graph containing plots of each column of y against the corresponding column of x. Each has its own help entry. @@@@hstrips_and_vstrips_keywords#Keywords hstrips and vstrips Keyword phrase 'hstrips:h,vstrips:v' are required on panelhist() and panelplot() and are optional on plotmatrix() and plotpanes(). @@@@gridlines_keyword#Keyword gridlines You can suppress the drawing of lines between the panes of a panel graph by including 'gridlines:F' as an argument to a panel graph macro creating such a graph. The default is 'gridlines:T' unless 'add:T' is an argument, when the default is 'gridlines:F'. @@@@graphics_keywords#Graphics keywords These macros recognize most of the usual graphics keywords such as 'title', 'xlab', 'show' and 'window'. Exceptions include 'logx', 'logy' and any keywords having to do with tickmarks. When using panelplot() or panelhist() to add a plot to an existing panel graph, you must use 'add:T'. When graphics keywords 'xmin', 'ymin', 'xmin' or 'xmax' are used as arguments to macros drawing panel graphs, their values replace the extremes of x and/or y in scaling data and values outside the limits are omitted. @@@@see_also#Cross references See also plotmatrix(), plotpanes(), panelhist() and panelplot(). @@@@______ ====piechart()#distribution graphs %%%% piechart(p [,start:p0] [,labels:labs] [,rlab:r1 [, rval:r2]\ [, xwidth:w] [,graphics keyword phrases]), REAL vector p with p[i] >= 0, p0 >= 0, REAL scalar, CHARACTER vector labs, REAL scalars r1 > 0, r2 > 0, w > 0 %%%% @@@@usage#Usage piechart(p) draws a pie chart of data in REAL vector p which should have no MISSING values and satisfy min(p) >= 0. The chart is drawn in a circle with radius 1. Usually p is a vector of proportions (sum(p) = 1) or percentages (sum(p) = 100), but this is not required. What is actually drawn is a pie chart with sector angles computed from the proportions p1 = p/sum(p). The angle defining sector I of the pie chart, going clockwise around the circle is 360*p1[I] degrees. By default, the starting edge of sector 1 is vertical. Each sector is is labelled by sector number, from 1 to nrows(p). There several optional keywords. @@@@keywords#Optional Keywords start piechart(p, start:p0 [,other keywords]) where p0 is a REAL scalar draws a pie chart with the starting sector edge located p0 of a cycle (abs(p0) <= 1) or p0 percent of a cycle (abs(p0) > 1) around the circle from the vertical. For instance, with p0 = .25 or 25, the starting sector edge is 90 degrees clockwise from the vertical. 'start' can be used with other keywords. labels piechart(p, labels:labs [,other keywords]), where labs is a CHARACTER vector with length(labs) = length(p), labels sector I with labs[I]. You can suppress sector labelling with labels:"". rlab piechart(p, rlab:r1 [,labels:labs] [,other keywords]) puts sector labels at radius r1 > 0 from the pie center. Usually r1 < 1. The default radius is .9. rval piechart(p, rval:r2 [,other keywords]), prints p[I] at radius r2 > 0 in sector I, I = 1, ..., length(p). Usually r2 < 1. This allows you to label sectors both with a descriptive tag and the value of the data. xwidth piechart(p, xwidth:w [other keywords]) includes 'xmin:-w/2,xmax:w/2' in the argument list of the plotting commands that draw the pie chart. You need to use 'xwidth' only when the plot without it looks like an ellipse instead of a circle. The default is 'xwidth:3.2'. You can also use many of the usual graphics keywords like 'xlab', 'ylab', 'title' and 'window'. See topic 'graph_keys'. @@@@adding_labels#Adding labels If you don't like the default labeling, you may be able to use Mouse() and addstrings() to position labels more to your liking. See Mouse() and addstrings(). @@@@______ ====plotmatrix()#multivariate graphs,panel graphs %%%% plotmatrix(x [, symbols:syms] [,bottomup:T] [,upper:T or lower:T]\ [,hstrip:h] [,vstrip:v] [,labels:labsx or nolabels:T] [,gridlines:F]\ [,diaglabs:F] [,name:xname] [,graphics keyword phrases]), x REAL matrix, ncols(x) > 1, CHARACTER scalar or vector labsx, CHARACTER scalar xname plotmatrix(x, y [, symbols:syms] [,bottomup:T] [,hstrip:h] [,vstrip:v]\ [,labels:structure(labsx,labsy) or nolabels:T] [,gridlines:F]\ [,names:vector(xname,yname)] [,graphics keyword phrases]), x, y REAL matrices with same number of rows, labsx and labsx CHARACTER scalars or vectors, xname and yname CHARACTER scalars For both usages, h > 0, v > 0 are integers, syms is a CHARACTER or non-negative integer vector %%%% @@@@usage#Usage plotmatrix(x) makes scatter plots of every column of REAL matrix x against every other column in the panes of a panel graph (see topic 'panel_graphs'). When x has nx columns, the plot is a nx by nx array of panes, with no graphs on the diagonals. When x has labels (see topic 'labels'), the column labels are printed in the diagonal boxes. Otherwise, "X1", "X2",... are used as labels. Column numbers increase down the y axis and across the x axis. @@@@diaglabels_upper_and_lower_keywords#Keywords diaglabels, upper and lower plotmatrix(x, diaglabels:F) does the same except the labels are in the margins rather than the diagonals. plotmatrix(x, upper:T) and plotmatrix(x lower:T) do the same except only the plots in the upper or lower triangle of the display are drawn in a nx-1 by nx array of plots. Labels are put in the margins. You can't use both 'upper:T' and 'lower:T'. @@@@two_matrix_arguments#Two matrix arguments plotmatrix(x,y), where x and y are REAL matrices with the same number of rows and nx and ny columns, makes a similar plot of every column of y against every column of x in a ny by nx array of small plots. Column labels of x and/or y (default "X1","X2",... and "Y1","Y2",...) are printed in the margins. plotmatrix(x,y) differs from plotpanes(x,y) in that the latter plots column j of y only against column j of x, and not all against all columns of x. @@@@symbols_keyword#Keyword symbols plotmatrix(x [,y], symbols:syms ...), where syms is a CHARACTER scalar or vector or an integer scalar or vector with values between 0 and 999 uses 'syms' as plotting symbols similarly to chplot(). The default plotting symbols are "\7", the code for a dot. Small plotting symbols (ascii codes 7 and 17 - 24, that is, "\7' and "\21" - "\30") are recommended. 'symbols:syms' can be used with any other keywords. @@@@bottomup_keyword#Keyword bottomup plotmatrix(x [,y], bottomup:T ...) does the same, except that column numbers increase up the y axis. 'bottomup:T' can be used with any other keywords. @@@@gridlines_keyword#Keyword gridlines plotmatrix(x [,y],gridlines:F ...) does the same, but no lines separating the panes are drawn. The default for 'gridlines' is True unless 'add:T' is an argument, in which case the default is False. @@@@labels_and_nolabels_keywords#Keywords labels and nolabels plotmatrix(x [,y], labels:labs ...) does the same, except column labels are taken from labs. With just x, labs should be a CHARACTER scalar or vector labsx. With x and y, labs should be structure(labsx, labsy), where labsx and labsy are CHARACTER scalars or vectors. When labsx or labsy are scalars, they are expanded by appending "1", "2", .... When they are vectors, their length must match the number of columns of x and y. plotmatrix(x [,y], nolabels:T ...) does the same except no variable labels are added to the plot. plotmatrix(x [,y], name:Name ...), does the same, except that CHARACTER variable Name is used in constructing a title and axis labels. With just x, Name should a scalar; with x and y, Name should be a vector of length 2. @@@@hstrip_and_vstrip_keywords#Keywords hstrip and vstrip plotmatrix(x [,y], hstrip:h, vstrip:v ...) does the same, except that the overall array of small plots will be h by v, where h and v are positive integers. It is an error if h or v is too small to allow all plots. @@@@graphics_keywords#Graphics keywords You can use many of the usual graphics keywords phrases with plotmatrix(), including 'symbols', 'window', 'show', 'title', 'xlab', 'ylab', 'xaxis', 'yaxis', 'lines', 'linetype' and keywords related to files. See topic 'graph_keys'. Values for 'xmin', 'xmax', 'ymin' and 'ymax' may be vectors with lengths matching the appropriate number of columns. You cannot use keywords 'add', 'logx', 'logy', 'impulses', and keywords related to tick marks. @@@@example Example: Cmd> irisdata <- matread("macanova.dat","irisdata") #Fisher data Cmd> # col 1 is variety number, 2 - 5 are data Cmd> colnames <- vector("SepLen","SepWid","PetLen","PetWid") Cmd> plotmatrix(irisdata[,-1],lower:T,name:"Iris Data",\ symbols:vector("\21","\22","\23")[irisdata[,1]], labels:colnames) Cmd> plotmatrix(irisdata[,run(2,3)],irisdata[,run(4,5)],bottomup:T,\ symbols:vector("\21","\22","\23")[irisdata[,1]],\ names:vector("Iris Cols 1,2","Iris Cols 3,4"),\ labels:structure(colnames[run(2)],colnames[-run(2)])) @@@@see_also#Cross references See also topics 'graphs', plot(), lineplot(), chplot(). @@@@______ ====plotpanes()#panel graphs,line graphs %%%% plotpanes(x,y [,addlabels:T, labels:structure(labsx,labsy)]\ [,names:vector(xname,yname)] [,hstrips:h, vstrips:v] [,gridlines:F] [,graphics keyword phrases]), x and y REAL vectors or matrices, labsx, labsy CHARACTER scalars or vectors, xname,yname CHARACTER scalars, h > 0, v > 0 integers. %%%% @@@@usage#Usage plotpanes(x, y) draws a panel graph (see topic 'panel_graphs') whose panes contain reduced size plots of each column of REAL vector or matrix y against the corresponding column of REAL vector or matrix x. If neither x and y are vectors, ncols(x) = ncols(y) is required. If one, say x, is a vector and the other (y) is a matrix, the each column of y is plotted against x. The plots are arranged in a h by v array of panes where either h = v or h = v - 1. Each pane is drawn using macro panelplot(). plotpanes(x,y) differs from plotmatrix(x,y) in that the plotpanes() plots column j of y only against column j of x, and not all against all columns of x. @@@@gridlines_keyword#Keyword gridlines plotpanes(x,y,gridlines:F ...) does the same, but no lines separating the panes are drawn. The default for 'gridlines' is True unless 'add:T' is an argument, in which case the default is False. @@@@graphics_keywords#Graphics keywords You can use most of the standard standard graphics keywords except 'add', 'logx', 'logy' and any keywords having to do with tick marks. In particular, you can use 'symbols', 'window', 'show', 'title', 'xlab', 'ylab', 'xmin', 'xmax', 'ymin', 'ymax', 'xaxis', 'yaxis', 'lines', 'linetype', 'impulses' and keywords having to do with files. See topic 'graph_keys'. The default value of 'symbols' is "\007" = "\x07" (dot), except with lines:T, when no symbols are drawn. Small characters, code 9 ("\011" or "\x09") through 24 ("\030" or "\x18") are recommended. There are no labelled ticks on the small graphs. If either or both of the x-axis or y-axis are within the limits of the data, they are drawn unless suppressed by xaxis:F or yaxis:F. @@@@equally_spaced_x_values#Equally spaced x values If nrows(x) <= 2 and differs from nrows(y), each plot has equally spaced x-values starting with x[1,] and incrementing by x[2,] (by 1 if nrows(x) = 1), just as happens with standard plotting commands such as plot(), lineplot() and chplot(). @@@@hstrips_vstrips_keywords#Keywords hstrips and vstrips plotpanes(x,y,hstrips:h, vstrips:v), h > 0, v > 0 integers, does the same except the array of plots is h by v. h and v must satisfy h*v >= max(ncols(x),ncols(y)). If just one of 'hstrips' and 'vstrips' is provided, the value for the other is selected large enough to hold all plots. 'hstrips' and 'vstrips' can be used with any other keywords. @@@@names_keyword#Keyword names plotpanes(x, y, names:vector(xname,yname)), where xname and yname are CHARACTER scalars, does the same, with xname and yname used to generate the graph title and labels for the x and y axes. 'names' can be used with any other keywords. If you use keywords 'title', 'xlab' or 'ylab', their values take precedence over labels generated from xname and yname. @@@@labels_and_addlabels_keyword#Keywords labels and addlabels plotpanes(x, y, labels:structure(labsx, labsy)), where labsx and labsy are CHARACTER scalars or vectors, enables interactive addition of labels to each plot. If labsx or labsy is a vector, it must have length max(ncols(x), ncols(y)). If either is a scalar, it is expanded to a vector by appending "1", "2", .... The labels generated for positioning using Mouse() are of the form paste(labsy[i],"vs",labsx[i]). Thus, labs(structure("X","Y")) generates labels "Y1 vs X1", "Y2 vs X2", ... . plotpanes(x,y,addlabels:T) is another way to specify labels. Column labels of x and/or y, if they exist, are used for labsx and labsy. When column labels do not exist, labsx and/or labsy are assumed to be "X" and "Y", repectively. With 'addlabels:F', the value of 'labels', if any, is ignored. With 'show:F' the values of 'labels' and 'addlabels', if any, are ignored. @@@@xmin_xmax_ymin_and_ymax_keywords#Keywords xmin, xmax, ymin and ymax The values of any of 'xmin', 'xmax', 'ymin' or 'ymax' can either be scalars to be used in every small graph, or vectors with length matching ncols(x) or ncols(y). As usual, MISSING means the extreme is to be determined from the data @@@@example Example: Cmd> irisdata <- matread("macanova.dat","irisdata") #Fisher data Cmd> # col 1 is variety number, 2 - 5 are data Cmd> colnames <- vector("SepLen","SepWid","PetLen","PetWid") Cmd> plotpanes(1,irisdata[,-1], names:vector("Index","Iris data"),\ labels:structure("Index",colnames),\ symbols:vector("\21","\22","\23")[irisdata[,1]]) This creates a 2 by 2 panel plot containing plots of all variables against the observation number. @@@@see_also#Cross references See also topics plotmatrix(), panelplot(), panelhist(), 'graphs', 'graph_keys', plot(), lineplot(), chplot(). @@@@______ ====rowplot()#line graphs,interaction graphs %%%% rowplot(x [, graphics keyword phrases]), x a REAL matrix %%%% @@@@usage#Usage rowplot(x) makes an "interaction" plot of the data in the matrix x. The plotting positions are the column numbers and the values in x. Points within each row are joined by lines. Any keywords useable in chplot may follow x. Rowplot is implemented as a pre-defined macro. If option 'dumbplot' has been set False (see options), the plot will be a low resolution plot unless 'dumb:F' is an argument. You can use all the usual graphics keywords, including 'title', 'xlab', 'ylab', and 'file'. See topics 'graphs', 'graph_keys', 'graph_border' and 'graph_ticks'. @@@@example Example: Cmd> rowplot(run(20)^(.2*run(5)'),\ title:"X^vector(.2, X^.4, X^.6, X^.8, X)'") @@@@see_also#Cross reference See also topic colplot(). @@@@______ ====sampcdf()#distribution graphs,line graphs %%%% @@@@usage#Usage sampcdf(x [,quiet:T, keep:T, draw:T] [,graphics keywords]), x REAL vector with no MISSING elements %%%% sampcdf(x [,graphics keywords]), where x is a REAL vector, draws the sample cumulative distribution function (CDF) of x. The graphics keywords may include 'xlab', 'ylab', 'title', 'linetype', 'show' and 'keep'. See topic 'graph_keys'. Any MISSING elements are removed sampcdf(x, quiet:T [,graphics keywords]) does the same except any warning messages are suppressed. sampcdf(x, save:T [,graphics keywords]) doesn't draw the CDF. Instead it returns as value structure(x:xvals,y:yvals [,graphics keywords],lines:T), where xvals and yvals are REAL vectors defining the lines making up the CDF. Note that any graphics keyword phrases that are arguments are components of the structure. sampcdf(x, save:T, draw:T [,graphics keywords]) both draws the CDF and returns a structure. @@@@example Example: Both Cmd> sampcdf(x, xlab:"Bunny weight",\ title:"Sample CDF of Bunny Weights", wind:1) and Cmd> GRAPHWINDOWS[1] <- sampcdf(x, save:T, xlab:"Bunny weight",\ title:"Sample CDF of Bunny Weights") will draw a sample CDF in graphics window 1. @@@@______ ====vboxplot()#distribution graphs %%%% vboxplot(x1,x2,...,xk [, graphics keyword phrases]), arguments REAL vectors vboxplot(Struc, [, graphics keyword phrases]), Struc a structure with REAL vector components %%%% @@@@usage#Usage vboxplot(var1, var2, ... , vark [,graphics keyword phrases]) produces vertically oriented parallel Tukey boxplots for the vectors var1 through vark. It is identical with boxplot(var1, var2, ..., vark, vertical:T [,graphics keyword phrases]). vboxplot(Struc [,graphics keyword phrases]) produces vertically oriented parallel box plots for the components of structure Struc, all of which must be vectors. It is identical with boxplot(Struct, vertical:T [,graphics keyword phrases]). You can use all the graphics keyword phrases phrases that boxplot() recognizes. For more information including how to use split() to create a structure argument, see boxplot(). @@@@______ _E_O_F_#This should be the last line, an internal End Of File marker