为数组中的每个唯一元素创建布尔掩码

时间:2017-08-08 08:04:03

标签: python pandas optimization

我有一个包含数字的列表。我想为此列表的每个唯一元素创建此列表(或数组,无关紧要)的bool掩码。

在下面的示例中,我想创建四个长度为len(labels)的蒙版。第一个掩码在True位置i,如果labels[i]==0,第二个掩码在True位置ilabels[i]==1等< / p>

我尝试用pandas和循环中的.isin方法做到这一点。但是,这对我来说太慢了,因为在我的算法中多次调用它并且标签列表可能很长,因此循环无效。我怎样才能让它更快?

labels = [0,0,1,1,3,3,3,1,2,1,0,0]
d = dict()
y = pd.Series(labels)
for i in set(labels):
    d[i] = y.isin([i])

3 个答案:

答案 0 :(得分:4)

方法1

使用listset

In [989]: {x: [x==l for l in labels] for x in set(labels)}
Out[989]:
{0: [True, True, False, False, False, False, False, False, False, False, True, True],
 1: [False, False, True, True, False, False, False, True, False, True, False, False],
 2: [False, False, False, False, False, False, False, False, True, False, False, False],
 3: [False, False, False, False, True, True, True, False, False, False, False, False]}

如果您想要dataframe

In [994]: pd.DataFrame({x: [x==l for l in labels] for x in set(labels)})
Out[994]:
        0      1      2      3
0    True  False  False  False
1    True  False  False  False
2   False   True  False  False
3   False   True  False  False
4   False  False  False   True
5   False  False  False   True
6   False  False  False   True
7   False   True  False  False
8   False  False   True  False
9   False   True  False  False
10   True  False  False  False
11   True  False  False  False

方法2

使用pd.get_dummies,无论如何你可以<{1}}

series

<强>基准

In [997]: pd.get_dummies(y).astype(bool)
Out[997]:
        0      1      2      3
0    True  False  False  False
1    True  False  False  False
2   False   True  False  False
3   False   True  False  False
4   False  False  False   True
5   False  False  False   True
6   False  False  False   True
7   False   True  False  False
8   False  False   True  False
9   False   True  False  False
10   True  False  False  False
11   True  False  False  False

In [1002]: len(labels)
Out[1002]: 12

In [1003]: %timeit pd.get_dummies(y).astype(bool)
1000 loops, best of 3: 476 µs per loop

In [1004]: %timeit pd.DataFrame({x: [x==l for l in labels] for x in set(labels)})
1000 loops, best of 3: 580 µs per loop

In [1005]: %timeit pd.DataFrame({x : (y == x) for x in y.unique()})
1000 loops, best of 3: 1.15 ms per loop

答案 1 :(得分:1)

你可以使用statsmodels.tools.tools.categorical,这应该是相当快的,特别是如果你已经有一个NumPy数组可以使用。

categorical(np.array(labels), drop=True).astype(bool)

如果要在结果数组中的每个列与其相应标签之间进行显式映射,请将dictnames=True传递给category

<强>演示

>>> from statsmodels.tools.tools import categorical
>>> labels = np.array([0,0,1,1,3,3,3,1,2,1,0,0])
>>> categorical(labels, drop=True).astype(bool)
array([[ True, False, False, False],
       [ True, False, False, False],
       [False,  True, False, False],
       [False,  True, False, False],
       [False, False, False,  True],
       [False, False, False,  True],
       [False, False, False,  True],
       [False,  True, False, False],
       [False, False,  True, False],
       [False,  True, False, False],
       [ True, False, False, False],
       [ True, False, False, False]], dtype=bool)

>>> res, d = categorical(np.array(labels), drop=True, dictnames=True)
>>> d
{0: 0, 1: 1, 2: 2, 3: 3}

粗略基准(假设已经是NumPy数组)

您的数据集:

>>> %timeit categorical(labels, drop=True).astype(bool)
14.1 µs ± 519 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

更大的数据集:labels = np.random.randint(0, 4, 10000)

%timeit categorical(labels, drop=True).astype(bool)
360 µs ± 9.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

答案 2 :(得分:0)

创建一个groupby值数组。遍历True以获取标签的索引位置,并将其设置为d = {} empty_labels = np.array([False] * len(labels)) for label, group in pd.DataFrame(labels, columns=['labels']).groupby('labels'): d[label] = empty_labels.copy() d[label][group] = True >>> d {0: array([ True, False, False, False, False, False, False, False, False, False, False, False], dtype=bool), 1: array([False, True, False, False, False, False, False, False, False, False, False, False], dtype=bool), 2: array([False, False, True, False, False, False, False, False, False, False, False, False], dtype=bool), 3: array([False, False, False, True, False, False, False, False, False, False, False, False], dtype=bool)}

pd.get_dummies

速度应与 $scope.IsValidImageUrl = function(url){ return imageTestService.IsValidImageUrl(url); }; 相同。