Подтвердить что ты не робот

Аналогичная функция для R rep в Matlab

Я ищу функцию, которая ведет себя аналогично функции rep в R для Matlab. Например, с помощью rep я могу сделать следующее:

> rep(c(1,2,3),times=3)
[1] 1 2 3 1 2 3 1 2 3

> rep(c(1,2,3),each=3)
[1] 1 1 1 2 2 2 3 3 3
> 

В Matlab существует функция repmat, которая выполняет первую часть

>> repmat([1,2,3],1,3)

ans =

     1     2     3     1     2     3     1     2     3

но не вторая часть (или, по крайней мере, я не могу понять, как это сделать).

Любые предложения?

4b9b3361

Ответ 1

Вы можете воспроизвести синтаксис функции rep в R довольно близко, сначала определив функцию следующим образом:

function [result]=rep(array, count)
matrix = repmat(array, count,1);
result = matrix(:);

Затем вы можете воспроизвести желаемое поведение, вызвав либо вектор строки или столбца:

>> rep([1 2 3],3)
ans =
 1     1     1     2     2     2     3     3     3

>> rep([1 2 3]',3)
ans =
 1     2     3     1     2     3     1     2     3

Примечание. Я использовал оператор transpose (') во втором вызове, чтобы передать входной массив как вектор-столбец (матрица 3x1).

Я сравнивал это на своем ноутбуке, и для базового массива с 100 000 элементов, повторяющихся 100 раз, это было в 2-8 раз быстрее, чем использование вышеописанной опции, в зависимости от того, хотите ли вы первую или вторую компоновку.

Ответ 2

Хороший вопрос +1. Оптимальный однострочный метод для достижения этого - через тензорное произведение Кронекера, например:

A = [1 2 3];
N = 3;
B = kron(A, ones(1, N));

Тогда:

B =

     1     1     1     2     2     2     3     3     3

ОБНОВЛЕНИЕ: @Dan предоставил очень аккуратное решение, которое выглядит более эффективным, чем мой метод kron, поэтому проверьте этот ответ перед тем, как покинуть страницу: -)

UPDATE: @bcumming также предоставил приятное решение, которое должно очень хорошо масштабироваться, когда входной вектор большой.

Ответ 3

Если вы, как я, вы не знаете, что такое тензорный продукт Kronecker, вам может быть интересно это более интуитивно понятное (и на самом деле я думаю быстрее) решение:

c(ceil((1:length(c)*n)/n));

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

c = 1:3;
c([1 1 1 2 2 2 3 3 3]) %for each
c([1 2 3 1 2 3 1 2 3]) %for times

так что вопросы в том, как мы создаем вектор [1 2 3 1 2 3 1 2 3] без самой функциональности, которую вы запрашиваете. Таким образом, я создал вектор с количеством элементов, которые нам нужны, то есть 1: 9, а затем разделим на три и округлить (т.е. Попробуйте ceil((1:9)/3) в командной строке.

Немного бенчмаркинга (я знаю, что этот материал должен быть в циклах, поэтому, возможно, это не так точно):

c = 1:3; n = 3;
tic; k = kron(c, ones(1, n)); toc; % 0.000208 seconds.
tic; a = c(ceil((1:length(c)*n)/n)); toc;  % 0.000025 seconds.
clear;
c = 1:1000000; n = 3;
tic; k = kron(c, ones(1, n)); toc; % 0.143747 seconds.
tic; a = c(ceil((1:length(c)*n)/n)); toc;  % 0.090956 seconds.
clear;
c = 1:10000; n = 1000;
tic; k = kron(c, ones(1, n)); toc; % 0.583336 seconds.
tic; a = c(ceil((1:length(c)*n)/n)); toc;  % 0.237878 seconds.

Ответ 4

Вот одна идея:

a=[1,2,3];
reshape(repmat(a,1,length(a)),1,length(a)^2)

ans =

 1     2     3     1     2     3     1     2     3

reshape(repmat(a,length(a),1),1,length(a)^2)

ans =

 1     1     1     2     2     2     3     3     3

Я пока не могу найти более простую функцию, которая делает это за один шаг, если вас это интересует.