# How to map a function over the given axis of a multi-dimension array and return another array?

I am trying to rotate some images, so I want to write something like

``````np.array(list(map(lambda x: rotate(x), images)))
``````

in python, where the variable `images` is an array of shape [N, H, W]. Is there a method in julia that can do this in one line as well? I have tried

``````result = map(x->rotl90(images[x,:,:]), 1:size(images))
``````

but variable `result` is of type Vector{Matrix{Float64}}, and I do not know how to convert it to an Array again.

In general, how can I apply a function over a given axis of an Array object and convert the output variable from Vector{Array{Float64}} to Array{Float64} again? Since using `map` is a powerful way to simplify and parallelize the code, it will be very convenient to have a one-line solution for this kind of problem.

Thank you very much!

I think it would be better to organize your images so that they are stacked along the third dimension of the array. Unlike numpy, which uses ‘last-dimension-major’ ordering, Julia arrays are column-major, so it is natural to let the two first dimensions hold the image.

In that case, you can do

``````mapreduce(rotl90, (x,y)->cat(x,y; dims=3), eachslice(X; dims=3))
``````

If you must orient them along the last two dimensions, it’s harder, but I think possible. But, think hard about organizing your data reasonably, instead of copying numpy.

Can’t you just write

``````map(rotate, images)
``````

?

As @DNF says, it’s better for both performance and convenience to make the last array dimension enumerate your images.
Simple ways to convert between `Vector{Array{T}}` and `Array{T}` are available in the `SplitApplyCombine.jl` package:

``````julia> using SplitApplyCombine

# split by the last dimension, rotate each image, stack back by the last dimension
julia> combinedims(map(x -> rotate(x, 45), splitdims(images)))

# same, but split/combine is done lazily without extra copies:
julia> combinedims(map(x -> rotate(x, 45), splitdimsview(images)))
``````

You could use `mapslices`:

``````result = mapslices(rotl90, images; dims = (2, 3))
``````
5 Likes

Thank you @DNF and @aplavin for the suggestion of arranging data in the third dimension! From the snippet from @StevenWhitaker, I found that my understanding of `mapslices` is incorrect. The `dims` argument is how to pick the element to be applied from the list, rather than on which axis the function will apply. And `mapslices` returns another array, and this is very convenient. I think the method from @StevenWhitaker is the simplest solution for me, and thank you all for your help!