Использование accmarray для вывода матрицы
От Matlab accumarray
невероятно мощный во многих приложениях. Моя проблема в том, что мой accumarray
Функция для применения на моих входах имеет три выхода, и accumarray
может обрабатывать только скалярные выходы. Например, я хотел бы сделать что-то вроде этого:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
accumarray(subs, vals, [], @(x)[min(x),mean(x),max(x)],0)
и имеют accumarray
вернуть:
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
Я полагаю, я мог бы просто бежать accumarray
три раза, но моя функция работает медленно и работает accumarray
один раз будет намного быстрее, чем запустить его три раза. Я только что накрылся здесь?
1 ответ
Вы можете обмануть, чтобы анонимная функция выводила массив ячеек вместо одного значения. Сюда, accumarray
даст вам массив ячеек матриц. После этого вы можете объединить все матрицы в одну матрицу. Обратите внимание, что предложенная анонимная функция имеет min
, max
а также mean
как вектор строки, но ожидаемый результат - вектор столбца. Поэтому я перенес это в вашу анонимную функцию.
Гоча, которую мы должны принять во внимание, является значением заполнения. Указанное вами значение заполнения должно быть скалярным. Таким образом, вы можете обмануть, пропустив это, но тогда ваш вывод теперь будет содержать пустые матрицы в ячейке вместо строки результата, заполненной 0. Способ обойти это - найти все пустые ячейки, заменить их на ряд нулей, затем соберите все вместе, когда закончите. Чтобы выяснить, какие строки accumarray
выход будет пустым, вы можете использовать cellfun
в сочетании с isempty
так что мы можем видеть, какие элементы в результате пусты. Более точный способ сделать это состоит в том, чтобы сначала предварительно выделить матрицу zeros
затем заполнять только те строки, которые соответствуют непустым местам в выходных данных accumarray
чтобы закончить это:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
out = accumarray(subs, vals, [], @(x){[min(x),mean(x),max(x)].'});
ind_empty = cellfun('isempty', out);
out_final = zeros(3, numel(out));
out_final(:, ~ind_empty) = cat(2, out{:});
Принять к сведению использование cat
который объединяет матрицы вместе в указанном измерении. дела out{:}
создает так называемый список через запятую, поэтому он эквивалентен взятию каждого столбца accumarray
вывод и положить их в качестве отдельных аргументов в cat
так что в конечном итоге мы собираем все столбцы в одну матрицу, но я разбиваю вывод таким образом, что мы заполняем только те места, которые не были пустыми.
С вашими тестовыми данными я сопоставляю то, что вы получаете:
>> out_final
out_final =
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
Однако, если я могу быть честным - если вы точно знаете, что у вас будет только три значения для accumarray
, может быть быстрее просто вызвать его три раза, а затем объединить все, когда вы закончите. Я бы сказал, что это более читабельно и очень ясно дает понять, что вы делаете. Чтобы сделать это так, как я делал с массивом ячеек выше, вам нужно знать, как работает MATLAB.