朱莉娅(Julia):广播结果在数组的数组中

6

这似乎很基础,我本以为有人已经问过了,但我找不到。

当我使用广播的方式时,我得到的是一个数组中嵌套数组的结果,而我希望得到一个二维数组。例如,这个函数:

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个回答

4
您的函数返回向量,因此它们被收集为向量的向量。可以编写以下代码来解决这个问题:
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实现写入onehotencode.([1,2,3,4], hcat(1:10...)),但返回值被视为结果Matrix中单元格的条目(这显然不是您想要的)。
如果您将函数定义为:
function onehotencode(n, v)
    return n == v ? 1 : 0
end

即将标量作为输入并返回一个标量(更准确地说,返回预期结果“矩阵”中的“单个条目”,因为技术上它不一定是标量),那么所有内容都会按预期工作:
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

总之,该函数应:将标量作为参数并返回标量(注意,“标量”一词是一个简化,因为在参数和返回值中都可以是被认为是单个条目的任何内容。在这两种情况下,标量仅仅是最常见的用例)。


您的代码很好用,非常感谢。但是我的问题难道不正是“编写能够处理标量的函数,然后使用广播”这个问题的一个实例吗?我有一个可以处理标量的函数(例如onehotencode(4, 10)),但现在我必须使用不同的代码来处理向量情况(.==([1,2,3,4], hcat(1:10...)))。另外,您说“==可以被任何适用于标量的函数替换”,但实际上onehotencode.([1,2,3,4], hcat(1:10...))并没有给我想要的结果。 - user1950164
我会在答案中详细阐述。 - Bogumił Kamiński
我现在明白发生了什么。感谢澄清 :-) - user1950164
非常感谢您!能否解释一下在 .==([1,2,3,4], (1:10)')' 的作用是什么? - CodeNoob
1
(1:10)'1:10 的共轭转置,因此在这种情况下它是一个具有 1 行和 10 列的对象。由于 [1, 2, 4, 5] 具有 4 行和 1 列,结果是输入的所有组合,并且具有 4 行和 10 列。 - Bogumił Kamiński

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