假设我想编写一个函数,该函数需要任意长度的数组作为参数输入: 例如,
f = function(x,y)
z = x * y
outputs = DataFrame(x = x, y = y, z = z)
return(outputs)
end
返回f.([1,2],[1,2])
是两个1x3数据帧的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
。有什么我想念的吗?我的问题是,如何获得所需的n m元素而不是n m数组...
我尝试遵循此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
是单个元素,则用户调用两个函数时都不要带点,如果每个变量具有多个元素,则使用.
。这似乎不可能。因此,我必须学习生活的一部分是必须在我的函数中编写许多.
或[i]
(如果我想要“一致性”)。是吗?
或者,我可以添加文档来明确声明,当参数的长度大于1时,返回一个变量的函数需要使用.
调用,而返回数据帧的函数则不需要使用{{1出于任何原因。
[原谅任何对技术语言的滥用;我的背景是生态学]
答案 0 :(得分: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})
或其他适合您的参数中添加类型。
答案 1 :(得分:1)
我的偏好是,如果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
与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 │