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

**URL:** <https://discourse.julialang.org/t/how-to-map-a-function-over-the-given-axis-of-a-multi-dimension-array-and-return-another-array/83586>\
**Category:** General Usage\
**Tags:** arrays, splitapplycombine, mapslices\
**Created:** [June 30, 2022, 9:31pm UTC](https://discourse.julialang.org/t/how-to-map-a-function-over-the-given-axis-of-a-multi-dimension-array-and-return-another-array/83586 "2022-06-30T21:31:33Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![zhangqian](https://avatars.discourse-cdn.com/v4/letter/z/b4bc9f/32.png) [@zhangqian](https://discourse.julialang.org/u/zhangqian)\
**Post date:** [June 30, 2022, 9:31pm UTC](https://discourse.julialang.org/t/how-to-map-a-function-over-the-given-axis-of-a-multi-dimension-array-and-return-another-array/83586/1 "2022-06-30T21:31:33Z")

</div>

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

```python
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

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

```

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!

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [June 30, 2022, 10:12pm UTC](https://discourse.julialang.org/t/how-to-map-a-function-over-the-given-axis-of-a-multi-dimension-array-and-return-another-array/83586/2 "2022-06-30T22:12:17Z")

</div>

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

```julia
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.

> [@zhangqian](#):
>
> `map(lambda x: rotate(x), images)`

Can’t you just write

```julia
map(rotate, images)

```

?

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [June 30, 2022, 10:31pm UTC](https://discourse.julialang.org/t/how-to-map-a-function-over-the-given-axis-of-a-multi-dimension-array-and-return-another-array/83586/3 "2022-06-30T22:31:01Z")

</div>

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
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)))

```

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [July 1, 2022, 1:16pm UTC](https://discourse.julialang.org/t/how-to-map-a-function-over-the-given-axis-of-a-multi-dimension-array-and-return-another-array/83586/4 "2022-07-01T13:16:47Z")

</div>

You could use `mapslices`:

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

```

---

<div class="post-metadata">

**Author:** ![zhangqian](https://avatars.discourse-cdn.com/v4/letter/z/b4bc9f/32.png) [@zhangqian](https://discourse.julialang.org/u/zhangqian)\
**Post date:** [July 1, 2022, 3:27pm UTC](https://discourse.julialang.org/t/how-to-map-a-function-over-the-given-axis-of-a-multi-dimension-array-and-return-another-array/83586/5 "2022-07-01T15:27:32Z")

</div>

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!
