Быстрый способ получения частей матрицы, удовлетворяющих условию с помощью Matlab

#arrays #matlab #matrix #vectorization

#массивы #matlab #матрица #векторизация

Вопрос:

Мне нужен быстрый способ извлечения частей в матрице и складывания их в новую матрицу. Предположим, у меня была такая матрица:

M =

  1    45     4
 1    91    15
 2    34    89
 3    89     9
 3    96    99
  

Теперь я хочу, например, получить все элементы в последних двух столбцах, т.е. левый столбец имеет значения [1; 3], т. Е. Вывод должен выглядеть следующим образом:

  45     4
 91    15
 89     9
 96    99
  

Чтобы получить, например, часть, соответствующую 1 в первом столбце, я мог бы сделать

 M(M(:,1) == 1,2:end), 
  

и я мог бы использовать логическое «или», чтобы получить части, соответствующие [1;3] , но в реальном случае у меня был бы длинный вектор целых чисел… есть ли векторизованный способ сделать это?

Я думаю, что цикл for тоже может быть довольно быстрым, но части матрицы будут разного размера, и их быстрое сложение может быть затруднено…

Комментарии:

1. проверьте ismember() функцию. Определите сами массив, содержащий соответствующие вам значения (например, [1,3] ). Затем проверьте, является ли элемент в M членом этого вектора.

2. Спасибо за подсказку, Миньон, это действительно работает! Также опубликую свой собственный ответ ниже…

3. Обычно со сколькими целыми числами вы бы сравнивали? Если это всего лишь два типа [1 3] , использование M(:,1) == 1 | M(:,1) == 3 может быть быстрее, чем bsxfun решение, я думаю, может быть, не очень удобное.

4. Divakar: много целых чисел…

5. Если какое-либо решение, размещенное здесь, удовлетворяет потребностям вопроса, подумайте о том, чтобы принять его, чтобы SO можно было рассматривать это как «закрытый случай», и людям с аналогичными потребностями помогают самым правильным образом.

Ответ №1:

Посмотрите, достаточно ли это быстро для вас —

 int_arr = [1 3]; %// array of integers to select the rows
M(any(bsxfun(@eq,M(:,1),int_arr),2),2:end)
  

Или

 int_arr = [1;3]; %// array of integers to select the rows
M(any(bsxfun(@eq,M(:,1)',int_arr)),2:end)
  

Комментарии:

1. Какая польза any в этом случае? Как вы выбираете строки? Насколько я вижу, вывод any используется для выбора строк M в этом экземпляре, и any() вернет 0 или 1 итак, как вы получаете правильные строки? При этом выбирается номер строки 0 или 1, если я правильно понял код.

2. @kkuilla bsxfun вывод с @eq представляет собой двоичную матрицу с ones в местах, где выполняется условие равенства между первым столбцом M 1 и 3 . Использование any здесь похоже OR на выбор строк, соответствующих тому, когда столбец 1 имеет 1 ИЛИ 3 . Надеюсь, это будет иметь смысл! 🙂

3. Я не согласен с тем фактом, что any() возвращает номера строк, но привет… ваш ответ работает. 🙂 1

4. @kkuilla Он не возвращает номер строки, он возвращает логический массив «допустимых строк» после «ORing» with any . Этот логический массив используется для индексации в эти допустимые строки, таким образом, используя logical indexing . Использование any здесь просто ORing , вот и все.

5. @kkuilla Точно! Если вы запустите его по частям, надеюсь, все будет ясно! 🙂 Спасибо за голосование! 😉

Ответ №2:

Найден ответ, основанный на предложении Миньона… итак, сначала найдите строки, которые удовлетворяют условию:

 idx = ismember(testmat(:,1),[1 3])

ans =

 1
 1
 0
 1
 1
  

Теперь замените первый столбец:

 M(:,1) = idx

M=
 1    45     4
 1    91    15
 0    34    89
 1    89     9
 1    96    99
  

… а затем просто сделайте

 M(M(:,1)==1,2:end).
  

Я не сравнивал скорость с решением Дивакара выше, так как я спешу, но давайте посмотрим, какой из них быстрее! 😉

Комментарии:

1. Не могли бы вы добавить ссылку на сообщение, на котором вы основали это, пожалуйста?

2. Или, действительно, просто используйте m(ismember(m(:,1),[1,3]),2:end)

3. @MikeLimaOscar вот к чему я пытался добраться. Просто я бы рекомендовал перейти [1 3] на массив, который вы определяете где-то в другом месте. Тогда легче модифицировать.

4. 1, хотя решение с bsxfun может быть быстрее

5. Просто любопытно, смогли ли вы получить некоторые тесты времени выполнения для представленных решений.