37 lines
		
	
	
		
			1023 B
		
	
	
	
		
			R
		
	
	
	
	
	
			
		
		
	
	
			37 lines
		
	
	
		
			1023 B
		
	
	
	
		
			R
		
	
	
	
	
	
#' Sliced Inverse Regression
 | 
						|
#'
 | 
						|
#' @export
 | 
						|
SIR <- function(X, y, d, nr.slices = 10L, slice.method = c("cut", "ecdf")) {
 | 
						|
 | 
						|
    if (!(is.factor(y) || is.integer(y))) {
 | 
						|
        slice.method <- match.arg(slice.method)
 | 
						|
        if (slice.method == "ecdf") {
 | 
						|
            y <- cut(ecdf(y)(y), nr.slices)
 | 
						|
        } else {
 | 
						|
            y <- cut(y, nr.slices)
 | 
						|
            # ensure there are no empty slices
 | 
						|
            if (any(table(y) == 0)) {
 | 
						|
                y <- as.factor(as.integer(y))
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Center `X`
 | 
						|
    Z <- scale(X, scale = FALSE)
 | 
						|
 | 
						|
    # Split `Z` into slices determined by `y`
 | 
						|
    slices <- Map(function(i) Z[i, , drop = FALSE], split(seq_along(y), y))
 | 
						|
 | 
						|
    # Sizes and Means for each slice
 | 
						|
    slice.sizes <- mapply(nrow, slices)
 | 
						|
    slice.means <- Map(colMeans, slices)
 | 
						|
 | 
						|
    # Inbetween slice covariances
 | 
						|
    sCov <- Reduce(`+`, Map(function(mean_s, n_s) {
 | 
						|
        n_s * tcrossprod(mean_s)
 | 
						|
    }, slice.means, slice.sizes)) / nrow(X)
 | 
						|
 | 
						|
    # Compute EDR directions
 | 
						|
    La.svd(sCov, d, 0L)$u
 | 
						|
}
 |