简体   繁体   中英

Julia: How to extract a portion of an array along a specified dimension

I am trying to figure out (in Julia) how to extract a portion of an array along a specified dimension, when the dimension itself is a variable. If the dimension is known it is straightforward to extract a portion of an array. For example, I can extract a portion along the 3rd dimension by doing something like this:

A = rand(27,33,11)
A_portion = A[:,:,3:7]

Is there a compact/efficient method for extracting a portion of an array along a variable dimension? For example, something that looks like this?

A = rand(27,33,11)
dim = 3  ## dimension along which to grab a portion of the array
first_element = 3  ## first element over specified dimension
last_element = 7  ## last element over specified dimension 
A_portion = MyFunction(A,dim,first_sample,last_sample)

One possibility is to write a set of if-statements for every possible combination of array dimension (up to some maximum number of dimensions) and dimension along which to extract the portion. For example, something like this:

MyFunction(A::Array,dim::Int,first_element::Int,last_element::Int)
    if ndims(A)==1 && dim==1
        return A[first_element:last_element]
    elseif ndims(A)==2 && dim==1
        return A[first_element:last_element,:]
    elseif ndims(A)==2 && dim==2
        return A[:,first_element:last_element]
    elseif ndims(A)==3 && dim==1
        ...
        ...
        ...

Clearly this becomes quite messy in order to allow for arrays with large numbers of dimensions. Is there a more compact/efficient approach for doing this?

The function slicedim does this:

julia> a = rand(2,2,2)
2×2×2 Array{Float64,3}:
[:, :, 1] =
 0.754584  0.133549
 0.363346  0.731388

[:, :, 2] =
 0.415001  0.907887
 0.301889  0.763312

julia> slicedim(a, 1, 2)
2×2 Array{Float64,2}:
 0.363346  0.301889
 0.731388  0.763312

julia> slicedim(a, 3, 1)
2×2 Array{Float64,2}:
 0.754584  0.133549
 0.363346  0.731388

The second argument specifies the dimension number. In the first case, we selected index 2 in dimension 1. In the second case, we selected index 1 in dimension 3.

You can also hack together approaches to this using something like a[fill(:,2)...,1] which "splats" two : s into the argument list followed by a 1 .

Jeff Bezanson's post is correct, but the function slicedim was renamed to selectdim see julia github


julia> a = rand(2,2,2)
2×2×2 Array{Float64,3}:
[:, :, 1] =
 0.835392  0.645282
 0.398793  0.774604

[:, :, 2] =
 0.00894267  0.191362
 0.700798    0.897556


julia> selectdim(a, 1, 2)
2×2 view(::Array{Float64,3}, 2, :, :) with eltype Float64:
 0.398793  0.700798
 0.774604  0.897556


julia> selectdim(a, 3, 1)
2×2 view(::Array{Float64,3}, :, :, 1) with eltype Float64:
 0.835392  0.645282
 0.398793  0.774604

(not enough reputation to write comment)

I will propose another solution because it turns out that selectdim is not compatible for objects like HDF5 dataframes. Instead I will create an array of Colon 's, repeat the colons an appropriate number of times using repeat , then unwrap them either side of the desired location using ... .

    
arr = zeros(10,10,10,10,10); # example array
d = 1  # dimension to slice
i = 4  # index on d to slice
    
slice = arr[repeat([:],d-1)..., i, repeat(Any[:],ndims(arr)-d)...]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM