How to get minimal value of Array in Julia? - julia

How do I get the minimum value of an Array, Vector, or Matrix in Julia?
The code min([1, 2, 3]) doesn't work.

The Julia manual:
https://docs.julialang.org/en/v1/base/math/#Base.min
https://docs.julialang.org/en/v1/base/collections/#Base.minimum
min(x, y, ...)
Return the minimum of the arguments. Operates elementwise over arrays.
julia> min([1, 2, 3]...)
1
julia> min(2,3)
2
minimum(A, dims)
Compute the minimum value of an array over the given dimensions.
minimum!(r, A)
Compute the minimum value of A over the singleton dimensions of r, and write results to r.
julia> minimum([1, 2, 3])
1

Related

Unique elements of an array of arrays with "issetequal"

For an array like
v=[[1,2],[1,2,3],[2,3,1]]
I am looking for a method to delete all entries that are duplicated in the sense that they are equal when considered as sets.
In this example, issetequal([1,2,3],[2,3,1]) = true, so the method should return the array [[1,2],[1,2,3]].
In principle, something like unique(issetequal, v) would solve the problem. But in practice, this option gives the error
ERROR: MethodError: no method matching issetequal(::Array{Int64,1})
Does anybody have a sugestion?
From the documentation, we see that this form of unique takes as first argument a unary function:
unique(f, itr)
Returns an array containing one value from itr for each unique value produced by f applied to elements of itr.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> unique(x -> x^2, [1, -1, 3, -3, 4])
3-element Array{Int64,1}:
1
3
4
In your example, issetequal is a binary function that directly checks the set-equality of two values. What you want instead is the Set constructor, which constructs a Set out of an Array. You can then let unique test the equality between sets:
julia> unique(Set, [[1,2],[1,2,3],[2,3,1]])
2-element Array{Array{Int64,1},1}:
[1, 2]
[1, 2, 3]

Why doesn't julia broadcasting work when deals with more than one array?

I have defined two structs and a function like this
struct A
x::Float64
end
struct B
y::Float64
end
f(a::A, b::B) = a.x*sin(b.y)
f.([A(0.1), A(0.2)], [B(1.), B(2.), B(3.)])
But f returns this error:
DimensionMismatch("arrays could not be broadcast to a common size")
How can I solve this error? I expect an array with 6 elements as the function output.
The problem is that your first argument is a 2-element Vector, and a second argument is 3-element Vector.
If you e.g. make the first argument a 1x2 Matrix, then all works fine:
julia> f.([A(0.1) A(0.2)], [B(1.), B(2.), B(3.)])
3×2 Array{Float64,2}:
0.0841471 0.168294
0.0909297 0.181859
0.014112 0.028224
(note that the missing or 1-length dimensions get automatically broadcasted)
Note that you could also broadcast calls to A and B constructors:
f.(A.([0.1 0.2]), B.(1.:3.))
The arrays have to have compatible dimensions - either identical in size and shape (local operations), or they span a larger vector space where each has singleton dimensions where the others have non-singleton dimensions, e.g. as an operation on the dimensions, the .* operator will cause the mapping
(1 x 1 x n) .* (p x q x 1) => p x q x n

What is Julia's equivalent of R's which?

In Rb given a vector x one can find the indices where its elements are TRUE using the which function. E.g. y = 1:100 and which(is.even(y)) should return 2,4,...,100
There are also which.max and which.min which returns the indices of minimum and maximum values respectiely.
What are their equivalents in Julia?
The find function does that.
In R:
y = c(1,2,3,4)
which(y > 2)
In Julia:
y = [1, 2, 3, 4]
find(y .> 2)
There is no exact equivalent but findall
There is a comparison list of vocabularies for Julia vs R; which is on the list
http://www.johnmyleswhite.com/notebook/2012/04/09/comparing-julia-and-rs-vocabularies/
However, according to the list Julia's find is equivalent to R's which as answered by others.
The equivalent of R's which is Julia's findall:
y = [1, 2, 3, 4]
findall(y .> 2)

Initialize an array of arrays in Julia

