Simple way to replace nth element in a vector in clojure? - vector

E.g., I have a vector [1, 2, 3], and I want to update the second element so that the vector becomes [1, 5, 3]. In other languages, I would just do something like array[1] = 5, but I'm not aware of anything that would allow me to do this easily in Clojure.
Thoughts on how to accomplish this, or on whether I should be using a different data structure?

assoc works fine for that. It takes the index where to put the new value and return the newly created vector:
Clojure> (assoc [1 2 3] 1 5)
[1 5 3]

Yve's answer doesn't show how to update the original vector.
This does, but as a Clojure noob, I'm not sure it's the best way:
main=> (def ar [1 2 3])
#'main/ar
main=> ar
[1 2 3]
main=> (def ar (assoc ar 1 5))
#'main/ar
main=> ar
[1 5 3]

Related

How do you access multi-dimension array by N array of index element-wise?

Suppose we have
A = [1 2; 3 4]
In numpy, the following syntax will produce
A[[1,2],[1,2]] = [1,4]
But, in julia, the following produce a permutation which output
A[[1,2],[1,2]] = [1 2; 3 4]
Is there a concise way to achieve the same thing as numpy without using for loops?
To get what you want I would use CartesianIndex like this:
julia> A[CartesianIndex.([(1,1), (2,2)])]
2-element Vector{Int64}:
1
4
or
julia> A[[CartesianIndex(1,1), CartesianIndex(2,2)]]
2-element Vector{Int64}:
1
4
Like Bogumil said, you probably want to use CartesianIndex. But if you want to get your result from supplying the vectors of indices for each dimensions, as in your Python [1,2],[1,2] example, you need to zip these indices first:
julia> A[CartesianIndex.(zip([1,2], [1,2]))]
2-element Vector{Int64}:
1
4
How does this work? zip traverses both vectors of indices at the same time (like a zipper) and returns an iterator over the tuples of indices:
julia> zip([1,2],[1,2]) # is a lazy iterator
zip([1, 2], [1, 2])
julia> collect(zip([1,2],[1,2])) # collect to show all the tuples
2-element Vector{Tuple{Int64, Int64}}:
(1, 1)
(2, 2)
and then CartesianIndex turns them into cartesian indices, which can then be used to get the corresponding values in A:
julia> CartesianIndex.(zip([1,2],[1,2]))
2-element Vector{CartesianIndex{2}}:
CartesianIndex(1, 1)
CartesianIndex(2, 2)

How to initialise reduce and use accumulator in Julia

It works without initial value:
reduce(+, [2 3 4])
Tried multiple ways to provide initial value - nothing works
reduce(+, [2 3 4], 1)
reduce(+, 1, [2 3 4])
Also seems like reduce could be used only with 2 argument operator. What function should be used to reduce collection with custom functions that accept current value and accumulator? Something like code below?
reduce((accumulator, value) -> push!(accumulator, value^2), [1, 2, 3], [])
# => [1, 4, 9]
This example could be implemented as map(x -> x^2, [1, 2, 3]) but I would like to know how to implement it as reduce with accumulator.
julia version 1.1.1
The init argument to reduce is a keyword argument:
julia> reduce(+, [2 3 4], init = 1)
10
julia> reduce((accumulator, value) -> push!(accumulator, value^2), [1, 2, 3], init = [])
3-element Array{Any,1}:
1
4
9

Equivalent of pandas 'clip' in Julia

In pandas, there is the clip function (see https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.clip.html), which constrains values within the lower and upper bound provided by the user. What is the Julia equivalent? I.e., I would like to have:
> clip.([2 3 5 10],3,5)
> [3 3 5 5]
Obviously, I can write it myself, or use a combination of min and max, but I was surprised to find out there is none. StatsBase provides the trim and winsor functions, but these do not allow fixed values as input, but rather counts or percentiles (https://juliastats.github.io/StatsBase.jl/stable/robust.html).
You are probably looking for clamp:
help?> clamp
clamp(x, lo, hi)
Return x if lo <= x <= hi. If x > hi, return hi. If x < lo, return lo. Arguments are promoted to a common type.
This is a function for scalar x, but we can broadcast it over the vector using dot-notation:
julia> clamp.([2, 3, 5, 10], 3, 5)
4-element Array{Int64,1}:
3
3
5
5
If you don't care about the original array you can also use the in-place version clamp!, which modifies the input:
julia> A = [2, 3, 5, 10];
julia> clamp!(A, 3, 5);
julia> A
4-element Array{Int64,1}:
3
3
5
5

Julia: find maximum along columns in array

Suppose we have an array defined like this:
a=[1 2; 3 4; 5 5; 7 9; 1 2];
In Matlab, we could find the maximum values by writing:
[x y] = max(a)
x =
7 9
In Julia, we could use:
a=[1 2; 3 4; 5 5; 7 9; 1 2]
findmax(a,1)
returning:
([7 9],
[4 9])
However, I am interested not only in finding [7 9] for the two columns, but also their relative position within each column, like [4, 4]. Of course, I can write a bit more of coding lines, but can I do it directly with findmax?
The second matrix returned by findmax is the linear index of the locations of the maxima over the entire array. You want the position within each column; to get that, you can convert the linear indices into subscripts with ind2sub. Then the first element of the subscript tuple is your row index.
julia> vals, inds = findmax(a, 1)
(
[7 9],
[4 9])
julia> map(x->ind2sub(a, x), inds)
1×2 Array{Tuple{Int64,Int64},2}:
(4,1) (4,2)
julia> map(x->ind2sub(a, x)[1], inds)
1×2 Array{Int64,2}:
4 4
This is mentioned in the comments but I figured I'd do a response that's easy to see. I have version 1.0.3, so I don't know what's the earliest version that allows this. But now you can just do
julia> findmax(a) #Returns 2D index of overall maximum value
(9, CartesianIndex(4, 2))
julia> findmax(a[:,1]) #Returns 1D index of max value in column 1
(7, 4)
julia> findmax(a[:,2]) #Returns 1D index of max value in column 2
(9, 4)
Hope this makes things easier.
I've adopted the following function:
indmaxC(x) = cat(1, [indmax(x[:,c]) for c in 1:size(x,2)]...)
The Good: it's convenient and small
The Bad: it's only valid for 2-D arrays
A safer version would be:
function indmaxC(x::AbstractArray)
assert(ndims(x)==2)
cat(1, [indmax(x[:,c]) for c in 1:size(x,2)]...)
end

Is there outer map function in Julia?

I am trying to construct all possible combinations of four vectors (parameters in a model) that would give me a big nx4 matrix and I could then run simulation on each set (row) of parameters. In R I would achieve this by using expand.grid in Mathematica style, I could use something like outer product with vcat and reduce the output using hcat.
Is there some function analog of expand.grid from R or outer map function?
Toy example:
A = [1 2]
B = [3 4]
some magic
output = [1 3, 1 4, 2 3, 2 4]
Using the Iterators package, it might look like this:
using Iterators
for p in product([1,2], [3,4])
println(p)
end
where you would replace println with your algorithm. You can also use collect if it's important to get the set of all combinations.
Not the exact notation you show, but a comprehension might be useful.
julia> a=[1, 2];
julia> b=[3, 4];
julia> [[i, j] for j in b, i in a]
2x2 Array{Any,2}:
[1,3] [2,3]
[1,4] [2,4]
julia> [[i, j] for j in b, i in a][:]
4-element Array{Any,1}:
[1,3]
[1,4]
[2,3]
[2,4]

Resources