# How does replace.() work on a string vector containing missing?

**URL:** <https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029>\
**Category:** General Usage\
**Tags:** strings, broadcast, missing-values\
**Created:** [March 13, 2023, 9:09pm UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029 "2023-03-13T21:09:45Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 13, 2023, 9:09pm UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/1 "2023-03-13T21:09:45Z")

</div>

```julia
replace() and replace.() both work on the same string vector containing no missing

julia> vs=["1.","2","3.","1"]
4-element Vector{String}:
 "1."
 "2"
 "3."
 "1"

julia> replace(vs, "1"=>"999")
4-element Vector{String}:
 "1."
 "2"
 "3."
 "999"

julia> replace.(vs, "1"=>"999")
4-element Vector{String}:
 "999."
 "2"
 "3."
 "999"

julia> vsm=["1.","2","3.",missing,"1"]
5-element Vector{Union{Missing, String}}:
 "1."
 "2"
 "3."
 missing
 "1"

julia> replace(vsm, "1"=>"999")
5-element Vector{Union{Missing, String}}:
 "1."
 "2"
 "3."
 missing
 "999"

# in the case of an array of strings containing missing, the replace.() function cannot handle missing values.Why?

julia> replace.(vsm, "1"=>"999")
ERROR: MethodError: no method matching similar(::Missing, ::Type{Any})

```

a workaround!!?!?

```julia
julia> vsm=["1.","2","3.",[missing],"1"]
5-element Vector{Any}:
 "1."
 "2"
 "3."
 [missing]
 "1"

julia> replace(vsm, "1"=>"999")
5-element Vector{Any}:
 "1."
 "2"
 "3."
 [missing]
 "999"

julia> replace.(vsm, "1"=>"999")
5-element Vector{Any}:
 "999."
 "2"
 "3."
 Union{Missing, String}[missing]
 "999"

```

does this mean that the reason for the error is not the missing value but the fact that the missing is not contained in a vector?

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [March 13, 2023, 9:39pm UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/2 "2023-03-13T21:39:43Z")

</div>

I’m not sure why this is surprising. The issue is that `replace` is not defined for `missing`, but it _is_ defined for `Vector`s.

This has nothing to do with broadcasting.

```julia
julia> replace(missing, "a" => "b")
ERROR: MethodError: no method matching similar(::Missing, ::Type{Any})

julia> replace([missing], "a" => "b")
1-element Vector{Union{Missing, String}}:
 missing

```

I would suggest using `passmissing`

```julia
julia> using Missings

julia> passmissing(replace)(missing, "a" => "b")
missing

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 13, 2023, 10:01pm UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/3 "2023-03-13T22:01:00Z")

</div>

more than anything else, it is a curiosity that comes from the attempt to answer this  
[request](https://discourse.julialang.org/t/how-to-change-form-using-inmemorydatasets-package/95989) without using flow control

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 13, 2023, 10:11pm UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/4 "2023-03-13T22:11:27Z")

</div>

it looks like just what was missing in previous proposals to the problem

```julia
tocurr3(e)=passmissing(parse)(Int,passmissing(replace)(e, r"\$?(\d),?(\d+)( )?(USD)?"=>s"\1\2"))

df3=transform!(df, "Accommodation cost"=>ByRow(tocurr3)=>:ac_cost)

```

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [March 13, 2023, 11:14pm UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/5 "2023-03-13T23:14:15Z")

</div>

> [@rocco\_sprmnt21](#):
>
> ```julia
> tocurr3(e)=passmissing(parse)(Int,passmissing(replace)(e, r"\$?(\d),?(\d+)( )?(USD)?"=>s"\1\2"))
> 
> ```

Feels like using `passmissing` once is neater:

```julia
tocurr3(e)=passmissing(e->parse(Int,replace(e, r"\$?(\d),?(\d+)( )?(USD)?"=>s"\1\2")))(e)

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 14, 2023, 6:12am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/6 "2023-03-14T06:12:58Z")

</div>

> [@pdeffebach](#):
>
> The issue is that `replace` is not defined for `missing`, but it _is_ defined for `Vector`s.

my question is precisely about this. Why does replace() work in one case and not in the other?

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [March 14, 2023, 6:48am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/7 "2023-03-14T06:48:30Z")

</div>

`replace(::String,...)` is a special case. You’ll find `replace(1, 1=>999)` doesn’t work either. Because what is the point of a replace method working on scalars - unless those scalars have some internal structure where substitution is meaningful like strings?

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 14, 2023, 7:33am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/8 "2023-03-14T07:33:52Z")

