朱莉娅:以数组的形式广播结果

时间:2019-07-27 19:00:22

标签: arrays julia

这似乎很基本,以至于我期望有人已经问过这个问题,但是我找不到它。

当我使用广播的幼稚方式时,我想获得二维数组时就得到了数组数组。例如,此功能

function onehotencode(n, domain_size)
    return [ n == k ? 1 : 0 for k in 1:domain_size ]
end

我跑步时

onehotencode.([1,2,3,4], 10)

我明白了

4-element Array{Array{Int64,1},1}:
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]

相反,我想得到

4x10 Array{Int64,2}:
 1 0 0 0 0 0 0 0 0 0
 0 1 0 0 0 0 0 0 0 0
 0 0 1 0 0 0 0 0 0 0
 0 0 0 1 0 0 0 0 0 0

1 个答案:

答案 0 :(得分:3)

您的函数返回向量,因此它们被作为向量的向量收集。要么写:

permutedims(reduce(hcat, onehotencode.([1,2,3,4], 10)))

这将重用您的代码并获得所需的内容(但效率不高),或者只需编写:

.==([1,2,3,4], (1:10)')

.==([1,2,3,4], hcat(1:10...))

如果您想获得Int(而不是Bool),请输入Int.(.==([1,2,3,4], hcat(1:10...)))

==可以由您选择的可在标量上使用的任何功能替换,例如:

julia> f(x,y) = (x,y)
f (generic function with 1 method)

julia> f.([1,2,3,4], hcat(1:10...))
4×10 Array{Tuple{Int64,Int64},2}:
 (1, 1)  (1, 2)  (1, 3)  (1, 4)  (1, 5)  (1, 6)  (1, 7)  (1, 8)  (1, 9)  (1, 10)
 (2, 1)  (2, 2)  (2, 3)  (2, 4)  (2, 5)  (2, 6)  (2, 7)  (2, 8)  (2, 9)  (2, 10)
 (3, 1)  (3, 2)  (3, 3)  (3, 4)  (3, 5)  (3, 6)  (3, 7)  (3, 8)  (3, 9)  (3, 10)
 (4, 1)  (4, 2)  (4, 3)  (4, 4)  (4, 5)  (4, 6)  (4, 7)  (4, 8)  (4, 9)  (4, 10)

通常来说,我发现在Julia的实践中有用的规则是编写在标量上起作用的函数,然后使用广播或语言的其他高阶组件对其进行处理。

编辑

您的函数采用标量,但实际上是在内部对其进行扩展并返回Vector。因此,从概念上讲,您的功能类似于:

function onehotencode(n, domain_range)
    return [ n == k ? 1 : 0 for k in domain_range]
end

尽管它是隐藏的,因为您传递了标量。因此,您可以在onehotencode.([1,2,3,4], hcat(1:10...))实现中编写onehotencode,但是将返回值视为结果Matrix的单元格中的一个条目(这显然不是您想要的)。

如果您将函数定义为:

function onehotencode(n, v)
    return n == v ? 1 : 0
end

即取标量并返回标量(或更准确地说,返回预期结果Matrix中的“单项”,因为从技术上讲,它不必是标量),然后所有操作都按预期进行:

julia> onehotencode.([1,2,3,4], hcat(1:10...))
4×10 Array{Int64,2}:
 1  0  0  0  0  0  0  0  0  0
 0  1  0  0  0  0  0  0  0  0
 0  0  1  0  0  0  0  0  0  0
 0  0  0  1  0  0  0  0  0  0

因此,总而言之,该函数应:将标量作为参数并返回标量(再次,标量一词是一种简化-在参数和返回值中,这些都可以视为单个条目的任何内容-两者中都简单地标量用例是最常见的用例。)