Reputation: 4624
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
Reputation: 677
To create a vector from a matrix row, you can simply use:
Vector(m[i, :])
Upvotes: 0
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 view
s to avoid data copying:
julia> @view m[[1],:]
1×4 view(::Array{Int64,2}, [1], :) with eltype Int64:
4 5 3 9
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.
Deciding whether or not to use views is not trivia - mostly this is whether your code benefits from buffering. However, surprisingly often view
s 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 view
s 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