Nothing
#' Reorganize results of search for close (similar) values in matrix-view
#'
#' \code{closeMatchMatrix} reorganizes/refines results from simple search of similar values of 2 sets of data by \code{\link[wrMisc]{findCloseMatch}} (as list for one-to many relations) to more human friendly/readable matrix.
#' This function returns results combining two sets of data which were initially compared (eg measured and threoretical values) as matrix-view using output of \code{\link[wrMisc]{findCloseMatch}} and both original datastes
#' Additional information (covariables, annotation, ...) may be included as optional columns for either 'predMatr' or 'measMatr'.
#' Note : It is important to run \code{\link[wrMisc]{findCloseMatch}} with \code{sortMatch=FALSE} !
#' Note : Results presented based on view of 'predMatr', so if multiple 'measMatr' are at within tolared distance, lines of 'measMatr' will be repeated;
#' Note : Distances 'disToMeas' and 'ppmToPred' are oriented : neg value if measured is lower than predicted (and pos values if higher than predicted);
#' Note : Returns \code{NULL} when nothing within given limits of comparison;
#' @param closeMatch (list) output from \code{\link[wrMisc]{findCloseMatch}}, ie list with hits for each 'x' (1st argument) : named vectors of value & x index in name; run with 'sortMatch'=F
#' @param predMatr (vector or matrix) predicted values, the column 'colPred' indicates which column is used for matching from \code{\link[wrMisc]{findCloseMatch}}; if column 'id' present this column will be used as identifier for matching
#' @param measMatr (vector or matrix) measured values, the column 'colMeas' indicates which column is used for matching from \code{\link[wrMisc]{findCloseMatch}}; if column 'id' present this column will be used as identifier for matching
#' @param prefMatch (character, length=2) prefixes ('^x' and/or '^y') thay may have been added by \code{findCloseMatch}
#' @param colPred (integer or text, length=1) column of 'predMatr' with main values of comparison
#' @param colMeas (integer or text, length=1) column of 'measMatr' with main measures of comparison
#' @param limitToBest (integer) column of 'measMatr' with main measures of comparison
#' @param asDataFrame (logical) convert results to data.frame if non-numeric matrix produced (may slightly slow down big results)
#' @param origNa (logical) will try to use original names of objects 'predMatr','measMatr', if they are not multi-column and not conflicting other output-names (otherwise 'predMatr','measMatr' will appear)
#' @param silent (logical) suppress messages
#' @param callFrom (character) allows easier tracking of message(s) produced
#' @param debug (logical) for bug-tracking: more/enhanced messages
#' @return results as matrix-view based on initial results from \code{\link[wrMisc]{findCloseMatch}}, including optional columns of suppelemental data for both sets of data for comparison. Returns \code{NULL} when nothing within limits
#' @seealso \code{\link[wrMisc]{findCloseMatch}}, \code{\link[wrMisc]{checkSimValueInSer}}
#' @examples
#' aA <- c(11:17); bB <- c(12.001,13.999); cC <- c(16.2,8,9,12.5,15.9,13.5,15.7,14.1,5)
#' (cloMa <- findCloseMatch(aA,cC,com="diff",lim=0.5,sor=FALSE))
#' # all matches (of 2d arg) to/within limit for each of 1st arg ('x'); 'y' ..to 2nd arg = cC
#' (maAa <- closeMatchMatrix(cloMa,aA,cC,lim=TRUE)) #
#' (maAa <- closeMatchMatrix(cloMa,aA,cC,lim=FALSE,origN=TRUE)) #
#' (maAa <- closeMatchMatrix(cloMa,cbind(valA=81:87,aA),cbind(valC=91:99,cC),colM=2,
#' colP=2,lim=FALSE))
#' (maAa <- closeMatchMatrix(cloMa,cbind(aA,valA=81:87),cC,lim=FALSE,deb=TRUE)) #
#' a2 <- aA; names(a2) <- letters[1:length(a2)]; c2 <- cC; names(c2) <- letters[10+1:length(c2)]
#' (cloM2 <- findCloseMatch(x=a2,y=c2,com="diff",lim=0.5,sor=FALSE))
#' (maA2 <- closeMatchMatrix(cloM2,predM=cbind(valA=81:87,a2),measM=cbind(valC=91:99,c2),
#' colM=2,colP=2,lim=FALSE,asData=TRUE))
#' (maA2 <- closeMatchMatrix(cloM2,cbind(id=names(a2),valA=81:87,a2),cbind(id=names(c2),
#' valC=91:99,c2),colM=3,colP=3,lim=FALSE,deb=FALSE))
#' @export
closeMatchMatrix <- function(closeMatch, predMatr, measMatr, prefMatch=c("^x","^y"), colPred=1, colMeas=1, limitToBest=TRUE, asDataFrame=FALSE, origNa=TRUE,silent=FALSE,callFrom=NULL,debug=FALSE){
fxNa <- .composeCallName(callFrom,newNa="closeMatchMatrix")
namesMXY <- c(deparse(substitute(closeMatch)), deparse(substitute(predMatr)), deparse(substitute(measMatr)))
if(debug) silent <- FALSE
if(debug) {message(fxNa,".. xxidentToMatr2a\n")}
if(length(closeMatch) <1) message(fxNa," INPUT EMPTY, NOTHING TO DO !!")
if(length(dim(predMatr)) <2) {
predMatr <- cbind(id=if(is.null(names(predMatr))) 1:length(predMatr) else names(predMatr), predMatr)
if(is.character(colPred)) colnames(predMatr)[2] <- colPred
colPred <- 2
} else if(!is.matrix(predMatr)) predMatr <- as.matrix(predMatr)
if(is.character(colPred)) { chCol <- colnames(predMatr)==colPred
if(sum(chCol) <1) { if(!silent) message(fxNa," PROBLEM : '",colPred,"' not found in ",namesMXY[2]," !!")
colPred <- 2
} else colPred <- which(chCol)}
if("id" %in% colnames(predMatr)) {
if(colnames(predMatr)[1] != "id") {tmp <- colnames(predMatr)=="id"
predMatr <- predMatr[,c(which(tmp),which(!tmp))]}
} else { colPred <- colPred +1
predMatr <- cbind(id=if(is.null(rownames(predMatr))) 1:nrow(predMatr) else rownames(predMatr), predMatr)}
if(length(dim(measMatr)) <2) {
measMatr <- cbind(id=if(is.null(names(measMatr))) 1:length(measMatr) else names(measMatr), measMatr)
if(is.character(colMeas)) colnames(measMatr)[2] <- colMeas
colMeas <- 2
} else if(!is.matrix(measMatr)) measMatr <- as.matrix(measMatr)
if(is.character(colMeas)) colMeas <- which(colnames(measMatr)==colMeas)
if("id" %in% colnames(measMatr)) {
if(colnames(measMatr)[1] != "id") {tmp <- colnames(measMatr)=="id"
measMatr <- measMatr[,c(which(tmp),which(!tmp))]}
} else { colMeas <- colMeas +1
measMatr <- cbind(id=if(is.null(rownames(measMatr))) 1:nrow(measMatr) else rownames(measMatr), measMatr) }
txt <- c(" TROUBLE AHEAD : ", "elements of 'closeMatch' have no name !!")
chCloseM <- sub(prefMatch[1],"", names(closeMatch)) %in% predMatr[,"id"]
if(all(!chCloseM, na.rm=TRUE)) stop("None of (list-) names of 'closeMatch' fits to 'predMatr'")
if(any(!chCloseM, na.rm=TRUE) && !silent) message(fxNa,txt[1],sum(chCloseM)," out of ",length(chCloseM)," elements from 'closeMatch' not found in 'predMatr'")
chCloMaNa <- nchar(names(closeMatch)) # check for empty names
if(any(chCloMaNa <1, na.rm=TRUE)) message(fxNa,txt[1],sum(chCloMaNa <1)," out of ",length(closeMatch)," (list-)",txt[2])
chCloMaN2 <- nchar(unlist(sapply(closeMatch, names)))
if(any(chCloMaN2 <1, na.rm=TRUE)) message(fxNa,txt[1],sum(chCloMaN2 <1)," out of ",sum(sapply(closeMatch,length))," indiv ",txt[2]) ##if(is.null(colnames(predMatr))) colnames(predMatr) <- "predMatr"
nMatch <- sapply(closeMatch,length)
if(debug) {message(fxNa,".. xxidentToMatr2c\n")}
## main joining of predMatr & measMatr
measNa <- sub(prefMatch[2],"", unlist(lapply(closeMatch, names))) # names of measured (y) to each 'y'
if(length(grep("[[:alpha:]]", measNa)) <1) measNa <- as.integer(measNa)
prediNa <- sub(prefMatch[1],"", names(closeMatch)) # ..'x', ie predMatr
if(length(grep("[[:alpha:]]", prediNa)) <1) prediNa <- as.integer(prediNa)
txt <- c(fxNa," TROUBLE ahead, trouble matching names or NAs already in 'closeMatch' (see ")
if(any(is.na(prediNa))) message(txt,"'x'/predicted) !!")
if(any(is.na(measNa))) message(txt,"'y'/measured) !!")
chP <- match(rep(prediNa, nMatch), predMatr[,1])
partP <- if(length(chP)==1) matrix(predMatr[chP,], nrow=1, dimnames=list(rownames(predMatr)[chP], colnames(predMatr))) else predMatr[chP,]
partM <- if(length(measNa)==1) matrix(measMatr[measNa,], nrow=1, dimnames=list(rownames(measMatr)[measNa], colnames(measMatr))) else measMatr[measNa,]
if(origNa && length(grep(" = ",namesMXY[2:3])) >0) { origNa <- FALSE
if(!silent) message(fxNa,"Reset argument 'origNa' to FALSE since names of 'predMatr' and/or 'measMatr' result of formula and would be too long")}
if(origNa) {
colnames(partP)[1] <- paste("id",namesMXY[2],sep=".")
colnames(partM)[1] <- paste("id",namesMXY[3],sep=".")
if(ncol(partP)==2) colnames(partP)[colPred] <- namesMXY[2] else {
colnames(partP)[-1] <- paste(namesMXY[2],colnames(partP)[-1],sep=".")}
if(ncol(partM)==2) colnames(partM)[colMeas] <- namesMXY[3] else {
colnames(partM)[-1] <- paste(namesMXY[3],colnames(partM)[-1],sep=".")}
} else {
dupNa <- duplicated(c(colnames(partP), colnames(partM)))
if(any(dupNa)) {
dupNa <- c(colnames(partP), colnames(partM))[dupNa]
chNaP <- colnames(partP) %in% dupNa
chNaM <- colnames(partM) %in% dupNa
colnames(partP)[which(chNaP)] <- paste(colnames(partP)[which(chNaP)],"pred",sep=".")
colnames(partM)[which(chNaM)] <- paste(colnames(partM)[which(chNaM)],"meas",sep=".") }
}
out <- cbind(partP, partM)
colMeas <- colMeas + ncol(partP)
if(debug) {message(fxNa,".. xxidentToMatr2d\n")}
chOrd <- order(as.character(out[,colMeas])) # grouping done by measured mass; tapply will always sort by this alphabetically (so instead of repeated re-sorting...)
if(!identical(chOrd, 1:nrow(out))) out <- out[chOrd,]
## add suppelemental info (eg distance, if dist is closest, ...)
if(nrow(out) <1) {if(!silent) message(fxNa," nothing left"); return(NULL)} else {
di <- cbind(me=as.numeric(out[,colMeas]), pr=if(length(colPred) >0) as.numeric(out[,colPred]))
out <- cbind(out, disToPred=di[,2] -di[,1], ppmToPred=XYToDiffPpm(di[,2], di[,1], nSign=5, callFrom=fxNa), nByGrp=NA, isMin=NA, nBest=NA) # note : ppm as normalized difference 1e6*(meas - ref)/ref
if(debug) {message(fxNa,".. xxidentToMatr2e\n")}
## inspect groups for multiple values
ch1 <- table(out[,colPred])
out[,ncol(out) -2] <- rep(ch1, ch1) # nByGrp
tmp <- tapply(as.numeric(out[,"disToPred"]), out[,colPred], function(x) {if(length(unique(x))==1) rep(1,length(x)) else 0+(abs(x)==min(abs(x)))} )
out[,"isMin"] <- unlist(tmp)
tmp <- tapply(as.integer(out[,"isMin"]), out[,colPred], sum) # prepare nBest
out[,ncol(out)] <- rep(tmp, ch1) # nBest
ch3 <- out[,ncol(out) -1] =="0"
if(any(ch3)) out[which(ch3), ncol(out)] <- 0 # reset lines which are not best dist as nBest=0
chMax <- out[,ncol(out) -1] >0
if(limitToBest && any(!chMax)) out <- out[which(chMax),] # filter & add col for nBest
if(debug) { message(fxNa,".. xxidentToMatr2f \n")}
## re-sort
if(nrow(out) >1) {chOrd <- as.integer(order(out[,1])) #out[,"id.predMatr"]
out <- out[chOrd,]}
if(is.character(out) & asDataFrame) out <- convMatr2df(out)[,-1]
out }}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.