I have
type MyArray{T,N} <: AbstractArray{T,N}
x::Array{T,N}
y::Int
end
It prints like an array. However, I would like its show/print/display/Juno render to act like it's just any ol' type. Is there a good way to remove the overrides without dropping the AbstractArray subtyping?
Here's a way to restore the standard Base.show behavior for a type, using invoke:
julia> type MyArray{T,N} <: AbstractArray{T,N}
x::Array{T,N}
y::Int
end
julia> Base.show(io::IO, A::MyArray) =
invoke(show, Tuple{typeof(io), Any}, io, A)
julia> Base.show(io::IO, ::MIME"text/plain", A::MyArray) = show(io, A)
julia> MyArray([1, 2, 3], 4)
MyArray{Int64,1}([1, 2, 3], 4)
I don't know if this handles the Juno part; apparently Juno uses its own infrastructure.
Not sure how one might generically 'restore' the default show function, but this is easy enough to emulate:
julia> type MyArray{T,N} <: AbstractArray{T,N}
x::Array{T,N}
y::Int
end
julia> Base.show(io::IO, a::MyArray) = print(io, "$(typeof(a))($(a.x), $(a.y))");
julia> Base.show(io::IO, ::MIME"text/plain", a::MyArray) = show(io, a);
julia> a = MyArray([1., 2., 3., 4., 5.], 5)
MyArray{Float64,1}([1.0, 2.0, 3.0, 4.0, 5.0], 5)
As an aside, personally I find dump to work a lot better as a multi-line 'display' function than the default one for such an array-containing type:
julia> Base.show(io::IO, ::MIME"text/plain", a::MyArray) = dump(a);
julia> a
MyArray{Float64,1}
x: Array{Float64}((5,)) [1.0, 2.0, 3.0, 4.0, 5.0]
y: Int64 5
Related
I want to move an array from my laptop (Julia 1.3.1) to my desktop PC (Julia 1.6.2).
I make an array in Julia 1.3.1 as follows.
using LinearAlgebra
H = ... #give a matrix H
eigen,vector = eigen(H)
Then, I'd like to move "vector" to Julia 1.6.2.
How do you do that?
The simplest way is by using DelimitedFiles:
julia> v = [1.0,2.0,3.0]
julia> using DelimitedFiles
julia> writedlm("f.txt", v)
julia> readdlm("f.txt")
3×1 Matrix{Float64}:
1.0
2.0
3.0
julia> vec(readdlm("f.txt"))
3-element Vector{Float64}:
1.0
2.0
3.0
Note that DelmitedFiles works with matrices so the last example shows what to do if you rather store a vector.
Edit following Bogumil's comment
When you have a Matrix of Complex numbers you need to provide the output type for readdlm:
julia> v = Complex.(rand(2,3), rand(2,3))
2×3 Matrix{ComplexF64}:
0.282157+0.540556im 0.757765+0.103518im 0.979935+0.212347im
0.557499+0.934859im 0.604032+0.338489im 0.431962+0.945946im
julia> writedlm("f.txt", v)
julia> readdlm("f.txt",'\t',Complex{Float64})
2×3 Matrix{ComplexF64}:
0.282157+0.540556im 0.757765+0.103518im 0.979935+0.212347im
0.557499+0.934859im 0.604032+0.338489im 0.431962+0.945946im
julia> readdlm("f.txt",'\t',Complex{Float64}) == v
true
Another way is to use a binary format. For long term in-between version serialization BSON (binary json) could be a good option:
julia> using BSON
julia> BSON.bson("v.bson", v = v)
julia> v2 = BSON.load("v.bson")[:v]
2×3 Matrix{ComplexF64}:
0.282157+0.540556im 0.757765+0.103518im 0.979935+0.212347im
0.557499+0.934859im 0.604032+0.338489im 0.431962+0.945946im
I have a pair of matrices, say Ws, Xs, of equal dimension and a function myFunc(w, x) which takes two vectors as input. I want to apply this function to pairs of columns (think of it as zip-ing the columns) and mapping this function to them.
Is there a non-iterative way to do this? If there were only two columns in each of Ws, Xs, I can do
allCols = permutedims(reshape(hcat(Ws, Xs), d, 2), [1, 3, 2])
mapslices(x -> myFunc(x[:, 1], x[:, 2]), allCols, dims=[1, 2])
but I'm having trouble moving to an arbitrary number of columns.
Edit: using vcat and the correct dimensions seems to fix this:
# assume d is column size
wxArray = reshape(vcat(Ws, Xs), 2, d) # group pairs of columns together
mapslices(x -> myFunc(x[:, 1], x[:, 2]), wxArray, dims=[1,2])
You can use eachcol function like this (I give three ways just to show different possible approaches but eachcol is crucial in all of them):
julia> Ws = rand(2,3)
2×3 Array{Float64,2}:
0.164036 0.233236 0.937968
0.724233 0.102248 0.55047
julia> Xs = rand(2,3)
2×3 Array{Float64,2}:
0.0493071 0.735849 0.643352
0.909295 0.276808 0.396145
julia> using LinearAlgebra
julia> dot.(eachcol(Ws), eachcol(Xs))
3-element Array{Float64,1}:
0.6666296397421881
0.19992972241709792
0.8215096642236619
julia> dot.(eachcol.((Ws, Xs))...)
3-element Array{Float64,1}:
0.6666296397421881
0.19992972241709792
0.8215096642236619
julia> map(dot, eachcol(Ws), eachcol(Xs))
3-element Array{Float64,1}:
0.6666296397421881
0.19992972241709792
0.8215096642236619
This requires Julia 1.1.
EDIT
If you are on Julia 1.0 and do want to avoid iteration while not mind some extra allocations (the solution above avoids allocations) you can also use cat function (which is a bit simpler than your approach I think):
julia> Ws = rand(2,3)
2×3 Array{Float64,2}:
0.975749 0.660932 0.391192
0.619872 0.278402 0.799096
julia> Xs = rand(2,3)
2×3 Array{Float64,2}:
0.0326003 0.272455 0.713046
0.389058 0.886105 0.950822
julia> mapslices(x -> (x[:,1], x[:,2]), cat(Ws, Xs; dims=3), dims=[1,3])[1,:,1]
3-element Array{Tuple{Array{Float64,1},Array{Float64,1}},1}:
([0.975749, 0.619872], [0.0326003, 0.389058])
([0.660932, 0.278402], [0.272455, 0.886105])
([0.391192, 0.799096], [0.713046, 0.950822])
of course you can also simply do this:
julia> map(i -> (Ws[:,i], Xs[:,i]), axes(Ws, 2))
3-element Array{Tuple{Array{Float64,1},Array{Float64,1}},1}:
([0.975749, 0.619872], [0.0326003, 0.389058])
([0.660932, 0.278402], [0.272455, 0.886105])
([0.391192, 0.799096], [0.713046, 0.950822])
or more fancy:
julia> (i -> (Ws[:,i], Xs[:,i])).(axes(Ws, 2))
3-element Array{Tuple{Array{Float64,1},Array{Float64,1}},1}:
([0.975749, 0.619872], [0.0326003, 0.389058])
([0.660932, 0.278402], [0.272455, 0.886105])
([0.391192, 0.799096], [0.713046, 0.950822])
I have an array that can take Float64 and Missing values:
local x::Array{Union{Float64, Missing}, 1} = [1.0, missing, 3.0]
I can add more Float64 values using the append! function, but I can't add a missing value this way. I get the following error:
julia> append!(x, missing)
ERROR: MethodError: no method matching length(::Missing)
What's the correct way to add missing values to this array?
Yes you are right that push! should be used.
Additionally your code does not need to be so verbose:
julia> x = [1.0, missing, 3.0]
3-element Array{Union{Missing, Float64},1}:
1.0
missing
3.0
julia> y = Union{Missing, Float64}[]
0-element Array{Union{Missing, Float64},1}
julia> push!(y,1);
julia> push!(y,missing)
2-element Array{Union{Missing, Float64},1}:
1.0
missing
Moreover, instead of Array{Union{Float64, Missing}, 1} the shorter and more readable version Vector{Union{Float64, Missing}} can be used.
I should have been using push! - append! is for adding collections, while push! is for single values.
I am using Julia from time to time, however I am surprised by the following behavior:
Let's define an 3x4 array
julia> m=rand(3,4)
3×4 Array{Float64,2}:
0.889018 0.500847 0.539856 0.828231
0.492425 0.582958 0.521406 0.754102
0.28227 0.834333 0.669967 0.0939701
Now I check that
julia> size(m,1), size(m,2)
(3, 4)
as expected.
However, I am surprised by this:
julia> size(m,3), size(m,2018)
(1, 1)
-> I would have expected (0,0) or an error message
Looking the Julia code confirms this behavior:
size(t::AbstractArray{T,N}, d) where {T,N} = d <= N ? size(t)[d] : 1
Moreover:
julia> m[2,1,1,1,1]
0.4924252391289974
-> I would have expected an out of bounds error
So my question is: "what is the rationale?"
( I do not thing it is a bug, I use Julia version 0.6.2)
I believe it's for broadcasting.
julia> m=rand(3,4)
3×4 Array{Float64,2}:
0.139323 0.663912 0.994985 0.517332
0.423913 0.121753 0.0327054 0.0754665
0.392672 0.47006 0.351121 0.787318
julia> size(m)
(3, 4)
julia> n = rand(3)
3-element Array{Float64,1}:
0.716752
0.98755
0.661226
julia> m .* n
3×4 Array{Float64,2}:
0.09986 0.475861 0.713157 0.370799
0.418636 0.120237 0.0322983 0.074527
0.259645 0.310816 0.23217 0.520595
Notice that n is of one dimension less, so it's size 1 in the 2nd dimension and thus applies column-wise. Scalars in broadcast are treated differently and are generally inlined into the fused broadcasting function which you cannot do with a mutable type, so the size 1 = expand in higher dimensions rule for broadcast is a nice way to implement this.
I'm porting some code from Julia 0.4.7 to 0.5.1. I've noticed that there is something not compatible related to the array of anonymous functions. The code is here:
f = x::Array{Function} -> size(x)
# Option 1
f([k -> k+1, k-> k+1]) # This works in 0.4 & 0.5
# Option 2
f(repmat([k -> k+1], 2)) # This only works in 0.4
As far as I can see, the difference is although in 0.4 the anonymous array is still internally seen as Array{Function, 1}, in 0.5 it's seen like Array{#11#12, 1} (the numbers may change), so then it raises a MethodError thus they don't match.
Although the example is stupid it shows what I really need: to replicate an anonymous function a variable number of times.
Thanks!
In Julia 0.5+, Function becomes an abstract type, so Array{Function} is a parametric type which is invariant.
julia> typeof(x -> 2x)
##1#2
julia> typeof(x -> 2x) <: Function
true
julia> typeof([x -> 2x]) <: Array{Function}
false
As a result, the correct way to define f is:
f{T<:Function}(x::Array{T}) = size(x)
julia> f(repmat([k -> k+1], 2))
(2,)