Как я могу эффективно удалить нули из (не разреженной) матрицы? - PullRequest
11 голосов
/ 10 апреля 2009

У меня есть матрица:

x = [0 0 0 1 1 0 5 0 7 0];

Мне нужно удалить все нули, вот так:

x = [1 1 5 7];

Матрицы, которые я использую, большие (1x15000), и мне нужно сделать это несколько раз (5000+), поэтому эффективность является ключевым фактором!

Ответы [ 6 ]

16 голосов
/ 10 апреля 2009

В одну сторону:

x(x == 0) = [];

Примечание о сроках:

Как упоминалось woodchips , этот метод выглядит медленным по сравнению с тем, который используется KitsuneYMG . Это также было отмечено Лорен в одном из ее сообщений в блоге MathWorks . Поскольку вы упоминали о необходимости сделать это тысячи раз, вы можете заметить разницу, в этом случае я сначала попробую x = x(x~=0);.

ПРЕДУПРЕЖДЕНИЕ: Осторожно, если вы используете нецелые числа. Например, если у вас очень маленькое число, которое вы хотите считать достаточно близким к нулю, чтобы его можно было удалить, приведенный выше код не удалит его. Только точные нули удаляются. Следующее поможет вам также удалить числа "достаточно близко" к нулю:

tolerance = 0.0001;  % Choose a threshold for "close enough to zero"
x(abs(x) <= tolerance) = [];
11 голосов
/ 11 апреля 2009

Это три общих решения. Это помогает увидеть разницу.

x = round(rand(1,15000));

y = x;

tic,y(y==0) = [];toc

Elapsed time is 0.004398 seconds.

y = x;

tic,y = y(y~=0);toc

Elapsed time is 0.001759 seconds.

y = x;

tic,y = y(find(y));toc

Elapsed time is 0.003579 seconds.

Как вы должны видеть, самый дешевый способ - это прямой логический индекс, выбирающий элементы для сохранения. Поиск является более дорогим, поскольку matlab находит эти элементы, возвращает их список, а затем индексирует в векторе.

11 голосов
/ 10 апреля 2009

Просто чтобы быть другим:

x=x(x~=0);

или

x=x(abs(x)>threshold);

Также есть бонус к работе с комплексными числами

3 голосов
/ 10 апреля 2009

Вот еще один способ

y = x (найти (x))

Я оставлю это вам, чтобы выяснить относительную эффективность различных подходов, которые вы пробуете - напишите и сообщите нам всем.

2 голосов
/ 23 июля 2013

Несмотря на то, что мои временные результаты не позволяют сделать вывод о том, является ли он значительно более быстрым, этот способ представляется наиболее быстрым и простым:

y = nonzeros(y) 
0 голосов
/ 09 августа 2012
x = [0 0 0 1 1 0 5 0 7 0]
y = [0 2 0 1 1 2 5 2 7 0]

Тогда x2 и y2 можно получить как:

x2=x(~(x==0 & y==0))
y2=y(~(x==0 & y==0))

x2 = [0     1     1     0     5     0     7]
y2 = [2     1     1     2     5     2     7]

Надеюсь, это поможет!

...