myr*_*dio 6 performance matlab vector unique
给定三个字符数组,说size(a) = [N,80],size(b) = [N,100];; size(c) = [N,10];
当N=5
a,b并且c看起来像,
ans =
5×80 char array
‘efawefref’
‘Afreafraef’
‘afeafefaef’
‘afeafeaffa’
‘afeafaefae’
Run Code Online (Sandbox Code Playgroud)
我想找到唯一条目(不是组合),这是 x = [a, b, c]
我当然可以做,unique([a, b, c])但是对于这些数据来说这太慢了。N~1e7
例,
a = [ 'timon ';
'simba ';
'nala ';
'timon ';
'mufasa'];
b = [ 'boar ';
'lion ';
'lionese';
'boar ';
'lion '];
c = [ 'chubby';
'small ';
'fat ';
'chubby';
'fit '];
unique([a,b,c],'rows')
ans =
4×19 char array
'mufasalion fit '
'nala lionesefat '
'simba lion small '
'timon boar chubby'
size(unique([a,b,c],'rows'),1)
ans =
4
Run Code Online (Sandbox Code Playgroud)
有没有更聪明的方法可以做到这一点?
编辑:答案的结果对于这些大小的条目,
>> size(a)
ans =
11724952 76
>> size(b)
ans =
11724952 64
>> size(c)
ans =
11724952 6
Run Code Online (Sandbox Code Playgroud)
结果
@myradio
>> tic, size(unique(horzcat(a,b,c),'rows')), toc
ans =
1038303 146
Elapsed time is 74.402044 seconds.
Run Code Online (Sandbox Code Playgroud)
@gnovice 1
>> tic, size(unique(cellstr([a b c]))), toc
ans =
1038303 1
Elapsed time is 77.044463 seconds.
Run Code Online (Sandbox Code Playgroud)
@gnovice 2
>> tic, map = containers.Map(cellstr([a b c]), ones(length(a), 1)); size(map.keys.'), toc
ans =
1038303 1
Elapsed time is 58.732947 seconds.
Run Code Online (Sandbox Code Playgroud)
@沃尔菲
>> tic, size(unique( [categorical(cellstr(a)),categorical(cellstr(b)),categorical(cellstr(c))], 'rows' )), toc
ans =
1038303 3
Elapsed time is 189.517131 seconds.
Run Code Online (Sandbox Code Playgroud)
@obchardon
>> tic, x = primes(2000); a1 = prod(x(a+0),2); b1 = prod(x(b+0),2); c1 = prod(x(c+0),2); size(unique([a1,b1,c1],'rows')), toc
ans =
1038258 3
Elapsed time is 46.889431 seconds.
Run Code Online (Sandbox Code Playgroud)
我对最后一个感到困惑,我尝试了其他示例,但它总是给出较低的值。
为了模仿问题中更大的数据集,我使用以下命令创建了以下随机字符数组randi:
a = char(randi([65 90], [100 76])); % Generate 100 76-character arrays
a = a(randi([1 100], [11724952 1]), :); % Replicate rows: 11724952-by-76 result
b = char(randi([65 90], [100 64])); % Generate 100 64-character arrays
b = b(randi([1 100], [11724952 1]), :); % Replicate rows: 11724952-by-64 result
c = char(randi([65 90], [100 6])); % Generate 100 6-character arrays
c = c(randi([1 100], [11724952 1]), :); % Replicate rows: 11724952-by-6 result
Run Code Online (Sandbox Code Playgroud)
a、b和中每个最多有 100 个唯一字符串c,连接时将产生接近 1,000,000 个唯一组合。
然后我测试了 3 种解决方案:原始的 using unique、一种将字符数组转换为字符串元胞数组的变体 usingcellstr以避免使用'rows'参数,以及一种使用containers.Map对象。最后一个将字符串作为键提供给类containers.Map(具有虚拟关联值),并让它创建一个仅将唯一字符串作为键的映射,然后您可以提取该映射。
由于这些测试至少需要 1 分钟才能运行,因此使用更准确的计时例程timeit(多次运行该函数以获得平均测量值)是不可行的。因此我使用了tic/ toc。以下是使用版本 R2018a 的一些典型结果:
>> clear d
>> tic; d = unique(horzcat(a, b, c), 'rows'); toc
Elapsed time is 726.324408 seconds.
>> clear d
>> tic; d = unique(cellstr([a b c])); toc
Elapsed time is 99.312927 seconds.
>> clear d
>> tic; map = containers.Map(cellstr([a b c]), ones(size(a, 1), 1)); d = map.keys.'; toc
Elapsed time is 89.853430 seconds.
Run Code Online (Sandbox Code Playgroud)
两种更快的解决方案的平均速度通常大致相同,但containers.Map平均速度稍快一些。unique它们都比使用with the argument快得多'rows',尽管这与使用版本 R2018b 的帖子中的结果不一致。也许unique在新版本中进行了重大更新,或者字符数组的具体内容可能非常重要(例如,所有字符串是否以大致相同的频率重复,数组是否已排序与未排序等)。