NoseKnowsAll
NoseKnowsAll

Reputation: 4624

Creating a row vector from slice of matrix

I was wondering if anyone has a clear way to return a row vector from a slice of a matrix?

matrix[k,:]

actually returns a vector of size (n,), so it's automatically treated by Julia as a column vector, not a row vector. So far, I've been using the syntax

matrix[k,:]'

to represent the row vector of size (1,n), but somehow this seems clunky and not at all intuitive that this is a row vector and not a column vector. Most mathematicians I've talked to assume incorrectly that this isn't a row vector.

Is there a more Julianic way to get a row vector slice, that is more clear?

Upvotes: 3

Views: 988

Answers (2)

aurelia
aurelia

Reputation: 677

To create a vector from a matrix row, you can simply use:

Vector(m[i, :])

Upvotes: 0

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

julia> m=rand(1:10,3,4)
3×4 Array{Int64,2}:
 4  5  3  9
 6  8  1  5
 4  5  3  4

julia> m[[1],:]
1×4 Array{Int64,2}:
 4  5  3  9

Note that it is almost always better to use views to avoid data copying:

julia> @view m[[1],:]
1×4 view(::Array{Int64,2}, [1], :) with eltype Int64:
 4  5  3  9

Explanation:

Selection of Array elements can be done either by using scalars or by using iterables. Using a scalar causes the given dimension to be dropped. On the other hand using a collection does not drop the dimension. For better explanation consider yet another example:

julia> m[1:1,1:1]
1×1 Array{Int64,2}:
 4

You can see that only one element has been selected but the dimensions have not been dropped. Hence you end-up having a Matrix (that is 2-dimensional Array) having only one row and one column.

EDIT (comment by Colin T Bowers - thank you!)

Deciding whether or not to use views is not trivia - mostly this is whether your code benefits from buffering. However, surprisingly often views are better.

julia> const vals = rand(200,200);

julia> using BenchmarkTools

julia> @btime sum(view(vals,1,:))
  169.392 ns (1 allocation: 48 bytes)
95.08924081258299

julia> @btime sum(vals[1,:])
  184.384 ns (1 allocation: 1.77 KiB)
95.08924081258299

Let us define our own summing function.

julia> function mysum(a::AbstractVector{A}) where A <: Number
    v = zero(A)
    @inbounds @simd for i in 1:length(a)
        v += a[i]
    end
    v
end;

julia> @btime mysum(view(vals,1,:))
  141.931 ns (0 allocations: 0 bytes)
95.08924081258299

julia> @btime mysum(vals[1,:])
  174.934 ns (1 allocation: 1.77 KiB)
95.08924081258297

It can be clearly seen that when you are summing row once views are still better. Last but not least summing by columns is of course several time faster and copying the data is expensive as hell:

julia> @btime sum(view(vals,:,1))
  25.828 ns (1 allocation: 48 bytes)
96.04440265541243

julia> @btime mysum(view(vals,:,1))
  13.927 ns (0 allocations: 0 bytes)
96.04440265541243

julia> @btime sum(vals[:,1])
  167.745 ns (1 allocation: 1.77 KiB)
96.04440265541243

Upvotes: 5

Related Questions