Как сделать функцию, используя несколько входов? - PullRequest
0 голосов
/ 25 апреля 2019

Я должен сделать матрицу 50x50 со случайными значениями от -10 до 10, а затем, используя пользовательскую функцию с именем averageColumn(), мне нужно создать матрицу 1x50 среднего значения для каждого столбца, исключая любые значения меньше 0.

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

Код для этой функции:

function outputArg1 = averageColumn(inputArg1, inputArg2)
%inputArg1 = an m x n matrix
% inputArg2 = the column# to average
% outputArg1 = the column average, or zero if all the values happen to be zero
for rowNum = 1:50
if inputArg1(rowNum, inputArg2) > 0
    inputArg1(rowNum, inputArg2) = inputArg1(rowNum, inputArg2);
else
    inputArg1(rowNum, inputArg2) = NaN;
end

outputArg1 = nanmean(inputArg1, inputArg2);
end

и код, который у меня есть для матрицы в отдельном файле:

inputArg1 = randi([-10 10],50,50)

for inputArg2 = 1:50
    outputArg1 = averageColumn(inputArg1, inputArg2)    
end

Пожалуйста, будьте нежны, я действительно новичок в Matlab.

Ответы [ 5 ]

2 голосов
/ 25 апреля 2019

Почему все повторяются?Используйте больше векторизации! ...

И почему все NaNs?Используйте положительный взгляд вверх! ...

Мое предложение

Функция:

function ret = averageCol(A, n)

ret = mean(A(A(:, n)>=0, n))

end

Позвоните

A = randi([-100, 100], 50);

out = arrayfun( @(n) averageCol(A, n), 1:size(A, 2))

Пояснение

Изнутри наружу

[1] A(:, n) - вернуть n-й столбец

[2] [1] >= 0 - возвращает вектор логического столбца, который также может использоваться для индексации

[3] A([2], n) - возвращает все значения из n-го столбца, которые больше или равны нулю

[4] Возьмите среднее значение [3] ... Бум!Вы там ...

1 голос
/ 25 апреля 2019

Еще два варианта для получения того же результата:

С

A = randi([-10, 10], 50);

Решение 1. Использование матричного индексирования и nanmean

A(A<0)=NaN;
out = nanmean(A);

Решение 2: Использование линейной алгебры

out = ones(1,size(A,2))*(A.*(A>=0))./sum(A>=0)

Где я использую X̅ = 1'*X*(1'*1)^-1, где 1 - это n x 1 вектор-столбец единиц

0 голосов
/ 25 апреля 2019

РЕДАКТИРОВАТЬ: Ах, я не видел вашего последнего редактирования.Просто используйте nanmean than.


Итак, я попытался сохранить как можно больше вашего кода.

Прежде всего, давайте посмотрим на ваш скрипт, вызывающий вашу функцию:

inputArg1 = randi([-10 10], 50, 50)

for inputArg2 = 1:size(inputArg1, 2)
    outputArg1(inputArg2) = averageColumn(inputArg1, inputArg2);   
end

outputArg1

Просто общий совет: лучше извлекать размеры вводимых данных вместо жестко заданных значений.(Конечно, вы сами настраиваете здесь свой ввод, но постарайтесь помнить об этом.) Чтобы создать требуемый массив со средними, просто используйте номер столбца из цикла for в качестве индекса массива.

Теперь давайте перейдем к вашей функции:

function outputArg1 = averageColumn(inputArg1, inputArg2)
% inputArg1 = an m x n matrix
% inputArg2 = the column# to average
% outputArg1 = the column average, or zero if all the values happen to be zero

for rowNum = 1:size(inputArg1, 1)
    if inputArg1(rowNum, inputArg2) < 0
        inputArg1(rowNum, inputArg2) = NaN;
    end
end

outputArg1 = nanmean(inputArg1(:, inputArg2));

end

Опять же, не задавайте жесткие значения (rowNum)!Кроме того, end для этого цикла for (ваше редактирование) отсутствовал.Оператор if был слишком сложным, поскольку inputArg1(rowNum, inputArg2) = inputArg1(rowNum, inputArg2) является избыточным.Просто установите все отрицательные входы на NaN.Чтобы вычислить «среднее», просто используйте функцию mean, используя флаг omitnan.Или, если у вас есть доступ к «Инструментам статистики и машинного обучения», вы можете использовать функцию nanmean.

0 голосов
/ 25 апреля 2019

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

Так что я верю, что это то, что вы хотите, надеюсь, на этот раз.

inputArg1 = randi([-10 10],50,50);

outputArg1 = [];
for inputArg2 = 1:50
    outputArg1 = [outputArg1 averageColumn(inputArg1, inputArg2)];  
end

В приведенном выше сценарии я изменил способ управления выходным параметром Arg1 на каждой итерации, поэтому посмотрите на него.Я беру значение из функции averegaColumn на каждой итерации и добавляю его в массив outputArg.

Будьте осторожны, изменение размера массива внутри цикла - плохая практика !!!Но опять же, ваш вопрос может быть завершен в 3-4 строки в любом случае:)

А вот и все остальное.Я думаю, что код не требует пояснений.

function outputArg1 = averageColumn(inputArg1, inputArg2)
% inputArg1 = an m x n matrix
% inputArg2 = the column# to average
% outputArg1 = the column average, or zero if all the values happen to be zero

column = inputArg1(:,inputArg2); % take the required column from the input matrix
column(column < 0) = 0; % thanks to Sven Krüger for reminding me this usage!!!
outputArg1 = mean(column);

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

0 голосов
/ 25 апреля 2019

Я считаю, что ваша реализация немного усложнила вещи. Может быть, вы можете попробовать более простой подход.

Если я правильно понял ваши требования, приведенный ниже код должен дать вам желаемое. Если это не так, пожалуйста, дайте мне знать.

Комментариев в коде должно быть достаточно, чтобы вы поняли, что происходит.

mat = randi([-10 10],50,50); % your input matrix

sums = sum(mat); % an array that contains sums of all columns

avgMat = sums/50; % an array that contains average of each column

for i = 1:length(avgMat) % this loop removes negative averages
    if avgMat(i) < 0
        avgMat(i) = NaN;
    end
end

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...