How do I create vectors from matrix columns?


#1

What is the most simple syntax for extracting a matrix columns into separate vectors?
My matrix is in a text file (with the name data.dat) with 19 columns and 30000 rows , where each row ends with a line feed \n

In principle, say I have this matrix in the text file:

1 2 3 \n
4 5 6 \n
7 8 9 \n

And want the vectors
v1 = [1, 4, 7]
v2 = [2, 5, 8]
v3 = [3, 6, 9]


#2

There might be a neat trick that is simpler, but what about

julia> a = [1 2 3; 4 5 6; 7 8 9];

julia> (v1, v2, v3) = [a[:,x] for x in 1:size(a,1)]
3-element Array{Array{Int64,1},1}:
 [1, 4, 7]
 [2, 5, 8]
 [3, 6, 9]

after creating the matrix (probably using readdlm)?


#3

Thanks,

I solved it by:

file = open("data.dat")
data = readdlm("data.dat")
close(file)

v1 = data[:,1] 
v1 = transpose(v1)

v2 = data[:,2] 
v2 = transpose(v2)

# ... and so forth for all columns

#4

You don’t need the transpose. Just data[:,1] works fine. Also, you don’t need to open or close the file. @sbromberger 's approach works great.


#5

It’s probable that you want views instead of copies:

columns = [view(a, :, i) for i in 1:size(a, 2)]

Also note that you want size(a, 2), rather than size(a, 1).


#6

I’ve always thought it’d be nice with a method that allowed you to specify size(a, :columns) (or mean, sum, etc.)


#7

I have several times wanted a columns(M) function that returned that vector of views.


#8

Or even better, that returned an iterator across the columns which could be collected to form that Vector. That’d actually be fairly easy to implement, I guess :slight_smile: But maybe not much is gained by an iterator if it’s already views?


#9
julia> columns(M) = (view(M, :, i) for i in 1:size(M, 2))
columns (generic function with 1 method)

julia> M = rand(3, 3)
3×3 Array{Float64,2}:
 0.594998  0.565428  0.19341
 0.522016  0.651766  0.39392
 0.652366  0.59112   0.375274

julia> columns(M)
Base.Generator{UnitRange{Int64},##3#4{Array{Float64,2}}}(#3, 1:3)

julia> for i in columns(M)
       println(i)
       end
[0.594998, 0.522016, 0.652366]
[0.565428, 0.651766, 0.59112]
[0.19341, 0.39392, 0.375274]

#10

The problem with an iterator is that you can’t do columns(M)[2].


#11

But maybe it’s all a bit pointless, since these days you can write

ulia> @view M[:, 2]
3-element SubArray{Float64,1,Array{Float64,2},Tuple{Base.Slice{Base.OneTo{Int64}},Int64},true}:
 0.565428
 0.651766
 0.59112

#12

I don’t think it’s pointless - I like for col in columns(M) :slight_smile:


#13

Yes, me too!


#14

I think it could also solve the issue of colwise inplace operations, e.g. https://github.com/JuliaData/DataTables.jl/issues/36 EDIT No that’s silly - because DataFrames have eachcol :blush: