Dima Lituiev
Dima Lituiev

Reputation: 13116

Converting Array{Array{Float64,1},1} to Array{Float64,2} in Julia

My problem is similar to the problem described earlier, with the difference that I don't input numbers manually. Thus the accepted answer there does not work for me.

I want to convert the vector of cartesian coordinates to polars:

function cart2pol(x0,
                  x1)
    rho = sqrt(x0^2 + x1^2)
    phi = atan2(x1, x0)
    return [rho, phi]
end

@vectorize_2arg Number cart2pol

function cart2pol(x)
    x1 = view(x,:,1)
    x2 = view(x,:,2)
    return cart2pol(x1, x2)
end



x = rand(5,2)

vcat(cart2pol(x))

The last command does not collect Arrays for some reason, returning the output of type 5-element Array{Array{Float64,1},1}. Any idea how to cast it to Array{Float64,2}?

Upvotes: 3

Views: 1226

Answers (2)

Jeff Bezanson
Jeff Bezanson

Reputation: 3207

The function mapslices can also do this, essentially transforming the rows of the input:

julia> x = rand(5,2)
5×2 Array{Float64,2}:
 0.458583   0.205246 
 0.285189   0.992547 
 0.947025   0.0853141
 0.79599    0.67265  
 0.0273176  0.381066 

julia> mapslices(row->cart2pol(row[1],row[2]), x, [2])
5×2 Array{Float64,2}:
 0.502419  0.420827 
 1.03271   1.291    
 0.95086   0.0898439
 1.04214   0.701612 
 0.382044  1.49923  

The last argument specifies dimensions to operate over; e.g. passing [1] would transform columns.

As an aside, I would encourage one or two stylistic changes. First, it's good to map like to like, so if we stick with the row representation then cart2pol should accept a 2-element array (since that's what it returns). Then this call would just be mapslices(cart2pol, x, [2]). Or, if what we're really trying to represent is an array of coordinates, then the data could be an array of tuples [(x1,y1), (x2,y2), ...], and cart2pol could accept and return a tuple. In either case cart2pol would not need to be able to operate on arrays, and it's partly for this reason that we've deprecated the @vectorize_ macros.

Upvotes: 4

halirutan
halirutan

Reputation: 4341

If you look at the definition of cat (which is the underlying function for hcat and vcat), you see that you can collect several arrays into one single array of dimension 2:

cat(2, [1,2], [3,4], [5,6])

2×3 Array{Int64,2}:
 1  3  5
 2  4  6

This is basically what you want. The problem is that you have all your output polar points in an array itself. cat expects you to provide them as several arguments. This is where ... comes in.

... used to cause a single function argument to be split apart into many different arguments when used in the context of a function call.

Therefore, you can write

cat(2, [[1,2], [3,4], [5,6]]...)

2×3 Array{Int64,2}:
 1  3  5
 2  4  6

In your situation, it works exactly in the same way (I changed your x to have the points in columns):

x=rand(2,5)
cat(2, cart2pol.(view(x,1,:),view(x,2,:))...)

2×5 Array{Float64,2}:
 0.587301  0.622    0.928159  0.579749  0.227605
 1.30672   1.52956  0.352177  0.710973  0.909746

Upvotes: 6

Related Questions