Re: Reducing the dimension of an array with 1-element axes
Bradley Lucier 17 Jan 2022 20:21 UTC
On 1/17/22 2:55 PM, Jens Axel Søgaard wrote:
> Hi All,
>
> Suppose you have a 3-dimensional array with domain
> (make-interval #(0 5 0) #(10 6 10)).
> The second axis only has one element.
> Therefore it can be thought of as a 2-dimensional array with domain
> (make-interval #(0 10) #(0 10)).
>
> The question is if one easily can drop a single axis?
>
> FWIW the equivalent procedure in `ndarray` is called `squeeze`.
> (I was looking for projection)
>
> https://numpy.org/doc/stable/reference/generated/numpy.ndarray.squeeze.html
> <https://numpy.org/doc/stable/reference/generated/numpy.ndarray.squeeze.html>
>
> It seems `ndarray` has an even more general procedure named `choose`.
>
> /Jens Axel
>
>
Something like this should work (untested):
(define (squeeze a)
(let* ((domain
(array-domain a))
(dim
(interval-dimension domain))
(all-axes
(iota dim))
(ks
;; indices of all the length-one axes
(filter (lambda (k)
(= (- (interval-upper-bound domain k)
(interval-lower-bound domain k))
1))
all-axes))
(length-ks
(length ks))
(permutation
;; put length-one axes first, leave the rest in order.
(list->vector (append ks (remove (lambda (k) (memv k ks))
all-axes)))))
(cond ((zero? length-ks)
a)
((= dim length-ks)
;; a has one element, this may be what python does.
(car (array->list a)))
(else
(car (array->list
(array-curry ;; this array has only one element.
(array-permute a permutation)
(- dim (length ks)))))))))
Brad