Pages

SyntaxHighlighter

Showing posts with label transpose. Show all posts
Showing posts with label transpose. Show all posts

Saturday, April 18, 2015

Custom inclusive ranges using proc univariate

Using the LEVELS= option in proc gmap makes it easy to split data into equally distributed segments. However, there are times when the results are not exactly what you desire.

This is where the use of proc univariate can help get you most of the way there. The trick is to get the value that is just before the maximum value to display an inclusive range. You can use the SEXCL and/or EEXCL options in proc format but I wanted the legend to show the distinct unambiguous ranges.

Once completed, you can just change the levels = to discrete and use a custom format. The below code shows how this can be achived.

data sampledata ;
  format value comma8.2 ;
  do _n_ = 1 to 1000 ;
    value = round( ranuni( 1 ) * 10000, .01 ) ;
    output ;
  end ;
run ;

proc sort data = sampledata ;
  by value ;
run ;

proc univariate 
  data = sampledata
  noprint ;

  var value ;
  format _numeric_ comma8.2 ;

  output 
    out = univariate
    pctlpts  = 0 to 100 by 20  
    pctlpre = p_ ;
run ;

proc transpose data = univariate out = ranges ( rename = ( _name_ = range col1 = boundary ) drop = _label_ ) ; run ;
data maxless1( drop = value ) ; set ranges ; format previousvalue comma8.2 ; do while( value < boundary ) ; previousvalue = value ; set sampledata ; end ; output ; run ;
data formatdata( keep = fmtname start end label type ) ; retain fmtname 'unirange' type 'n' ; set maxless1 end = eof ; start = lag( boundary ) ; end = previousvalue ; if eof then end = boundary ; label = catx( " - ", put( start, comma8.2 ) , put( end, comma8.2 ) ) ; if _n_ > 1 then output ; format start end comma8.2 ; run ;
proc format lib = work cntlin = formatdata ; run ; proc freq data = sampledata ; table value ; format value unirange. ; run ;

Saturday, March 8, 2014

RGB Color Matrix

There is a scene in the movie Vegas Vacation where cousin Eddie says "I'll have some of the yella and don't get cheap on me". If you were to select a yellow, just how yellow is yellow, how blue is blue, etc...?

RGB (red, green, blue) is an additive color scheme that can produce 16.7 million colors. Each of the primary colors is comprised of hexidecimal (hex) values that range from 00 to FF or 256 unique values. If you take those 256 values to the 3rd power, for each of the 3 RGB color, you get 256**3 = 16,777,216. SAS identifies RGB colors with a CX prefix where CX000000 is black (no color), CXFF0000 is red, CX00FF00 is green, CX0000FF is blue and CXFFFFFF is white (all colors).

The idea for this post comes from a paper by Perry Watts, one of the foremost experts on SAS and colors. What I did was to extract and whittle down the 280 predefined SAS colors in the version 8 documentation and changed some of the grouped assignments. The goal was to create a one page matrix of the 161 colors that were retained. The below image reveals the structure of the retained colors in the CNS (color naming system) SAS data set.

The below code uses proc SQL to determine the size of the two dimensional array and to assign column names to the output data set. A DOW-loop is used to load data into the temporary two dimensional array to properly slot the colors into the correct locations. After that, the data from the temporary array is assigned to the columns and written to the output data set.

The compute block in proc report is used to define the background color using the RGB color code. The next image is the final resulting color matrix.

%macro rgbcolormatrix ;
  %local
    columnnames
    columncount
    tablecolumns
    tablerows
    i
    column
  ;
 
  proc sql noprint ;
    select       group
               , count( * )
      into       :columnnames separated by " "
               , :columncount separated by ","
      from       cns
      group by   group ;
  quit ;
 
  %let tablecolumns = &sqlobs. ;
  %let tablerows = %sysfunc( max( &columncount. ) ) ;
 
  data sascolors( keep = obs &columnnames. ) ;
    length Obs 3 ;
    array atemp[ &tablerows., &tablecolumns. ] $8 _temporary_ ;
    array akeep[ &tablecolumns. ] $8 &columnnames. ;
 
    do until( eof ) ;
      col + 1 ;
      do row = 1 by 1 until( last.group ) ;
        set cns end = eof ;
          by group ;
        atemp[ row, col ] = rgb ;
      end ;
    end ;
 
    do row = 1 to &tablerows. ;
      do col = 1 to &tablecolumns. ;
        akeep[ col ] = atemp[ row, col ] ;
      end ;
      obs + 1 ;
      output ;
    end ;
  run ;
 
  ods listing close ;
  ods pdf
    file      = "%sysfunc( pathname( work ) )\rgbcolormatrix.pdf"
    notoc
    author    = "Tom Bellmer"
    title     = "RGB Color Matrix" ;
 
    options nodate nonumber ;
    title ;
 
    proc report
      data = sascolors
      style( header ) = [ background = cx4d7ebf foreground = cx000000 ]
      nowd
    ;
 
      columns obs ( 'RGB Colors' &columnnames. ) ;
      define obs / center ;
 
      %do i = 1 %to &tablecolumns. ;
        %let column = %scan( &columnnames., &i. ) ;
        compute &column. ;
          if not missing( &column. ) then do ;
            if substr( &column., 3, 1 )
              in ( '0', '1', '2', '3', '4', '5', '6' ,'7' )
              and &column. not in ( 'CX00FF00', 'CX00FFFF' ) then
              colorval = cat( 'style={foreground=white background='
                , &column., ' font_size = 8pt}' ) ;
            else
              colorval = cat( 'style={foreground=black background='
                , &column., ' font_size = 8pt}' ) ;
 
            call define( _col_, 'style', colorval ) ;
          end ;
        endcomp ;
      %end ;
 
    run;
  ods pdf close;
  ods listing;
%mend ;