我有一个包含数字的列表。我想为此列表的每个唯一元素创建此列表(或数组,无关紧要)的bool掩码。
在下面的示例中,我想创建四个长度为len(labels)
的蒙版。第一个掩码在True
位置i
,如果labels[i]==0
,第二个掩码在True
位置i
,labels[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])
答案 0 :(得分:4)
方法1
使用list
和set
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);
};
相同。