快速 numpy/torch 语法来合并具有相同列值的行
Fast numpy/torch syntax to pool rows with same column value
我给出了一个 array/tensor 的 n 个值,其中每个值由一个特征向量(在示例中是前 4 个值)和一个位置向量(在示例中是第 5 个值)组成。因此这里的整个数组的形状是 (n, 5).
[ 1 2 3 4 *0* ]
[ 5 1 0 1 *1* ]
[ 0 1 0 1 *1* ]
[ 1 0 3 0 *2* ]
[ 1 1 2 6 *2* ]
[ 0 1 0 2 *2* ]
我的目标是根据位置向量沿第一个维度汇集(最大或求和或平均)值。 IE。具有相同位置向量(此处为第 5 个值)的所有行应结合给定一些对称函数(假设为 sum()),同时保持第 5 个值不变。产生一个新的形状数组 (n', 5)
[ 1 2 3 4 *0* ]
[ 5 2 0 2 *1* ]
[ 2 2 5 8 *2* ]
自然地,这可以通过遍历数组并使用 key, value = positional_vector, sum(feature_vector, dict[positional_vector])
将它们全部保存到字典中然后将其转换回数组来实现。
不幸的是,这种方法似乎相当慢,因为我打算在神经网络的训练中使用它,所以使用一些 tensor/matrix 乘法魔法似乎更明智。
非常感谢任何有帮助的评论:)
[与给定的例子相反,位置向量可能是 n 维的并且没有顺序。]
所以这是基于我在评论中提到的 diff
方法的粗略答案。请注意,由于您需要基于组的聚合操作,因此没有真正有效地对其进行矢量化的真正方法。此外,此示例假设您的数据已排序,我们稍后再谈。
def reduce(x): return np.r_[x[:,:-1].sum(axis=0), x[0,-1]]
x = np.array([[ 1, 2, 3, 4, 0 ],
[ 5, 1, 0, 1, 1 ],
[ 0, 1, 0, 1, 1 ],
[ 1, 0, 3, 0, 2 ],
[ 1, 1, 2, 6, 2 ],
[ 0, 1, 0, 2, 2 ] ])
ind = np.where(np.diff(x[:,-1], prepend=x[0,-1]))[0]
x_agg = np.array([reduce(i) for i in np.split(x, ind)])
代码很简单,它找到最后一行的值发生变化的索引,在这些位置拆分数组并根据需要聚合它。
现在如果数据没有排在最后一行,就会出现两种情况:
- 目标值相同的元素相邻。这应该没问题,因为差异行为是相同的(可能必须添加
np.where(np.diff(...)!=0)
之类的条件
- 相同的目标值是分散的,那么顺序应该不会
很重要,因为在聚集后没有合乎逻辑的方法来映射它们。
希望对您有所帮助。
我给出了一个 array/tensor 的 n 个值,其中每个值由一个特征向量(在示例中是前 4 个值)和一个位置向量(在示例中是第 5 个值)组成。因此这里的整个数组的形状是 (n, 5).
[ 1 2 3 4 *0* ]
[ 5 1 0 1 *1* ]
[ 0 1 0 1 *1* ]
[ 1 0 3 0 *2* ]
[ 1 1 2 6 *2* ]
[ 0 1 0 2 *2* ]
我的目标是根据位置向量沿第一个维度汇集(最大或求和或平均)值。 IE。具有相同位置向量(此处为第 5 个值)的所有行应结合给定一些对称函数(假设为 sum()),同时保持第 5 个值不变。产生一个新的形状数组 (n', 5)
[ 1 2 3 4 *0* ]
[ 5 2 0 2 *1* ]
[ 2 2 5 8 *2* ]
自然地,这可以通过遍历数组并使用 key, value = positional_vector, sum(feature_vector, dict[positional_vector])
将它们全部保存到字典中然后将其转换回数组来实现。
不幸的是,这种方法似乎相当慢,因为我打算在神经网络的训练中使用它,所以使用一些 tensor/matrix 乘法魔法似乎更明智。
非常感谢任何有帮助的评论:)
[与给定的例子相反,位置向量可能是 n 维的并且没有顺序。]
所以这是基于我在评论中提到的 diff
方法的粗略答案。请注意,由于您需要基于组的聚合操作,因此没有真正有效地对其进行矢量化的真正方法。此外,此示例假设您的数据已排序,我们稍后再谈。
def reduce(x): return np.r_[x[:,:-1].sum(axis=0), x[0,-1]]
x = np.array([[ 1, 2, 3, 4, 0 ],
[ 5, 1, 0, 1, 1 ],
[ 0, 1, 0, 1, 1 ],
[ 1, 0, 3, 0, 2 ],
[ 1, 1, 2, 6, 2 ],
[ 0, 1, 0, 2, 2 ] ])
ind = np.where(np.diff(x[:,-1], prepend=x[0,-1]))[0]
x_agg = np.array([reduce(i) for i in np.split(x, ind)])
代码很简单,它找到最后一行的值发生变化的索引,在这些位置拆分数组并根据需要聚合它。
现在如果数据没有排在最后一行,就会出现两种情况:
- 目标值相同的元素相邻。这应该没问题,因为差异行为是相同的(可能必须添加
np.where(np.diff(...)!=0)
之类的条件
- 相同的目标值是分散的,那么顺序应该不会 很重要,因为在聚集后没有合乎逻辑的方法来映射它们。
希望对您有所帮助。