假设我想编写一个需要任何长度的数组作为参数输入的函数:例如,
f = function(x,y)
z = x * y
outputs = DataFrame(x = x, y = y, z = z)
return(outputs)
end
返回,f.([1,2],[1,2])
是一个包含两个1x3 DataFrame的2元素数组。但是,在这种情况下,我想要一个2x3 DataFrame。
我可以通过在嵌套for循环之前定义z来实现这一点:
f = function(x,y)
z=fill(0,length(x))
for i in 1:length(x)
z[i] = x[i] * y[i]
end
outputs = DataFrame(x = x, y = y, z = z)
return(outputs)
end
在这里,f([1,2],[1, 2])
得到了我想要的东西。但是,问题是我必须两次定义所有函数内变量并添加for循环,同时记住包含迭代变量i
。有什么我想念的吗?我的问题是,我如何得到我想要的nm元素而不是nm数组...我试着遵循这个Julia blog post。此外this Julia discussion post专门解决了这个问题,但我认为解决方案已经过时了1.0。
----编辑
使用for循环可以像使用点来表示元素操作一样。我关心的更大问题是一致性。假设我有两个功能。一个函数(f1
)返回一维输出,而另一个函数(f2
)具有二维输出。
function f1(x, y)
z = x .* y
DataFrame(x = x, y = y, z = z)
end
function f2(x, y)
z = x * y
return(z)
end
这里正确的调用当x = [1,2]
和y = [1,2]
将是f1([1,2], [1,2])
和f2.([1,2], [1,2])
。我在这里称之为不一致的是(从一个不知道内部函数代码的用户的角度来看),得到一个输出,其中z
是x
和y
的长度,.
与f2
一起使用但是不是f1
。我能看到的唯一解决方法是在z = .x * y
中定义f2
(或者为每个索引循环使用a)。在这种情况下,f1
和f2
都可以在没有点的情况下调用。这是一个合适的解决方案?为了清楚起见,我的目标是f1
和f2
被用户称为x
和y
是单个还是多个元素数组。如果x
和y
是单个元素,并且.
if每个变量都有多个元素,那么我的偏好是让用户在没有点的情况下调用这两个函数。这似乎不可能。因此,我必须学会忍受的部分是必须在我的函数中写出许多.
或[i]
(如果我想要“一致性”)。正确?
或者,我可以添加文档,明确指出当参数长度> 1时,我需要使用.
调用返回一个变量的函数,并且无需出于任何原因使用.
调用返回数据帧的函数。 [原谅任何滥用技术语言的行为;我的背景是生态学]
那是你要的吗?
julia> function f(x, y)
z = x .* y
DataFrame(x = x, y = y, z = z)
end
f (generic function with 1 method)
julia> f([1,2], [1,2])
2×3 DataFrame
│ Row │ x │ y │ z │
├─────┼───┼───┼───┤
│ 1 │ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │ 4 │
你也可以写简短的f(x, y) = DataFrame(x = x, y = y, z = x .* y)
。
你写函数定义的方式表明你知道R.在Julia中,与R相反,标量和数组是完全分离的类型(例如.Float64
和Vector{Float64}
),并且必须区别对待;但通常情况下,只需在正确的位置添加足够的广播(并通过在任何函数调用之后或任何运算符之前放置.
来进行广播工作)。
为了确保不混淆这些东西,你可以在参数中添加类型:f(x::Vector{Float64}, y::Vector{Float64})
或任何适合你的东西。
我的偏好是让用户在没有点的情况下调用两个函数,如果x和y是单个元素,并且如果每个变量都有多个元素。
您需要一个专门研究参数类型的函数。执行时最优雅,最快的编译方式是使用@generated
宏。
using DataFrames
@generated function f(a,b)
if a<:Array && b<:Array
code = quote
DataFrame(x = a, y = b, z = a .* b)
end
else
code = quote
DataFrame(x = a, y = b, z = a * b)
end
end
code
end
现在让我们测试一下。请注意函数行为如何取决于参数的类型(Float64
vs Int
)。每个参数可以是Array
或标量。
julia> f(3,4)
1×3 DataFrame
│ Row │ x │ y │ z │
├─────┼───┼───┼────┤
│ 1 │ 3 │ 4 │ 12 │
julia> f(3,4.0)
1×3 DataFrame
│ Row │ x │ y │ z │
├─────┼───┼─────┼──────┤
│ 1 │ 3 │ 4.0 │ 12.0 │
julia> f(3.0,[1,2,3])
3×3 DataFrame
│ Row │ x │ y │ z │
├─────┼─────┼───┼─────┤
│ 1 │ 3.0 │ 1 │ 3.0 │
│ 2 │ 3.0 │ 2 │ 6.0 │
│ 3 │ 3.0 │ 3 │ 9.0 │
julia> f([1,2,3],4)
3×3 DataFrame
│ Row │ x │ y │ z │
├─────┼───┼───┼────┤
│ 1 │ 1 │ 4 │ 4 │
│ 2 │ 2 │ 4 │ 8 │
│ 3 │ 3 │ 4 │ 12 │
julia> f([6,7,8],[1,2,3])
3×3 DataFrame
│ Row │ x │ y │ z │
├─────┼───┼───┼────┤
│ 1 │ 6 │ 1 │ 6 │
│ 2 │ 7 │ 2 │ 14 │
│ 3 │ 8 │ 3 │ 24 │