# Re: [racket-users] How to apply a vector of functions to columns of a matrix?

```Ah, I see.  Well, here's a minimal version:

(require math/matrix)```
```
(define M (matrix ([1 2 3] [4 5 6] [7 8 9] [10 11 12])))

;;    Define some simple functions that we can use on our matrix
(define (add-n n) (lambda (m)  (+ n m)))

;;    This will apply a vector of functions to one piece (column) of M.  It
gets used below.
(define (matrix-apply-piece M-piece f-vec)
(for/list ((item (matrix->list M-piece))
(func f-vec))
(func item)))

M ;; show for comparison
(for/list ((r (matrix-cols M)))
(matrix-apply-piece r

Output:
#<array '#(4 3) #[1 2 3 4 5 6 7 8 9 10 11 12]>
'((3 7 11 15) (4 8 12 16) (5 9 13 17))

I had it return the results as a list of lists because that allows you to
do post-processing on the individual element results if you wanted to
(e.g.) regroup the results from column => row or vice versa before using
list->matrix to convert back to a matrix.

Here's a more complete version with better error checking and more
functionality:

(require math/matrix)

;;    Define some simple functions that we can use on our matrix
(define (add-n n) (lambda (m)  (+ n m)))

(define M (matrix ([1 2 3] [4 5 6] [7 8 9] [10 11 12])))

(define (rows-lists-to-matrix m n lst)  (list->matrix m n (apply append
lst)))
(define (cols->rows lst) (apply (curry map list) lst))

(define (matrix-apply M f-vec
[slicer matrix-rows]
[pre-reassembly identity])
;;    This helper function will apply the functions from f-vec to
;;    the pieces of M
(define (matrix-apply-piece M-piece f-vec)
(define lst (matrix->list M-piece))
(unless (= (length lst) (vector-length f-vec))
(raise-arguments-error 'matrix-apply
"Function vector must have same length
as each piece of M as returned from (slicer M)"
"slicer" slicer
"function vector" f-vec
"(slicer M)" M-piece
"overall matrix" M))
(for/list ((item lst)
(func f-vec))
(func item))) ;; end of matrix-apply-piece
;;
(rows-lists-to-matrix (matrix-num-rows M)
(matrix-num-cols M)
(pre-reassembly
(for/list ((r (slicer M)))
(matrix-apply-piece r f-vec)))))

M ;; shown for comparison

On Tue, Oct 18, 2016 at 2:08 PM, Pierre-Henry Frohring <
frohring.pierrehe...@gmail.com> wrote:

> On Tuesday, October 18, 2016 at 5:48:07 PM UTC+2, David K. Storrs wrote:
> > Hi Pierre,
> >
> > Does matrix-map-cols do what you want?  It's the last function on page
> https://docs.racket-lang.org/math/matrix_poly.html
> >
> > Also, welcome to Racket!
> >
> > Dave
> >
> >
> >
> >
> > On Mon, Oct 17, 2016 at 7:00 PM, Pierre-Henry Frohring <
> frohring.p...@gmail.com> wrote:
> > Hello,
> >
> >
> >
> > First time here, and just a few hours into Racket...
> >
> > It is not going to be rocket science ;-).
> >
> >
> >
> >
> >
> > Context:
> >
> >
> >
> >   I am using Emacs and org-mode to map each heading of an org file to a
> html file.
> >
> >   Result: one org file → one static website.
> >
> >     https://github.com/phfrohring/org-to-blog
> >
> >
> >
> >   The org file contains data that is exported to a tsv file:
> >
> >     https://github.com/phfrohring/org-to-blog/blob/master/test/
> blog.org#data
> >
> >
> >
> >   A code block in the org file is evaluated:
> >
> >     https://github.com/phfrohring/org-to-blog/blob/master/test/
> blog.org#processing
> >
> >
> >
> >   And produces a stacked-chart from the tsv data:
> >
> >     https://github.com/phfrohring/org-to-blog/blob/master/test/
> blog.org#result
> >
> >
> >
> >
> >
> > The tsv data is parsed into a kind of matrix `M` where each cell
> `M[i][j]` is a
> >
> > string.
> >
> >   ex: `M[i][0]` is the column "day" i.e. contains dates
> >
> >       `M[i][1]` is the column "description" i.e. contains strings
> >
> >
> >
> > In order to use operations over "day" column (adding dates, ...) it is
> needed to
> >
> > parse that column with something like: `iso8601->date` but not the
> "description"
> >
> > column.
> >
> >
> >
> > So, it is needed to apply a vector of functions `vF = [f_0,f_1,...]` to
> `M =
> >
> > [col_0,col_1,...]` such that: `(matrix-apply vF M) = M'` where:
> >
> >
> >
> >                 M' = [f_0(col_0),f_1(col_1),...,f_n(col_n)]
> >
> >
> >
> > Well, this function `matrix-apply` does not seem to exist and my attempt
> at
> >
> > implementing it feels clunky to say the least (ex: fs is not a vector):
> >
> >
> >
> >     (define (matrix-apply fs m)
> >
> >       (cond [(= (length fs) (matrix-num-cols m))
> >
> >              (matrix-augment
> >
> >               (map (λ (f_col)
> >
> >                      (apply
> >
> >                       (λ (mat) (matrix-map (car f_col) mat))
> >
> >                       (cdr f_col)))
> >
> >                    (zip
> >
> >                     fs
> >
> >                     (matrix-cols m2))))]
> >
> >             [#t (error fs)]))
> >
> >
> >
> >     (define m2 (matrix [[1 2 3 4]
> >
> >                         [1 2 3 4]]))
> >
> >
> >
> >     (matrix-apply (list sqr sqr sqr sqr) m2)
> >
> >
> >
> >     => (array #[#[1 4 9 16] #[1 4 9 16]])
> >
> >
> >
> >
> >
> > Am I missing the elephant in the corridor? Is an implementation floating
> >
> > somewhere?
> >
> >
> >
> > Thx!
> >
> >
> >
> > --
> >
> > You received this message because you are subscribed to the Google
> Groups "Racket Users" group.
> >
> > To unsubscribe from this group and stop receiving emails from it, send
> >
> > For more options, visit https://groups.google.com/d/optout.
>
> Thx Dave!
>
> Assuming I understood the doc correctly:
>
>     (matrix-map-cols f M) → (Matrix B)
>       f : ((Matrix A) -> (Matrix B))
>       M : (Matrix A)
>
> So, `f` expects a matrix as an input.  What I am trying to do is to apply a
> vector of functions `[f_i]` such that each `f_i` acts on a vector: the
> columns
> of the matrix M.  Also, the type M[i,j] may differ from one column to the
> other.
>
> Something that would look like:
>
>     (matrix-map-cols [f] M) → (Matrix [B_1 B_2 … B_n])
>       where each f_i in [f] has type: f_i : (List A_i) → (List B_i)
>       M : (Matrix [A_1 A_2 … A_n])
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an