</div>

Okay. I had guessed this aspect. What I’m missing is understanding the reason (and I think there is a reason) why in the following two cases (where strings or string vectors are not involved but only missing and [missing] ) there is a behavior different

```julia

julia> replace(missing, "a" => "b")
ERROR: MethodError: no method matching similar(::Missing, ::Type{Any})

julia> replace([missing], "a" => "b")
1-element Vector{Union{Missing, String}}:
 missing

```

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [March 14, 2023, 7:40am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/9 "2023-03-14T07:40:52Z")

</div>

Does this help?

```julia
julia> replace("abc", "a" => "b")
"bbc"

julia> replace(["abc", "a", "b"], "a" => "b")
3-element Vector{String}:
 "abc"
 "b"
 "b"

```

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [March 14, 2023, 7:41am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/10 "2023-03-14T07:41:28Z")

</div>

Because the primary use of `replace` is to iterate a collection and replace any elements that equal `e` by `s`.  
`replace([1, 2, 3], 1=>999) == [999, 2, 3]`. You can’t do this with scalars because it doesn’t make sense to iterate them. Strings are an exception because they are also a collection of substrings.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 14, 2023, 7:45am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/11 "2023-03-14T07:45:12Z")

</div>

No. Because, in this case (ie without ‘missing’ elements) replace.() also works

```julia
julia> replace.(["abc", "a", "b"], "a" => "b")
3-element Vector{String}:
 "bbc"
 "b"
 "b"

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 14, 2023, 7:50am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/12 "2023-03-14T07:50:15Z")

</div>

I probably set the question wrong (but I wasn’t initially clear about the whole context).  
What I wanted to clarify is what @pdeffebach pointed out  
which I rewrite below so as to exclude the specifics of strings (scalar and iterable at the same time) from the question

```julia
ulia> replace(missing, 1 => 2)
ERROR: MethodError: no method matching similar(::Missing, ::Type{Any})

julia> replace([missing], 1 => 2)
1-element Vector{Union{Missing, Int64}}:
 missing

```

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [March 14, 2023, 8:18am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/13 "2023-03-14T08:18:59Z")

</div>

Right, but that’s completely analogous to

```julia
julia> replace(1, 1=>999)
ERROR...

julia> replace([1], 1=>999)
[999]

```

`replace` doesn’t work on _scalars_, only _collections_. `missing` isn’t a collection, but strings are, in a sense.

Note in your examples of `replace(::Vector{String})` vs `replace.(::Vector{String})`, that they both “work”, but they _don’t_ do the same thing. The first one treats each string as a scalar, and the second as a collection, so the results are different.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 14, 2023, 8:47am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/14 "2023-03-14T08:47:10Z")

</div>

mmmmh… maybe this clarifies my point better.  
It’s not so much being misslingt that generates the error but being an immutable scalar(!?).  
So if there was a passONE similar to passMISSING we would have this result…

```julia
using Missings
passmissing(replace)(missing,1=>999)
#hand made
using Ones
passone(replace)(1,2=>999)
1

```

at this point I wonder if it is correct that passmissing() changes this behavior in the case of missing

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [March 14, 2023, 9:25am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/15 "2023-03-14T09:25:44Z")

</div>

I mean yeah, but that has nothing to do with `replace` specifically. For instance, there is no `sort(scalar)` method (I assume, not at a computer right now), so `sort(missing)` is an error. But `passmissing(sort)(missing)` is `missing`. `passmissing` doesn’t care whether its argument function has a method for `missing`, if any of that argument function’s arguments is `missing`, `passmissing` returns `missing`.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 14, 2023, 10:25am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/16 "2023-03-14T10:25:59Z")

</div>

Yes I have seen passmissing() do this.  
I wonder if this isn’t a stretch in cases where, explicitly, the (wrapped) functions are not applicable to that specific situation (single missing and replace or sort functions , for example)

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [March 14, 2023, 10:30am UTC](https://discourse.julialang.org/t/how-does-replace-work-on-a-string-vector-containing-missing/96029/17 "2023-03-14T10:30:37Z")

</div>

That’s exactly what is documented:

```julia
Return a function that returns missing if any of its positional arguments are 
missing (even if their number or type is not consistent with any of the 
methods defined for f) and otherwise applies f to these arguments.

```
