I'm trying to use mean(A,1) to get the mean row of a matrix A, but am getting an error.
For example, try running the command mean(eye(3), 1).
This gives the error no method mean(Array{Float64,2},Int32).
The only documentation I can find for the mean function is here:
http://docs.julialang.org/en/release-0.1/stdlib/base/#statistics
mean(v[, region])
Compute the mean of whole array v, or optionally along the dimensions in region.
What is the region parameter?
EDIT: for Julia 0.7 and higher, write this as mean(v, dims=1).
julia> using Statistics
julia> A = [[1 2 3];[ 4 5 6]]
2×3 Array{Int64,2}:
1 2 3
4 5 6
# Column means
julia> mean(A, dims=1)
1×3 Array{Float64,2}:
2.5 3.5 4.5
# Row means
julia> mean(A, dims=2)
2×1 Array{Float64,2}:
2.0
5.0
It must be something with your installation, mean(eye(3),1) works just fine here.
Related
What is the best way in Julia to vectorize a function along a specific axis? For example sum up all the rows of a matrix. Is it possible with the dot notation?
sum.(ones(4,4))
Does not yield the desired result.
Try using the dims argument on a lot of functions that deal with sets of values.
sum([1 2; 3 4], dims=2)
2×1 Matrix{Int64}:
3
7
# or
using Statistics
mean([1 2; 3 4], dims=1)
1×2 Matrix{Float64}:
2.0 3.0
There is already a standard function called mapslices, looks like exactly what you need.
julia> mapslices(sum, ones(4, 4), dims = 2)
4-element Vector{Float64}:
4.0
4.0
4.0
4.0
You can find the documentation here or by typing ? followed by mapslices in REPL.
If in your example you want to use the dot notation you should pass an array of rows, not the array itself. Otherwise, sum is applied to each element resulting in the same matrix. It can be done with eachrow and eachcol for rows and columns respectively.
julia> sum.(eachrow(ones(4, 4)))
4-element Vector{Float64}:
4.0
4.0
4.0
4.0
EDIT: I tried to suggest a more general solution, but if you have this option I would recommend using Andre's answer.
Coming from R I am used to do something like this to get the first element of vector a:
a <- c(1:3, 5)
a[1]
[1] 1
H can I get the 1 in Julia? The first element of a is now a range.
a = [1:3, 5]
a[1]
1-element Array{UnitRange{Int64},1}:
1:3
The core problem here is that c(1:3, 5) in R and [1:3, 5] in Julia do not do the same thing. The R code concatenates a vector with an integer producing a vector of four integers:
> c(1:3, 5)
[1] 1 2 3 5
The Julia code constructs a two-element vector whose elements are the range 1:3 and the integer 5:
julia> [1:3, 5]
2-element Vector{Any}:
1:3
5
julia> map(typeof, ans)
2-element Vector{DataType}:
UnitRange{Int64}
Int64
This vector has element type Any because there's no smaller useful common supertype of a range and an integer. If you want to concatenate 1:3 and 5 together into a vector you can use ; inside of the brackets instead of ,:
julia> a = [1:3; 5]
4-element Vector{Int64}:
1
2
3
5
Once you've defined a correctly, you can get its first element with a[1] just like in R. In general inside of square brackets in Julia:
Comma (,) is only for constructing vectors of the exact elements given, much like in Python, Ruby, Perl or JavaScript.
If you want block concatenation like in R or Matlab, then you need to use semicolons/newlines (; or \n) for vertical concatenation and spaces for horizontal concatenation.
The given example of [1:3; 5] is a very simple instance of block concatenation, but there are significantly more complex ones possible. Here's a fancy example of constructing a block matrix:
julia> using LinearAlgebra
julia> A = rand(2, 3)
2×3 Matrix{Float64}:
0.895017 0.442896 0.0488714
0.750572 0.797464 0.765322
julia> [A' I
0I A]
5×5 Matrix{Float64}:
0.895017 0.750572 1.0 0.0 0.0
0.442896 0.797464 0.0 1.0 0.0
0.0488714 0.765322 0.0 0.0 1.0
0.0 0.0 0.895017 0.442896 0.0488714
0.0 0.0 0.750572 0.797464 0.765322
Apologies for StackOverflow's lousy syntax highlighting here: it seems to get confused by the postfix ', interpreting it as a neverending character literal. To explain this example a bit:
A is a 2×3 random matrix of Float64 elements
A' is the adjoint (conjugate transpose) of A
I is a variable size unit diagonal operator
0I is similar but the diagonal scalar is zero
These are concatenated together to form a single 5×5 matrix of Float64 elements where the upper left and lower right parts are filled from A' and A, respectively, while the lower left is filled with zeros and the upper left is filled with the 3×3 identity matrix (i.e. zeros with diagonal ones).
In this case, your a[1] is a UnitRange collection. If you want to access an individual element of it, you can use collect
For example for the first element,
collect(a[1])[1]
If I define A = [1] I get that A is not equal to A' since they are of different types:
julia> A=[1]
1-element Array{Int64,1}:
1
julia> A'
1×1 LinearAlgebra.Adjoint{Int64,Array{Int64,1}}:
1
julia> A == A'
false
If I define another vector B = [1, 2, 3] and I try to do the products with A'and A I obtain the following output:
B=[1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> B*A'
3×1 Array{Int64,2}:
1
2
3
julia> B*A
ERROR: MethodError: no method matching *(::Array{Int64,1}, ::Array{Int64,1})
...
...
That seems a problem of * operator signature that seems not to accept two Array{Int64,1} as operands while defining another vector C = [4 5] we get:
julia> C=[4 5]
1×2 Array{Int64,2}:
4 5
julia> B*C
3×2 Array{Int64,2}:
4 5
8 10
12 15
So * is defined for operands of types Array{Int64,1} and Array{Int64,2} respectively. Why I cannot multiply a column vector by a singleton vector A but I can using A'?
The answer to this depends on how well you understand linear algebra. Julia follows the conventions of linear algebra for it's array multiplication, if you need to brush up, wikipedia's page is a good source.
It boils down to the fact that your A is a column vector whereas A' is a row vector (like C). Matrix multiplication is defined between (n, k) and (k, m) matrices to produce a (n, m) matrix. Column vectors can sometimes be thought of as (n, 1) matrices, so there's no well defined notion of multiplication between two column vectors.
If you want the dot product, use the dot function (you'll need to do using LinearAlgebra first). If you want an element-wise product, you can use the broadcasting notation, u .* v.
In Julia Vectors are one dimensional Arrays, while the transposition works on two dimensional matrices (Array{T,2} equivalent to Matrix{T})
julia> A=[1]
1-element Array{Int64,1}:
1
julia> collect(A')
1×1 Array{Int64,2}:
1
Since transposition in Julia does not materialize the data and rather holds reference to the original I needed to use collect to actually see what is going on.
When using multiplication on 2-dimensional arrays you are actually using linear algebra operations.
If you want to multiply element-wise use the dot . operator instead:
julia> A .== A'
1×1 BitArray{2}:
1
Note it return an Array rather than a single value.
If you want to multiply element-wise (rather than using linear algebra matrix multiplication) you need to vectorize again:
julia> B.*A
3-element Array{Int64,1}:
1
2
3
When I try and run the inv() function on the example from the Julia documentation (v1.0.3), I get an error. The code is as follows (straight from the docs):
julia> M = [2 5; 1 3]
2×2 Array{Int64,2}:
2 5
1 3
julia> N = inv(M)
ERROR: MethodError: objects of type Array{Float64,2} are not callable
Use square brackets [] for indexing an Array.
It does work with pinv(), but I get some extremely small floating point values. Any ideas why I can't get inv() to work for this extremely simple case?
The error message suggests that you have previously defined a variable called inv which is a floating point matrix, and then try to use this matrix as a function, e.g.
julia> inv = rand(2, 2);
julia> M = [2 5; 1 3];
julia> inv(M)
ERROR: MethodError: objects of type Array{Float64,2} are not callable
Use square brackets [] for indexing an Array.
You can reach the inv function by restarting (and hence clearing the meaning of inv) or using the fully qualified name:
julia> import LinearAlgebra
julia> LinearAlgebra.inv(M)
2×2 Array{Float64,2}:
3.0 -5.0
-1.0 2.0
I have seen online in a few places the solution
a = [1 2 3; 4 5 Inf]
a[isinf(a)] = NaN
But this gives me an error on Julia 1.0.1:
ERROR: MethodError: no method matching isinf(::Array{Float64,2})
Closest candidates are:
isinf(::BigFloat) at mpfr.jl:851
isinf(::Missing) at missing.jl:79
isinf(::ForwardDiff.Dual) at <path on my local machine>
What gives?
As an additional comment. A standard function to perform this action is replace!. You can use it like this:
julia> a = [1 2 3; 4 5 Inf]
2×3 Array{Float64,2}:
1.0 2.0 3.0
4.0 5.0 Inf
julia> replace!(a, Inf=>NaN)
2×3 Array{Float64,2}:
1.0 2.0 3.0
4.0 5.0 NaN
It will perform better than broadcasting for large arrays.
If you really need speed you can write a simple function like this:
function inf2nan(x)
for i in eachindex(x)
#inbounds x[i] = ifelse(isinf(x[i]), NaN, x[i])
end
end
Now let us simply compare the performance of the three options:
julia> function bench()
x = fill(Inf, 10^8)
#time x[isinf.(x)] .= NaN
x = fill(Inf, 10^8)
#time replace!(x, Inf=>NaN)
x = fill(Inf, 10^8)
#time inf2nan(x)
end
bench (generic function with 1 method)
julia> bench()
0.980434 seconds (9 allocations: 774.865 MiB, 0.16% gc time)
0.183578 seconds
0.109929 seconds
julia> bench()
0.971408 seconds (9 allocations: 774.865 MiB, 0.03% gc time)
0.184163 seconds
0.102161 seconds
EDIT: For the most performant approaches to this problem see the excellent answer of #BogumilKaminski. This answer addresses the more general question of why isinf and related functions do not work on arrays anymore.
You are running into the more general issue that lots of functions that worked on arrays pre-v1.0 no longer work on arrays in v1.0 because you are supposed to be using broadcasting. The correct solution for v1.0 is:
a[isinf.(a)] .= NaN
I'm actually broadcasting in two places here. Firstly, we broadcast isinf over the array a, but we are also broadcasting the scalar NaN on the RHS to all indexed locations in the array on the LHS via .=. In general, the dot broadcasting notation is incredibly flexible and performant, and one of my favorite features of the latest iteration of Julia.
You are passing your entire array to isinf, it doesn't work on arrays, it works on numbers. Try this:
[isinf(i) ? NaN : i for i in a]