I want to create a sparse array where I define a rule to combine duplicates. The documentation says that I can do this with sparse(i,j,v,[m,n,combine]). I've tried in the example below but am unsuccessful. Can you please advise?
i = [1,2,3,3];
j = [1,2,3,2];
v = [10.,11.,12.,13.];
full(sparse([i;j],[j;i],[v;v], [3,3,combine(a,b)=mean([a,b])]))
full(sparse([i;j],[j;i],[v;v], [3,3,mean]))
full(sparse([i;j],[j;i],[v;v], [3,3,-(a,b)]))
full(sparse([i;j],[j;i],[v;v], [3,3,-]))
Square brackets in docstring mean that those are optional arguments. The way to write it is:
julia> full(sparse([i;j],[j;i],[v;v], 3,3,-))
3×3 Array{Int64,2}:
0 0 0
0 0 13
0 13 0
you can omit the last argument, then combine defaults to +:
julia> full(sparse([i;j],[j;i],[v;v], 3,3))
3×3 Array{Int64,2}:
20 0 0
0 22 13
0 13 24
You can check what argument sets the function accepts using methods(sparse). Additionally if you e.g. write #edit sparse([i;j],[j;i],[v;v]) you will go to the source code of sparse and can learn exactly what is accepted.
Related
I want to evaluate a set of vectors (or tuples) in a function $f$ but Julia says me that is imposible.
For example: If I have an array of tuples p=[(1,1), (1,-1), (-1,1), (-1,-1)] and a function f(x,y)=x+y. I would like to calculate f(p[1]) = f(1,1)= 2. But Julia says me that the types are incompatible.
Can you help me please?
You have to splat a tuple like this:
julia> p=[(1,1), (1,-1), (-1,1), (-1,-1)]
4-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(1, -1)
(-1, 1)
(-1, -1)
julia> f(x,y)=x+y
f (generic function with 1 method)
julia> f(p[1]...)
2
you could also define a higher order function splat that would conveniently wrap any function and perform splatting. It is useful as then you can e.g. broadcast such function:
julia> splat(f) = x -> f(x...)
splat (generic function with 1 method)
julia> splat(f)(p[1])
2
julia> splat(f).(p)
4-element Array{Int64,1}:
2
0
0
-2
Alternatively you can define your function f like this:
julia> f((x,y),)=x+y
f (generic function with 1 method)
julia> f(p[1])
2
and now you do not have to do splatting.
Just use the ... operator to unpack the tuple as parameters:
julia> f(p[1]...)
2
In addition to other answers, if your task allows you, you can just define
julia> f(x) = f(x...)
and use it as
julia> f.(p)
4-element Vector{Int64}:
2
0
0
-2
I've taken a project named with "Symbolic Linear Algebra" which is about doing basic operations on infinite matrices like addition, multiplication, accessing specific element etc. I will be implementing those on Julia.
For specifying those infinite matrices we'll have some mathematical cases like:
So the visual representation of matrix will be like:
For example let's say we want to find A + A' for this example. Here our cases change so we need to rewrite those cases to get desired output right ? I know Mathematica does this but how can I implement this? Yes, this was too general so let me ask some questions;
Let's start with taking cases as input. There can be many cases with different rules like if i % 2 == 0 or i == j like in this example how can I provide a generic input ?
Let's say that I'm done with input and I want to make those simple operations. How can I combine those cases in a programming language like Julia ?
I've wrote some non-generic dumb code to see how things will go so I will provide my code to apply minimum reproducible example but don't take it seriously, I think I'm just looking for a clue or a roadmap to get rid of the question marks in my head.
using Parameters
struct inf_matrix
mod_of :: Integer
mod_value :: Integer
i_coefficient :: Integer
j_coefficient :: Integer
value :: Integer
end
function single_demo(_mod_of :: Integer, _mod_value :: Integer, _i_coefficient :: Integer, _j_coefficient :: Integer, _value :: Integer)
test_matrix = inf_matrix(_mod_of, _mod_value, _i_coefficient, _j_coefficient, _value)
return test_matrix
end
function get_elem(st::inf_matrix ,i :: Integer, j :: Integer)
#This function is not completed yet
if (i % st.mod_of == st.mod_value) && (2 * st.i_coefficient == j)
return st.value;
else
return -1
end
end
demo_1 = single_demo(2, 0 ,1, 2, 1)
println(get_elem(demo_1, 1, 0))
Any help would be appreciated.
Here is how you could do this
import Base: getindex, +, *
abstract type InfiniteMatrix end
struct InfiniteIdentity <: InfiniteMatrix end
getindex(::InfiniteIdentity, i, j) = i .== j'
struct InfiniteConstant <: InfiniteMatrix
c
end
getindex(m::InfiniteConstant, i::Integer, j::Integer) = m.c
getindex(m::InfiniteConstant, i, j) = fill(m.c, size(i)..., size(j)...)
struct InfiniteMatrixFilter <: InfiniteMatrix
condition::Function
iftrue::InfiniteMatrix
iffalse::InfiniteMatrix
end
getindex(m::InfiniteMatrixFilter, i, j) = ifelse.(m.condition.(i,j'), m.iftrue[i,j], m.iffalse[i,j])
struct InfiniteMatrixFunction <: InfiniteMatrix
f::Function
args
end
getindex(m::InfiniteMatrixFunction, i, j) = m.f(getindex.(m.args, Ref(i), Ref(j))...)
+(m1::InfiniteMatrix, m2::InfiniteMatrix) = InfiniteMatrixFunction(+, (m1, m2))
*(n::Number, m::InfiniteMatrix) = InfiniteMatrixFunction(x -> n*x, (m,))
julia> i = InfiniteIdentity()
InfiniteIdentity()
julia> c1 = InfiniteConstant(1)
InfiniteConstant(1)
julia> (2i+3c1)[1:5, 1:5]
5×5 Array{Int64,2}:
5 3 3 3 3
3 5 3 3 3
3 3 5 3 3
3 3 3 5 3
3 3 3 3 5
julia> m = InfiniteMatrixFilter((i,j) -> i%2 == 0, c1, 0c1)
InfiniteMatrixFilter(var"#43#44"(), InfiniteConstant(1), InfiniteMatrixFunction(var"#41#42"{Int64}(0), (InfiniteConstant(1),)))
julia> m[1:5, 1:5]
5×5 Array{Int64,2}:
0 0 0 0 0
1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
0 0 0 0 0
(this is only a proof of concept and it's not optimized or bugfree)
I'm fairly new to Julia and as a Matlab/R User I find it, for the most part, really nice to work with.
However, I'm a little confused by the missing values and how to work with them.
Let's say I have a vector:
a=[missing -1 2 3 -12] #Julia
a=[NaN -1 2 3 -12] #Matlab
In Matlab I would just do the following to find the values below 0
a(a<0)
which gives me
-1 -12
The same unfortunately doesn't work in Julia and when I try
a[a.<0]
in Julia I just get the following error
ERROR: ArgumentError: unable to check bounds for indices of type Missing
I also tried the following
a[findall(skipmissing(a).<0)]
which gives me
missing
3
since, of course, I skipped the missing value in the findall-function. I'm pretty sure there is an easy and logical way to do this, but I don't seem to be able to find it.
Can someone please show me the way?
Best,
Richard
Here is the simplest way to do it:
julia> a=[missing -1 2 3 -12]
1×5 Array{Union{Missing, Int64},2}:
missing -1 2 3 -12
julia> a[isless.(a, 0)]
2-element Array{Union{Missing, Int64},1}:
-1
-12
This uses the fact that missing is considered larger than any number by isless.
Another way to write it:
julia> filter(x -> isless(x, 0), a)
2-element Array{Union{Missing, Int64},1}:
-1
-12
Now in order to avoid this special trick with isless you can do the following (using coalesce is a general approach that can be used for safe handling of missing values):
julia> a[coalesce.(a .< 0, false)]
2-element Array{Union{Missing, Int64},1}:
-1
-12
or
julia> filter(x -> coalesce(x < 0, false), a)
2-element Array{Union{Missing, Int64},1}:
-1
-12
finally you can be more explicit like:
julia> filter(x -> !ismissing(x) && x < 0, a)
2-element Array{Union{Missing, Int64},1}:
-1
-12
or
julia> [v for v in a if !ismissing(v) && v < 0]
2-element Array{Int64,1}:
-1
-12
(you could use comprehension syntax also in the examples above)
I have a boolean array (from previous computations) and I would like to select the related rows from several matrices. That is why I need the proper index array (to be reused later). This is easy in Matlab and python but I do not crock the correct julian way of doing it...
I am aware of DataFrames, but would like to find an orthodox matrix and array way of doing this.
In Matlab I would say:
n= 9; temp= 1:n; A= 1.0 + temp;
someTest= mod(temp,2) == 0; % just a substitute of a more complex case
% now I have both someTest and A!
inds= find(someTest); Anew= A(inds,:);
% I got inds (which I need)!
What I have got working is this:
n= 10; data= Array(1:n); A= 1.0 .+ data;
someTest= rem.(data,2) .== 0;
inds= [xy[2] for xy in zip(someTest,1:length(someTest)) if xy[1]]; # (*)
Anew= A[inds,:];
What I assumed is that there is some shorter way to express the above phrase. in v. 0.6 there was find() function, but I have not gotten good sense of the julia documentation yet (I am a very very newbie in this).
You can use the BitArray just directly to select the elements:
julia> A[someTest]
5-element Array{Float64,1}:
3.0
5.0
7.0
9.0
11.0
Fot your case:
julia> A[someTest,:] == A[inds,:]
true
find in 0.6 was renamed to findall in Julia 1.0.
To get inds, you can simply do the following:
inds = findall(someTest)
You do not have to compute the intermediate someTest first, which would allocate an array you do not intend to use. Instead, you can do the test with findall directly passing a predicate function.
inds = findall(x -> rem(x,2) == 0, data)
This will return indices of data for which the predicate rem(x,2) == 0 returns true. This will not allocate an intermediate array to find the indices, and should be faster.
As a side note, most of the time you do not need to materialize a range in Julia. Ranges are already iterable and indexable. They will automatically be converted to an Array when there is a need. Array(1:n) or collect(1:n) are usually redundant, and allocates more memory.
Your Matlab code doesn't work. A is just a row-vector (1x9 matrix), so when you try to do A(inds, :) you get an error:
>> Anew= A(inds,:)
Index in position 1 exceeds array bounds
(must not exceed 1).
But if you just fix that, you can solve the problem in exactly the same way in both Matlab and Julia, using either logical indices or regular ones:
Matlab (I'm making sure it's a matrix this time):
n = 9;
temp = (1:n).';
A = temp * (1:4);
inds = mod(temp,2) == 0;
>> A(inds, :) % using logical indices
ans =
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
>> A(find(inds), :) % using regular indices
ans =
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
And now, Julia:
n = 9;
temp = 1:n;
A = temp .* (1:4)'; # notice that we're transposing the opposite vector from Matlab
inds = mod.(temp, 2) .== 0; # you can use iseven.(temp) instead
julia> A[inds, :] # logical indices (BitArray)
4×4 Array{Int64,2}:
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
julia> A[findall(inds), :] # regular integer indices
4×4 Array{Int64,2}:
2 4 6 8
4 8 12 16
6 12 18 24
8 16 24 32
In this case, I would use the logical indices in both Julia and Matlab. In fact, the Matlab linter (in the editor) will tell that you should use logical indices here because it's faster. In Julia, however, there might be cases where it's more efficient to use inds = findall(iseven, temp), and just skip the logical BitArray, like #hckr says.
Ok lets take this logic here:
dummy = [1 2 3 4 5]
num_test = convert(Array{Int64},3 .== dummy)
I get the result:
0 0 1 0 0
If I try and match two statements:
num_test = convert(Array{Int64},3 .== dummy & 4 .== dummy)
It doesnt evaluate:
0 0 0 0 0
As i am writing this, is this because in the .== vectored call its looking for 3 & 4 on the same index element position?
I can do similar operations in R. But same type of logic not transferring to Julia or am I using incorrect syntax Julia?
Thanks
I'm assuming that the operation you are trying to perform is to evaluate 3 .== dummy and 4 .== dummy, and then compare the two element-wise. Given this, there are two problems here:
1) Order of operations. You need (3 .== dummy) & (4 .== dummy).
2) If you are on a recent v0.6, you should also be seeing a deprecation warning, since from v0.7+, you will need to broadcast the & operator. So use (3 .== dummy) .& (4 .== dummy).
As I understand the question, the conversion to Vector{Int} part is fine, and should work as expected, although you could just write Int.((3 .== dummy) .& (4 .== dummy)).
Given all of the above, you should now see the following outcomes:
julia> Int.((3 .== dummy) .& (4 .== dummy))
1×5 Array{Int64,2}:
0 0 0 0 0
julia> Int.((3 .== dummy) .| (4 .== dummy))
1×5 Array{Int64,2}:
0 0 1 1 0
One final note, I'm assuming you deliberately defined dummy to be a single-row Matrix rather than a Vector. If you wanted your final output to be a Vector, then you would use dummy = [1,2,3,4,5]