1

我有一个带有整数键和浮点值的字典。我还有一个带有整数条目的二维尴尬数组(我正在使用尴尬1)。我想根据字典用相应的浮点数替换这些整数,保持尴尬的数组格式。

假设密钥从 0 运行到 999,到目前为止我的解决方案是这样的:

resultArray = ak.where(myArray == 0, myDict.get(0), 0)
for key in range(1,1000):
    resultArray = resultArray + ak.where(myArray == key, myDict.get(key), 0)

有没有更快的方法来做到这一点?

更新

我的工作代码的最小可重现示例:

import awkward as ak # Awkward 1

myArray = ak.from_iter([[0, 1], [2, 1, 0]]) # Creating example array
myDict = {0: 19.5, 1: 34.1, 2: 10.9}

resultArray = ak.where(myArray == 0, myDict.get(0), 0)
for key in range(1,3):
    resultArray = resultArray + ak.where(myArray == key, myDict.get(key), 0)

我的数组:

<Array [[0, 1], [2, 1, 0]] type='2 * var * int64'>

结果数组:

<Array [[19.5, 34.1], [10.9, 34.1, 19.5]] type='2 * var * float64'>
4

1 回答 1

1

当我在评论中提到np.searchsorted是您应该查找的地方时,我没有注意到它myDict包含每个连续整数作为键。拥有像这样的密集查找表将允许更快的算法,这在 Awkward Array 中也恰好更简单。

因此,假设myDict每个整数0到某个值都有一个键,您同样可以将查找表表示为

>>> lookup = ak.Array([myDict[i] for i in range(len(myDict))])
>>> lookup
<Array [19.5, 34.1, 10.9] type='3 * float64'>

0在、1和处取值的问题2变成了一个数组切片。(此数组切片是数组长度n的O(n)算法,与 不同的是O(n log n)。这是拥有稀疏查找键的成本。)np.searchsorted

然而,问题在于它myArray是嵌套的而lookup不是嵌套的。我们可以给出与切片lookup相同的深度:myArray

>>> multilookup = lookup[np.newaxis][np.zeros(len(myArray), np.int64)]
>>> multilookup
<Array [[19.5, 34.1, 10.9, ... 34.1, 10.9]] type='2 * 3 * float64'>
>>> multilookup.tolist()
[[19.5, 34.1, 10.9], [19.5, 34.1, 10.9]]

然后multilookup[myArray]正是你想要的:

>>> multilookup[myArray]
<Array [[19.5, 34.1], [10.9, 34.1, 19.5]] type='2 * var * float64'>

必须重复查找,因为其中的每个列表都myArray使用全局索引lookup。如果创建所涉及的内存multilookup令人望而却步,则可以改为分解myArray以匹配它:

>>> flattened, num = ak.flatten(myArray), ak.num(myArray)
>>> flattened
<Array [0, 1, 2, 1, 0] type='5 * int64'>
>>> num
<Array [2, 3] type='2 * int64'>
>>> lookup[flattened]
<Array [19.5, 34.1, 10.9, 34.1, 19.5] type='5 * float64'>
>>> ak.unflatten(lookup[flattened], nums)
<Array [[19.5, 34.1], [10.9, 34.1, 19.5]] type='2 * var * float64'>

如果您的密钥不密集0到某个整数,那么您将不得不使用np.searchsorted

>>> keys = ak.Array(myDict.keys())
>>> values = ak.Array([myDict[key] for key in keys])
>>> keys
<Array [0, 1, 2] type='3 * int64'>
>>> values
<Array [19.5, 34.1, 10.9] type='3 * float64'>

在这种情况下,它们keys是微不足道的,因为它密集的。使用 时np.searchsorted,您必须将平面 Awkward Arrays 显式转换为 NumPy(目前;我们正在寻求解决该问题)。

>>> lookup_index = np.searchsorted(np.asarray(keys), np.asarray(flattened), side="left")
>>> lookup_index
array([0, 1, 2, 1, 0])

然后我们keys在将它传递给values.

>>> keys[lookup_index]
<Array [0, 1, 2, 1, 0] type='5 * int64'>
>>> values[keys[lookup_index]]
<Array [19.5, 34.1, 10.9, 34.1, 19.5] type='5 * float64'>
>>> ak.unflatten(values[keys[lookup_index]], num)
<Array [[19.5, 34.1], [10.9, 34.1, 19.5]] type='2 * var * float64'>

但我在昨天的评论中胡思乱想的事情是,您必须在myArray( ) 的扁平形式上执行此操作,然后在ak.unflattenflattened之后重新引入结构,如上所述。但也许我们应该至少在第二个参数中识别出一个完全结构化的 Awkward Array 。(它必须是非结构化的才能出现在第一个参数中。)np.searchsortedak.searchsorted

于 2021-01-15T18:30:14.190 回答