38

I am trying to write numeric data pulled from a database into a Float64[]. The original data is in ::ASCIIString format, so trying to push it to the array gives the following error:

julia> push!(a, "1")
ERROR: MethodError: `convert` has no method matching convert(::Type{Float64}, ::ASCIIString)
This may have arisen from a call to the constructor Float64(...),
since type constructors fall back to convert methods.
Closest candidates are:
  call{T}(::Type{T}, ::Any)
  convert(::Type{Float64}, ::Int8)
  convert(::Type{Float64}, ::Int16)
  ...
 in push! at array.jl:432

Attempting to convert the data directly unsurprisingly throws the same error:

julia> convert(Float64, "1")
ERROR: MethodError: `convert` has no method matching convert(::Type{Float64}, ::ASCIIString)
This may have arisen from a call to the constructor Float64(...),
since type constructors fall back to convert methods.
Closest candidates are:
  call{T}(::Type{T}, ::Any)
  convert(::Type{Float64}, ::Int8)
  convert(::Type{Float64}, ::Int16)
  ...

Given that I know the data is numeric, is there a way I can convert it before pushing?

p.s. I am using version 0.4.0

sophros
  • 14,672
  • 11
  • 46
  • 75
peter-b
  • 4,073
  • 6
  • 31
  • 43
  • 3
    BTW consider using `tryparse(Float64,x)` instead of `parse`. It returns a Nullable Float which is null in the case string doesn't parse well. – Dan Getz Oct 30 '15 at 16:52
  • 2
    Good suggestion, cheers. BTW if you want to write up an answer I'll accept it, otherwise I'll just write something for the sake of completeness in day or two. – peter-b Oct 30 '15 at 16:55

3 Answers3

52

You can parse(Float64,"1") from a string. Or in the case of a vector

map(x->parse(Float64,x),stringvec)

will parse the whole vector.

BTW consider using tryparse(Float64,x) instead of parse. It returns a Nullable{Float64} which is null in the case string doesn't parse well. For example:

isnull(tryparse(Float64,"33.2.1")) == true

And usually one would want a default value in case of a parse error:

strvec = ["1.2","NA","-1e3"]
map(x->(v = tryparse(Float64,x); isnull(v) ? 0.0 : get(v)),strvec)
# gives [1.2,0.0,-1000.0]
sophros
  • 14,672
  • 11
  • 46
  • 75
Dan Getz
  • 17,002
  • 2
  • 23
  • 41
  • Commenting in 2021: what is `Nullable{T}`? It looks like it should be `Union{Nothing,T}`? And should `isnull` be `isnothing` (or `=== nothing`) now? – BallpointBen Jun 11 '21 at 19:56
9

Use parse(Float64,"1").

See more at: parse specification

Maciek Leks
  • 1,288
  • 11
  • 21
0

The previous answers are good, however, I had expand on them:

#col1 = df[:,3]
col1 = ["1.2", "NA", "", Base.missing, "-1e3"]

# I do not like writing unreadable code like this:
col2 = map(x->(x=ismissing(x) ? "" : x; x=tryparse(Float64,x); isnothing(x) ? missing : x), col1)

returns Array{Float64,1} if original data was all numbers:

5-element Array{Union{Missing, Float64},1}:
     1.2
      missing
      missing
      missing
 -1000.0

Alternative (explained):

function convert_to_float(column)
    new_column = map(x -> (
            x = ismissing(x) ? "" : x;  # no method matching tryparse(::Type{Float64}, ::Missing)
            x = tryparse(Float64, x);   # returns: Float64 or nothing
            isnothing(x) ? missing : x; # options: missing, or "", or 0.0, or nothing
            ), column)  # input 
    # returns Array{Float64,1} OR Array{Union{Missing, Float64},1}
    return new_column
end
Uki D. Lucas
  • 516
  • 6
  • 4