如何在不循环的情况下将唯一组映射到 id

How to map unique groups to ids without looping

假设下面的numpy数组

>>> z = np.zeros(3, dtype={'names': ("id", "dim1", "cnt1"), 'formats': ('i8', 'S3', 'u8')})
>>> z
array([(0, '', 0L), (0, '', 0L), (0, '', 0L)],
      dtype=[('id', '<i8'), ('dim1', 'S3'), ('cnt1', '<u8')])
>>> z["dim1"] = ["foo", "foo", "bar"]
>>>
>>>
>>> z["cnt1"] = [1,2,3]
>>> z
array([(0, 'foo', 1L), (0, 'foo', 2L), (0, 'bar', 3L)],
      dtype=[('id', '<i8'), ('dim1', 'S3'), ('cnt1', '<u8')])

我想将每个唯一 dim1 映射到一个 ID。 在唯一 dim1 值上使用 for 循环执行此操作的一种方法如下:

>>> unique_groups = np.unique(z["dim1"])
>>> groups = z["dim1"]
>>> for idx, ug in enumerate(unique_groups):
...     z["id"][ug == groups] = idx
...
>>> z
array([(1, 'foo', 1L), (1, 'foo', 2L), (0, 'bar', 3L)],
      dtype=[('id', '<i8'), ('dim1', 'S3'), ('cnt1', '<u8')])
>>>

我想知道是否有办法在没有 for 循环的情况下使用向量运算来代替它。 我尝试通过矢量化函数来执行它,如下所示

>>> def map_column(key):
...     return m[key]
...
>>> m
{'foo': 1, 'bar': 0}
>>> f = np.vectorize(map_column, otypes=[str])
>>> f(z["dim1"])
array(['1', '1', '0'],
      dtype='|S1')

还有其他更有效的方法吗?在被认为性能更好的 2 种方式之间?

您可以使用 .searchsorted():

In [2]: unique_groups = np.unique(z["dim1"])

In [3]: z["id"] = unique_groups.searchsorted(z["dim1"])

In [4]: z
Out[4]:
array([(1, b'foo', 1), (1, b'foo', 2), (0, b'bar', 3)],
      dtype=[('id', '<i8'), ('dim1', 'S3'), ('cnt1', '<u8')])

不确定性能,但可能不会好多少。