# Replacing some elements of an array with corresponding elements from another array

**URL:** <https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248>\
**Category:** General Usage\
**Tags:** question, arrays\
**Created:** [October 23, 2021, 1:43am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248 "2021-10-23T01:43:27Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![leon](https://avatars.discourse-cdn.com/v4/letter/l/dc4da7/32.png) [@leon](https://discourse.julialang.org/u/leon)\
**Post date:** [October 23, 2021, 1:43am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/1 "2021-10-23T01:43:27Z")

</div>

My goal is to replace any elements in array A that are either NaN or \<0 with the corresponding elements in Array B.

Below is my code:

```julia
A = [1, 2.1, -5, 6, -3, 8, NaN];
B = [8, 8.2, 8, 8, 8, 8, 8];
C = replace!(x -> (x<0 || isnan(x)) ? B : x, A)

```

Here is the error:

```julia
MethodError: Cannot `convert` an object of type Vector{Float64} to an object of type Float64
Closest candidates are:
  convert(::Type{T}, ::T) where T<:Number at number.jl:6
  convert(::Type{T}, ::Number) where T<:Number at number.jl:7
  convert(::Type{T}, ::Base.TwicePrecision) where T<:Number at twiceprecision.jl:250
  ...

```

Why isn’t it working? Many thanks!

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [October 23, 2021, 2:45am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/2 "2021-10-23T02:45:38Z")

</div>

Here is one way to do that.

```julia
A = [1, 2.1, -5, 6, -3, 8, NaN];
B = [8, 8.2, 8, 8, 8, 8, 8];

isreplaceable(x) = x < 0 || isnan(x)

function replacewith!(A::AT, B::AT, predicate) where
                      {N, T, AT<:AbstractArray{T,N}}
   here = map(predicate, A) 
   A[here] .= B[here]
   A
end

# and use this way
replacewith!(A,B, isreplaceable);

# A becomes [1.0 , 2.1, 8.0, 6.0, 8.0, 8.0, 8.0]

```

Be that as it may, **use @DataFrames approach** (next).

---

<div class="post-metadata">

**Author:** ![DataFrames](https://avatars.discourse-cdn.com/v4/letter/d/e19b73/32.png) [@DataFrames](https://discourse.julialang.org/u/DataFrames)\
**Post date:** [October 23, 2021, 3:36am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/3 "2021-10-23T03:36:19Z")

</div>

use loop

```julia
isreplaceable(x) = x < 0 || isnan(x)
function replacewith!(A, B, predicate)
        for i in 1:length(A)
             if isreplaceable(A[i])
                 A[i] = B[i]
             end
      end
     A
end

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 23, 2021, 9:07am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/4 "2021-10-23T09:07:55Z")

</div>

> [@leon](#):
>
> Why isn’t it working?

Possibly because `x` iterates over the scalar elements of `A` and that code tries to replace such elements by full `B` arrays.

A comprehension could be used:

```julia
C = [a < 0 || isnan(a) ? b : a for (a,b) in zip(A,B)]

```

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [October 23, 2021, 9:28am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/5 "2021-10-23T09:28:34Z")

</div>

Another option:

```julia
inds = findall(x->x<0 || isnan(x), A)
A[inds] .= B[inds]

```

I wish we could write `findall(<(0) || isnan, A)` 🙂

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 23, 2021, 9:34am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/6 "2021-10-23T09:34:11Z")

</div>

One could even get rid of `findall`:

```julia
inds = (A .< 0) .| isnan.(A)
A[inds] .= B[inds]

```

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [October 23, 2021, 9:36am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/7 "2021-10-23T09:36:13Z")

</div>

I wonder though if it’s maybe less efficient, since it then has to loop over all the false values too, in the assignment?

---

<div class="post-metadata">

**Author:** ![leon](https://avatars.discourse-cdn.com/v4/letter/l/dc4da7/32.png) [@leon](https://discourse.julialang.org/u/leon)\
**Post date:** [October 23, 2021, 10:01am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/8 "2021-10-23T10:01:45Z")

</div>

Many thanks for all the solution. My data has millions of rows and I’m able to test their performance:

This is the fastest way of doing this (106 seconds):

```julia
B= replace!(x -> (x<0 || isnan(x)) ? 0 : x, B);
A = [a < 0 || isnan(a) ? b : a for (a, b) in zip(A, B)];

```

This is the 2nd fastest (196 seconds):

```julia
inds1 = findall(x -> x<0 || isnan(x), B);
B[inds1] .= 0;

inds2 = findall(x -> x<0 || isnan(x), A);
A[inds2,20] .= B[inds2]

```

This is the slowest method (330 seconds):

```julia
B[B.<0 .| isnan.(B)] .= 0;

Ind2 = map(A) do a
    a < 0 || isnan(a);
end
Ind2 = vec(Ind2);
if ~isempty(Ind2)
    A[Ind2] = B[Ind2];
end

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 23, 2021, 10:47am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/9 "2021-10-23T10:47:30Z")

</div>

@leon, it looks like you’ve changed the original problem and now `B` also has negative values and NaNs. This may confuse the logic of the post a bit.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 23, 2021, 11:26am UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/10 "2021-10-23T11:26:10Z")

</div>