I'm trying to create an array of two arrays. However, a = [[1, 2], [3, 4]] doesn't do that, it actually concats the arrays. This is true in Julia: [[1, 2], [3, 4]] == [1, 2, 3, 4]. Any idea?
As a temporary workaround, I use push!(push!(Array{Int, 1}[], a), b).
If you want an array of arrays as opposed to a matrix (i.e. 2-dimensional Array):
a = Array[ [1,2], [3,4] ]
You can parameterize (specify the type of the elements) an Array literal by putting the type in front of the []. So here we are parameterizing the Array literal with the Array type. This changes the interpretation of brackets inside the literal declaration.
Sean Mackesey's answer will give you something of type Array{Array{T,N},1} (or Array{Array{Int64,N},1}, if you put the type in front of []). If you instead want something more strongly typed, for example a vector of vectors of Int (i.e. Array{Array{Int64,1},1}), use the following:
a = Vector{Int}[ [1,2], [3,4] ]
In Julia v0.5, the original syntax now produces the desired result:
julia> a = [[1, 2], [3, 4]]
2-element Array{Array{Int64,1},1}:
[1,2]
[3,4]
julia> VERSION
v"0.5.0"
For a general answer on constructing Arrays of type Array:
In Julia, you can have an Array that holds other Array type objects. Consider the following examples of initializing various types of Arrays:
A = Array{Float64}(10,10) # A single Array, dimensions 10 by 10, of Float64 type objects
B = Array{Array}(10,10,10) # A 10 by 10 by 10 Array. Each element is an Array of unspecified type and dimension.
C = Array{Array{Float64}}(10) ## A length 10, one-dimensional Array. Each element is an Array of Float64 type objects but unspecified dimensions
D = Array{Array{Float64, 2}}(10) ## A length 10, one-dimensional Array. Each element of is an 2 dimensional array of Float 64 objects
Consider for instance, the differences between C and D here:
julia> C[1] = rand(3)
3-element Array{Float64,1}:
0.604771
0.985604
0.166444
julia> D[1] = rand(3)
ERROR: MethodError:
rand(3) produces an object of type Array{Float64,1}. Since the only specification for the elements of C are that they be Arrays with elements of type Float64, this fits within the definition of C. But, for D we specified that the elements must be 2 dimensional Arrays. Thus, since rand(3) does not produce a 2 dimensional array, we cannot use it to assign a value to a specific element of D
Specify Specific Dimensions of Arrays within an Array
Although we can specify that an Array will hold elements which are of type Array, and we can specify that, e.g. those elements should be 2-dimensional Arrays, we cannot directly specify the dimenions of those elements. E.g. we can't directly specify that we want an Array holding 10 Arrays, each of which being 5,5. We can see this from the syntax for the Array() function used to construct an Array:
Array{T}(dims)
constructs an uninitialized dense array with element type T. dims may be a tuple or a series of integer arguments. The syntax Array(T, dims) is also available, but deprecated.
The type of an Array in Julia encompasses the number of the dimensions but not the size of those dimensions. Thus, there is no place in this syntax to specify the precise dimensions. Nevertheless, a similar effect could be achieved using an Array comprehension:
E = [Array{Float64}(5,5) for idx in 1:10]
For those wondering, in v0.7 this is rather similar:
Array{Array{Float64,1},2}(undef, 10,10) #creates a two-dimensional array, ten rows and ten columns where each element is an array of type Float64
Array{Array{Float64, 2},1}(undef,10) #creates a one-dimensional array of length ten, where each element is a two-dimensional array of type Float64
You probably want a matrix:
julia> a = [1 2; 3 4]
2x2 Int64 Array:
1 2
3 4
Maybe a tuple:
julia> a = ([1,2],[3,4,5])
([1,2],[3,4,5])
You can also do {[1,2], [3,4]} which creates an Array{Any,1} containing [1,2] and [3,4] instead of an Array{Array{T,N},1}.

How do functions that simultaneously operate over vectors and their elements work in R?

Take the following example:
boltzmann <- function(x, t=0.1) { exp(x/t) / sum(exp(x/t)) }
z=rnorm(10,mean=1,sd=0.5)
exp(z[1]/t)/sum(exp(z/t))
[1] 0.0006599707
boltzmann(z)[1]
[1] 0.0006599707
It appears that exp in the boltzmann function operates over elements and vectors and knows when to do the right thing. Is the sum "unrolling" the input vector and applying the expression on the values? Can someone explain how this works in R?
Edit: Thank you for all of the comments, clarification, and patience with an R n00b. In summary, the reason this works was not immediately obvious to me coming from other languages. Take python for example. You would first compute the sum and then compute the value for each element in the vector.
denom = sum([exp(v / t) for v in x])
vals = [exp(v / t) / denom for v in x]
Whereas is R the sum(exp(x/t)) can be computed inline.
This is explained in An Introduction to R, Section 2.2: Vector arithmetic.
Vectors can be used in arithmetic expressions, in which case the
operations are performed element by element. Vectors occurring in the
same expression need not all be of the same length. If they are not,
the value of the expression is a vector with the same length as the
longest vector which occurs in the expression. Shorter vectors in the
expression are recycled as often as need be (perhaps fractionally)
until they match the length of the longest vector. In particular a
constant is simply repeated. So with the above assignments the command
x <- c(10.4, 5.6, 3.1, 6.4, 21.7)
y <- c(x, 0, x)
v <- 2*x + y + 1
generates a new vector v of length 11 constructed by adding together,
element by element, 2*x repeated 2.2 times, y repeated just once, and
1 repeated 11 times.
This might be clearer if you evaluated the numerator and the denominator separately:
x = rnorm(10,mean=1,sd=0.5)
t = .1
exp(x/t)
# [1] 1.845179e+05 6.679273e+03 4.379369e+06 1.852623e+06 9.960374e+02
# [6] 1.359676e+09 6.154045e+03 1.777027e+01 1.070003e+04 6.217397e+04
sum(exp(x/t))
# [1] 2984044296
Since the numerator is a vector of length 10, and the denominator is a vector of length 1, the division returns a vector of length 10.
Since you're interested in comparing this to Python, imagine the two following rules were added to Python (incidentally, these are similar to the usage of arrays in numpy):
If you divide a list by a number, it will divide all items in the list by the number:
[2, 4, 6, 8] / 2
# [1, 2, 3, 4]
The function exp in Python is "vectorized", which means that when it is applied to a list it will apply to each item in the list. However, sum still works the way you expect it to.
exp([1, 2, 3]) => [exp(1), exp(2), exp(3)]
In that case, imagine how this code would be evaluated in Python:
t = .1
x = [1, 2, 3, 4]
exp(x/t) / sum(exp(x/t))
It would follow the following simplifications, using those two simple rules:
exp([v / t for v in x]) / sum(exp([v / t for v in x]))
[exp(v / t) for v in x] / sum([exp(v / t) for v in x])
Now do you see how it knows the difference?
Vectorisation has several slightly different meanings in R.
It can mean accepting a vector input, transforming each element, and returning a vector (like exp does).
It can also mean accepting a vector input and calculating some summary statistic, then returning a scalar value (like mean does).
sum conforms to the second behaviour, but also has a third vectorisation behaviour, where it will create a summary statistic across inputs. Try sum(1, 2:3, 4:6), for example.

Resources