在pandas.DataFrame的多个列上使用numpy.unique

时间:2017-04-02 10:47:18

标签: python-3.x pandas numpy dataframe uniqueidentifier

我希望使用numpy.unique来获取pandas.DataFrame的两列的反向唯一索引。

我知道如何在一列上使用它:

u, rev = numpy.unique(df[col], return_inverse=True)

但我想在多列上使用它。例如,如果df看起来像:

    0   1   
0   1   1
1   1   2
2   2   1
3   2   1
4   3   1

然后我想获得反向索引:

[0,1,2,2,3]

2 个答案:

答案 0 :(得分:2)

方法#1

这里有一个NumPy方法将每一行转换为一个标量,每一行都将每一行视为一个二维(对于2列数据)网格的索引元组 -

def unique_return_inverse_2D(a): # a is array
    a1D = a.dot(np.append((a.max(0)+1)[:0:-1].cumprod()[::-1],1))
    return np.unique(a1D, return_inverse=1)[1]

如果数据中有负数,我们也需要使用min来获取这些标量。因此,在这种情况下,请使用a.max(0) - a.min(0) + 1代替a.max(0) + 1

方法#2

这是另一款基于NumPy的基于视图的解决方案,专注于受this smart solution by @Eric启发的性能 -

def unique_return_inverse_2D_viewbased(a): # a is array
    a = np.ascontiguousarray(a)
    void_dt = np.dtype((np.void, a.dtype.itemsize * np.prod(a.shape[1:])))
    return np.unique(a.view(void_dt).ravel(), return_inverse=1)[1]

样品运行 -

In [209]: df
Out[209]: 
    0   1   2   3
0  21   7  31  69
1  62  75  22  62  # ----|
2  16  46   9  31  #     |==> Identical rows, so must have same IDs
3  62  75  22  62  # ----|
4  24  12  88  15

In [210]: unique_return_inverse_2D(df.values)
Out[210]: array([1, 3, 0, 3, 2])

In [211]: unique_return_inverse_2D_viewbased(df.values)
Out[211]: array([1, 3, 0, 3, 2])

答案 1 :(得分:1)

我认为您可以将列转换为strings,然后转换为sum

u, rev = np.unique(df.astype(str).values.sum(axis=1), return_inverse=True)
print (rev)
[0 1 2 2 3]

如指出DSM(谢谢),这很危险。

另一种解决方案是将行转换为tuples

u, rev = np.unique(df.apply(tuple, axis=1), return_inverse=True)
print (rev)
[0 1 2 2 3]