Аналогичная функция для 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
но не вторая часть (или, по крайней мере, я не могу понять, как это сделать).
Любые предложения?
Ответы
Ответ 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
Я пока не могу найти более простую функцию, которая делает это за один шаг, если вас это интересует.