Given a matrix A of dimensions m,n, how would one normalize the columns of that matrix by some function or other process in Julia (the goal would be to normalize the columns of A so that our new matrix has columns of length 1)?
Given a matrix A of dimensions m,n, how would one normalize the columns of that matrix by some function or other process in Julia (the goal would be to normalize the columns of A so that our new matrix has columns of length 1)?
If you want a new matrix then mapslices is probably what you want:
julia> using LinearAlgebra
julia> x = rand(5, 3)
5×3 Matrix{Float64}:
0.185911 0.368737 0.533008
0.957431 0.748933 0.479297
0.567692 0.477587 0.345943
0.743359 0.552979 0.252407
0.944899 0.185316 0.375296
julia> y = mapslices(x -> x / norm(x), x, dims=1)
5×3 Matrix{Float64}:
0.112747 0.327836 0.582234
0.580642 0.66586 0.523562
0.344282 0.424613 0.377893
0.450816 0.491642 0.275718
0.573042 0.164761 0.409956
julia> map(norm, eachcol(y))
3-element Vector{Float64}:
1.0
1.0
1.0
If by length 1 you mean like with norm 1 maybe this could work
using LinearAlgebra
# if this is your matrix
m = rand(10, 10)
# norm comes from LinearAlgebra
# or you can define it as
# norm(x) = sqrt(sum(i^2 for i in x))
g(x) = x ./ norm(x)
# this has columns that have approximately norm 1
normed_m = reduce(hcat, g.(eachcol(m)))
Though there are likely better solutions I don't know!
mapslices seems to have some issues with performance. On my computer (and v1.7.2) this is 20x faster:
x ./ norm.(eachcol(x))'
This is an in-place version (because eachcol creates views), which is faster still (but still allocates a bit):
normalize!.(eachcol(x))
And, finally, some loop versions that are 40-70x faster than mapslices for the 5x3 matrix:
# works in-place:
function normcol!(x)
for col in eachcol(x)
col ./= norm(col)
end
return x
end
# creates new array:
normcol(x) = normcol!(copy(x))
Edit: Added a one-liner with zero allocations:
foreach(normalize!, eachcol(x))
The reason this does not allocate anything, unlike normalize!., is that foreach doesn't return anything, which makes it useful in cases where output is not needed.