如何将类型为字符串的向量转换为数字类型(Float64)? Julia

5
在Julia 1.1中,我想将一个字符串类型的向量转换为数字类型(Float64),以下是向量:
string = ["2.2", "3,3", "4.4"];

我尝试了以下这行代码,但没有成功:

x = convert(Float64, string)
x = convert(DataVector{Float64}, string)
x = map(x->parse(Float64,x),string)
x = parse(Float64,string)
x = Float64(string)
1个回答

10
最简单的方法是:
julia> s = ["2.2", "3.3", "4.4"];

julia> parse.(Float64, s)
3-element Array{Float64,1}:
 2.2
 3.3
 4.4

但是 map 也可以使用:

julia> map(x->parse(Float64,x), s)
3-element Array{Float64,1}:
 2.2
 3.3
 4.4

在您原始示例中存在两个问题:
  • 第二个字符串"3,3"是一个无效的Floa64数字(它有一个错误的小数分隔符);
  • 虽然有效,但我建议您不要将string作为变量名称使用,因为它会覆盖Base中的string函数。
此外,如果您原始的字符串以逗号作为小数分隔符,则可以先对它们运行replace命令,例如在这里我在向量上广播它:
julia> s = ["2.2", "3,3", "4,4"];

julia> replace.(s, [','=>'.'])
3-element Array{String,1}:
 "2.2"
 "3.3"
 "4.4"

编辑:正如DNF所指出的那样,写作时更快的方法是写:

replace.(s, (','=>'.',))

或者

replace.(s, Ref(','=>'.'))

通常情况下,如果使用了.,则表示正在进行广播操作,因此所有参数都应该可以广播。但是,在我们的情况下,Pair(即','=>'.')不能被视为可广播的,因此我们必须将其包装在一个可广播的单元素容器中。
第一种方法是使用[]将其包装在一个单元素数组中,但这有点低效,因为它会分配一个新的临时数组。
您可以使用单元素元组来包装它,使用(,)(请注意,)之前要加逗号,否则模式将无法正常工作)。这种方法不会分配内存。
最后,您可以使用内置的Ref函数,在这种情况下,它将创建一个Base.RefValue{Pair{Char,Char}}类型的对象,该对象被Julia视为0维单元素容器(这是一个稍微高级的主题,您可以在Julia手册的此部分中开始探索)。这种方法也不会分配内存。
有关您可以广播的内容,请参见Julia手册中的此处

其他情况:

对于字符串和缺失值的数组,您需要使用最新的Missings.jl(在包管理器中运行up命令)。
julia> s = ["2.2", "3.3", "4.4", missing]
4-element Array{Union{Missing, String},1}:
 "2.2"
 "3.3"
 "4.4"
 missing

julia> passmissing(parse).(Float64, s)
4-element Array{Union{Missing, Float64},1}:
 2.2
 3.3
 4.4
  missing

字符串的数组和NaN

在实际使用中,这种情况不应该发生,因为您会在一个向量中缺少字符串或浮点数,但您可以像这样做(我已经将5.5添加到向量中,以向您展示解决方案不仅限于NaN,而是可以吸收任何字符串或任何Float64):

julia> s = ["2.2", "3.3", "4.4", NaN, 5.5]
5-element Array{Any,1}:
    "2.2"
    "3.3"
    "4.4"
 NaN
   5.5

julia> [v isa Float64 ? v : parse(Float64, v) for v in s]
5-element Array{Float64,1}:
   2.2
   3.3
   4.4
 NaN
   5.5

非常感谢@BogumiłKamiński提供的非常清晰的答案。实际上,我刚刚在我的实际问题上尝试了一下:在一个数据框中,我有一个类型为s = ["2.2","3.3","4.4",missing]的列。有没有办法将该字符串s转换为Float64(如果我有s = ["2.2","3.3","4.4",NaN],答案是否相同)? - ecjb
非常感谢@BogumiłKamiński。使用NaN的例子完美运作,但是在安装了Missings并键入using Missings后,当我执行s = ["2.2", "3.3", "4.4", missing]passmissing(parse).(Float64, s)时,我遇到了UndefVarError: passmissing not defined Stacktrace: [1] top-level scope at none:0 - ecjb
1
非常微小的细节:将 replace 对在 replace.(s, [','=>'.']) 中用 Ref 或元组包装,而不是分配一个向量,这样做是否更好?虽然性能差异很小,但我认为使用 Ref 是正常的建议。 - DNF
2
我可以理解。虽然元组应该尽快引入,因为它们随处可见。 - DNF
你遇到了什么错误?请确保你已经安装了Missings.jl版本0.4.0,参见发布说明https://github.com/JuliaData/Missings.jl/releases。 - Bogumił Kamiński
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接