In How to convert an array of array into a matrix? we learned how to convert an array of arrays to a matrix. But what about the other way around? How do we go from input to output, as shown below?
input = [1 2 3; 4 5 6; 7 8 9]
output = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
If you want to make a copy of the data then:
[input[i, :] for i in 1:size(input, 1)]
If you do not want to make a copy of the data you can use views:
[view(input, i, :) for i in 1:size(input, 1)]
After some thought those are alternatives using broadcasting:
getindex.([input], 1:size(input, 1), :)
view.([input], 1:size(input, 1), :)
I add one alternative too:
mapslices(x->[x], input,2)
Edit:
Warning! Now I see that mapslices return 3x1 matrix! (you could change it: mapslices(x->[x], input,2)[:,1])
I am unsatisfied. I don't like any solution we find yet. They are too complicated (think for example how to explain it to children!).
It is also difficult to find function like mapslices in doc too. BTW there is non-exported Base.vect function which could be used instead of anonymous x->[x].
I was thinking that sometimes is more clever to use bigger hammer. So I tried to find something with DataFrames
julia> using DataFrames
julia> DataFrame(transpose(input)).columns
3-element Array{Any,1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
unfortunately there is not DataFrame.rows
result's type is Array{Any,1}
I don't think it could be very quick
I hope Julia could get us better solution! :)
Related
I am new to Julia and I am trying to migrate from existing code in Mathematica. I am trying to do: with an array of vectors, subtract a constant vector from it. Here is what I want:
a=[[1, 2], [1, 3]]
println(a)
b=a.-[1,1]
println(b)
I want b=[[0,1],[0,2]] but it gives me error about dimension mismatch. I am a bit at a loss regarding the difference between "a list of vectors" and "a matrix" in Julia. I am not sure what is the right way to do these two different things.
I then tried broadcasting but it did not work either
a=([1, 2], [1, 3])
println(a)
b=broadcast(-,[1,1],a)
println(b)
Finally, I tried
a=([1, 2], [1, 3])
println(a)
b=a.-([1,1],)
println(b)
and it worked.
My questions:
Why don't the first two work?
Is this a hack walkaround or should I be using this in the future?
You need to use Ref to avoid vectorization on the second argument of your difference:
julia> a .- Ref([1,1])
2-element Vector{Vector{Int64}}:
[0, 1]
[0, 2]
Without that you were iterating over elements of a as well as elements of [1, 1] which ended in calculating an unvectorized difference between a vector and a scalar so it did not work.
An alternative way:
julia> broadcast(.-, a, [1, 1])
2-element Vector{Vector{Int64}}:
[0, 1]
[0, 2]
In more recent Julia versions, "dotted operators" can be used as stand-alone values of a wrapper type:
julia> .-
Base.Broadcast.BroadcastFunction(-)
which you can then broadcast.
I have come accross a line code that actually works for the work I am doing but I do not understand it. I would like someone to please explain what it means.
b=(3,1,2,1)
a=2
q=np.zeros(b+(a,))
I would like to know why length of q is always the first entry of b.
for example len(q)=3
if b=(1,2,4,3) then len(q)=1
This is really confusing as I thought that the function 'len' returns the number of columns of a given array. Also, how do I get the number of rows of q. So far the only specifications I have found are len(q), q.size( which gives the total number of elements in q) and q.shape(which also I do not quite get the output, because in the latter case, q.shape=(b,a)=(1,2,4,3,2).
Is there function that could return the size of the array in terms of the numberof columns and rows? for example 24x2?
Thank you in advance.
In Python a array does only have one dimension, that's why len(array) returns a single number.
Assuming that you have a 'matrix' in form of array of arrays, like this:
1 2 3
4 5 6
7 8 9
declared like
mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
you can determine the 'number of columns and rows' by the following commands:
rows = len(mat)
columns = len(mat[0])
Note that it only works if number of elements in each row is constant
If you are using numpy to make the arrays, another way to get the column rows and columns is using the tuple from the np.shape() function. Here is a complete example:
import numpy as np
mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
rownum = np.shape(mat)[0]
colnum = np.shape(mat)[1]
In Julia vec reshapes multidimensional arrays into one-dimension arrays.
However it doesn't work for arrays of arrays or arrays of tuples.
A part from using array comprehension, is there another way to flatten arrays of arrays/tuples? Or arrays of arrays/tuples of arrays/tuples? Or ...
Iterators.flatten(x) creates a generator that iterates over each element of x. It can handle some of the cases you describe, eg
julia> collect(Iterators.flatten([(1,2,3),[4,5],6]))
6-element Array{Any,1}:
1
2
3
4
5
6
If you have arrays of arrays of arrays and tuples, you should probably reconsider your data structure because it doesn't sound type stable. However, you can use multiple calls to flatten, eg
julia> collect(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6]))
6-element Array{Any,1}:
1
2
[3, 3, 3, 3]
4
5
6
julia> collect(Iterators.flatten(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6])))
9-element Array{Any,1}:
1
2
3
3
3
3
4
5
6
Note how all of my example return an Array{Any,1}. That is a bad sign for performance, because it means the compiler could not determine a single concrete type for the elements of the output array. I chose these example because the way I read your question it sounded like you may have type unstable containers already.
In order to flatten an array of arrays, you can simply use vcat() like this:
julia> A = [[1,2,3],[4,5], [6,7]]
Vector{Int64}[3]
Int64[3]
Int64[2]
Int64[2]
julia> flat = vcat(A...)
Int64[7]
1
2
3
4
5
6
7
The simplest way is to apply the ellipsis ... twice.
A = [[1,2,3],[4,5], [6,7]]
flat = [(A...)...]
println(flat)
The output would be
[1, 2, 3, 4, 5, 6, 7].
If you use VectorOfArray from RecursiveArrayTools.jl, it uses the indexing fallback to provide convert(Array,A) for a VectorOfArray A.
julia> using RecursiveArrayTools
julia> A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
julia> VA = VectorOfArray(A)
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
First of it acts as a lazy wrapper for doing the indexing without conversion:
julia> VA[1,3]
7
Note that columns are the separate arrays so that way it's still "column-major" (i.e. efficient to index down columns). But then it has a straight conversion:
julia> convert(Array,VA)
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
The other way to handle this conversion is to do something like hcat(A...), but that's slow if you have a lot of arrays you're splatting!
Now, you may think: what about writing a function that pre-allocates the matrix, then loops through and fills it? That's almost what convert on the VectorOfArray works, except the fallback that convert uses here utilizes Tim Holy's Cartesian machinery. At one point, I wrote that function:
function vecvec_to_mat(vecvec)
mat = Matrix{eltype(eltype(vecvec))}(length(vecvec),length(vecvec[1]))
for i in 1:length(vecvec)
mat[i,:] .= vecvec[i]
end
mat
end
but I have since gotten rid of it because the fallback was much faster. So, YMMV but that's a few ways to solve your problem.
for Julia 0.7x:
for Arrays:
flat(arr::Array) = mapreduce(x -> isa(x, Array) ? flat(x) : x,
append!, arr,init=[])
for Tuples:
flat(arr::Tuple) = mapreduce(x -> isa(x, Tuple) ? flat(x) : x,
append!, arr,init=[])
Works for arbitrary depth.
see: https://rosettacode.org/wiki/Flatten_a_list#Julia
Code for Array/Tuple:
function flatten(arr)
rst = Any[]
grep(v) = for x in v
if isa(x, Tuple) || isa(x, Array)
grep(x)
else push!(rst, x) end
end
grep(arr)
rst
end
I'm new to Crystal and I find it fun to learn and work with.
What's a simple and quick way to sort an array?
Without knowing what your Array actually contains i assume it's an Array(Int32) (array of integers).
You can easily sort an array of integers like
[4, 7, 2].sort { |x, y| y <=> x } # => [7, 4, 2]
Check the array spec in Crystal core for more info https://github.com/crystal-lang/crystal/blob/bf6b743aa7649ed3ecc92dd06fde21f88460720a/spec/std/array_spec.cr#L998-L1047
you can use sort like in Ruby
puts [7,3,2,8].sort #=> [2, 3, 7, 8]
In ruby you can use percent notation to easily make an array of strings:
[14] pry(main)> %w(some cats ran far)
=> ["some", "cats", "ran", "far"]
Using a method found in another post I was able to make an array of strings using percent notation and then converting them into Fixnums later:
[15] pry(main)> %w(1 2 3).map(&:to_i)
=> [1, 2, 3]
But I'd really like to be able to do something like
%i(1 2 3) #=> [1 2 3]
Is this possible? Thanks :)
As cremno said, no that is not possible.
If you want strictly a range of integers, such as 1 through 10, the best method will be
(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
But if you want to specify exact integers I would do this
%w(1 5 10).map{|i| i.to_i}
# => [1, 5, 10]
But at that point I don't know why you wouldn't just do this directly...
[1, 5, 10]
Well, you can do something like this.
%i(1 2 3).map(&:to_s).map { |i| Integer(i) } #=> [1, 2, 3]
Using a range seems like it might be the easiest:
[26] pry(main)> (1..3).to_a
=> [1, 2, 3]