The fastest way is quite certainly a loop, as suggested above. Maybe something like this is close to optimal:

```julia
julia> function replacewith!(A, B, isrepleceable)
           for i in eachindex(A)
               @inbounds A[i] = ifelse(isrepleceable(A[i]), B[i], A[i])
           end
           return A
       end
replacewith! (generic function with 1 method)

julia> @btime replacewith!(A,B,x -> x < 0 || isnan(x)) setup=(A = [1, 2.1, -5, 6, -3, 8, NaN]; B = [8, 8.2, 8, 8, 8, 8, 8]);
  7.139 ns (0 allocations: 0 bytes)

```

To compare with, for example:

```julia
julia> function rep(A,B)
       B= replace!(x -> (x<0 || isnan(x)) ? 0 : x, B);
       A = [a < 0 || isnan(a) ? b : a for (a, b) in zip(A, B)];
       end
rep (generic function with 1 method)

julia> @btime rep(A,B) setup=(A = [1, 2.1, -5, 6, -3, 8, NaN]; B = [8, 8.2, 8, 8, 8, 8, 8]);
  39.938 ns (1 allocation: 144 bytes)

```

Or maybe this is a better benchmark:

```julia
julia> A = rand(10000); B = rand(10000);

julia> @btime replacewith!(a,b,x -> x < 0.1) setup=(a = copy(A); b = copy(B)) evals=1;
  2.080 μs (0 allocations: 0 bytes)

julia> @btime rep(a,b) setup=(a = copy(A); b = copy(B)) evals=1; # adapted inner conditional
  23.956 μs (2 allocations: 78.20 KiB)

```

---

<div class="post-metadata">

**Author:** ![leon](https://avatars.discourse-cdn.com/v4/letter/l/dc4da7/32.png) [@leon](https://discourse.julialang.org/u/leon)\
**Post date:** [October 23, 2021, 12:06pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/11 "2021-10-23T12:06:49Z")

</div>

Wow, this is fascinating! I was always told that a loop will be the slowest way of handling anything. This is so interesting to know.

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [October 23, 2021, 1:27pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/12 "2021-10-23T13:27:11Z")

</div>

Loops are the lowest abstraction here : i.e. closest to the actual hardware process.  
Loops are only slow when you compare interpreted loops (e.g. CPython or Matlab) with compiled libraries.  
Because Julia loops are compiled, there should be no way to get faster with more abstract expressions (considering sequential counterparts).

This does not imply that abstract expressions should be systematically avoided : they can be more compact, less error prone and even allow for parallel implementation on various hardware.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 23, 2021, 5:09pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/13 "2021-10-23T17:09:45Z")

</div>

Getting used to loops is also sort or liberating, because you don’t need to remember, learn, or search, for a function that does what you want every time. Just write what is logically natural and move forward. The impossibility of doing this (and get fast code) is what always kept me away from other high level languages, here you don’t need to adapt the logic to the language.

---

<div class="post-metadata">

**Author:** ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)\
**Post date:** [October 23, 2021, 6:19pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/14 "2021-10-23T18:19:51Z")

</div>

And you can enjoy a nother `7X` speedup using @Elrod’s magic (aka LoopVectorization):

```julia

using LoopVectorization

function replacewith!(A, B)
    @tturbo for i in eachindex(A) 
        A[i] = (A[i] < 0) | isnan(A[i]) ? B[i] : A[i]
    end
    return A
end

A = rand(10000); B = rand(10000);

@btime replacewith!(a,b) setup=(a = copy(A); b = copy(B));
  956.098 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 23, 2021, 6:35pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/15 "2021-10-23T18:35:34Z")

</div>

> [@Seif\_Shebl](#):
>
> `= (A[i] < 0) | isnan(A[i])`

Using `IfEelse.ifelse` here may be even faster.

---

<div class="post-metadata">

**Author:** ![leon](https://avatars.discourse-cdn.com/v4/letter/l/dc4da7/32.png) [@leon](https://discourse.julialang.org/u/leon)\
**Post date:** [October 23, 2021, 6:56pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/16 "2021-10-23T18:56:12Z")

</div>

Very cool. Thanks for sharing.

Is this kind of like parallel computing? BTW, my computer has a 8-Core Intel Core i9 process. What is the best way to make sure all of the 8 cores will be put into good use, but will not crash my computer?

---

<div class="post-metadata">

**Author:** ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)\
**Post date:** [October 23, 2021, 7:05pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/17 "2021-10-23T19:05:52Z")

</div>

Yes, that’s multithreading, a kind of light parallelization method. My results are on a 4-core machine and the number of threads is set to 8, for your processor the number of threads can be set to 16 and you can get more than 10X speedup. The number of threads can be set at the Julia command line as `-t auto`. [You can find this info in the Julia manual](https://docs.julialang.org/en/v1.6/manual/command-line-options/):

`-t, --threads {N|auto}` Enable N threads; `auto` currently sets N to the number of local CPU threads but this might change in the future

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [October 23, 2021, 10:57pm UTC](https://discourse.julialang.org/t/replacing-some-elements-of-an-array-with-corresponding-elements-from-another-array/70248/18 "2021-10-23T22:57:21Z")

</div>

LoopVectorization will do that automatically.
