1#' Transform an integer to an array of base-n digits 2#' 3#' Transform an integer to an array of base-n digits 4#' 5#' This function converts the elements of an integer vector as an array of its 6#' digits. The base of the numbering scheme may be changed away from 10, which 7#' defines our decimal system, to any other integer value. For base=2, the 8#' number is returned in the binary system. The least significant digit has the 9#' highest index in the array, i.e. it appears on the right. The highest 10#' exponent is at position 1, i.e. left. 11#' 12#' To write decimal values in another base is very common in computer science. 13#' In particular at the basis 2 the then possible values 0 and 1 are often 14#' interpreted as logical false or true. And at the very interface to 15#' electrical engineering, it is indicated as an absence or presence of 16#' voltage. When several bit values are transported synchronously, then it is 17#' common to give every lane of such a data bus a unique 2^x value and 18#' interpret it as a number in the binary system. To distinguish 256 characters 19#' one once needed 8 bit ("byte"). It is the common unit in which larger 20#' non-printable data is presented. Because of the many non-printable 21#' characters and the difficulty for most humans to memorize an even longer 22#' alphabet, it is presented as two half bytes ("nibble") of 4 bit in a 23#' hexadecimal presentation. Example code is shown below. 24#' 25#' For statisticians, it is more likely to use bit representations for hashing. 26#' A bit set to 1 (TRUE) at e.g. position 2, 9 or 17 is interpreted as the 27#' presence of a particular feature combination of a sample. With baseOf, you 28#' can refer to the bit combination as a number, which is more easily and more 29#' efficiently dealt with than with an array of binary values. The example code 30#' presents a counter of combinations of features which may be interpreted as a 31#' Venn diagram. 32#' 33#' @param v A single integer value to be transformed. 34#' @param base The base to which to transform to. 35#' @param len The minimal length of the returned array. 36#' @author Steffen Moeller \email{moeller@@debian.org} 37#' @keywords base 38#' @examples 39#' 40#' # decimal representation 41#' baseOf(123) 42#' 43#' # binary representation 44#' baseOf(123, base = 2) 45#' 46#' # octal representation 47#' baseOf(123, base = 8) 48#' 49#' # hexadecimal representation 50#' baseOf(123, base = 16) 51#' 52#' # hexadecimal with more typical letter-notation 53#' c(0:9, LETTERS)[baseOf(123, 16)] 54#' 55#' # hexadecimal again, now showing a single string 56#' paste(c(0:9, LETTERS)[baseOf(123, 16)], collapse = "") 57#' 58#' # decimal representation but filling leading zeroes 59#' baseOf(123, len = 5) 60#' 61#' # and converting that back 62#' sum(2^(4:0) * baseOf(123, len = 5)) 63#' 64#' # hashing and a tabular venn diagram derived from it 65#' m <- matrix(sample(c(FALSE, TRUE), replace = TRUE, size = 300), ncol = 4) 66#' colnames(m) <- c("strong", "colorful", "nice", "humorous") 67#' names(dimnames(m)) <- c("samples", "features") 68#' head(m) 69#' 70#' m.val <- apply(m, 1, function(X) { 71#' return(sum(2^((ncol(m) - 1):0) * X)) 72#' }) 73#' m.val.rle <- rle(sort(m.val)) 74#' m.counts <- cbind( 75#' baseOf(m.val.rle$value, base = 2, len = ncol(m)), 76#' m.val.rle$lengths 77#' ) 78#' colnames(m.counts) <- c(colnames(m), "num") 79#' rownames(m.counts) <- apply(m.counts[, 1:ncol(m)], 1, paste, collapse = "") 80#' m.counts[1 == m.counts[, "nice"] & 1 == m.counts[, "humorous"], , drop = FALSE] 81#' m.counts[, "num", drop = TRUE] 82#' @export 83baseOf <- function(v, 84 base = 10, 85 len = 1) { 86 if (is.null(v)) { 87 stop("v is null") 88 } 89 if (length(v) == 0) { 90 return(integer(0)) 91 } 92 93 if (any(as.integer(v) != v)) { 94 stop("non-integer value(s) provided for v.") 95 } 96 97 if (length(v) > 1) { 98 # this returns a list which may have vectors of varying lenths 99 val.list <- lapply(X = v, FUN = baseOf.inner, base = base, len = len) 100 longest <- max(sapply(val.list, length)) 101 102 # call again, forcing all elements to have the same lenth 103 retval <- t(sapply(X = v, FUN = baseOf.inner, base = base, len = longest)) 104 105 # add informative row and column names 106 rownames(retval) <- paste0("v.", v) 107 colnames(retval) <- paste0("b.", rev(c(0, base^(1:(longest - 1))))) 108 109 retval 110 } 111 else { 112 retval <- baseOf.inner(v = v, base = base, len = len) 113 } 114 115 retval 116} 117 118 119# Transform integer to array of digits in specified 120baseOf.inner <- function(v, 121 base = 10, 122 len = 1) { 123 if (is.na(v)) { 124 return(rep(NA, len)) 125 } 126 127 if (v == 0) { 128 return(rep(0, len)) 129 } 130 131 remainder <- v 132 i <- len 133 ret <- NULL 134 while (remainder > 0 || i > 0) { 135 # print(paste("i=",i," remainder=",remainder)) 136 m <- remainder %% base 137 if (is.null(ret)) { 138 ret <- m 139 } 140 else { 141 ret <- c(m, ret) 142 } 143 remainder <- remainder %/% base 144 i <- i - 1 145 } 146 147 if (length(ret) > 1) { 148 names(ret) <- rev(c(0, base^(1:(length(ret) - 1)))) 149 } 150 151 return(ret) 152} 153