Você pode aplicar uma função a cada item em um vetor dizendo, por exemplo v + 1
, ou pode usar a função arrayfun
. Como posso fazer isso para cada linha / coluna de uma matriz sem usar um loop for?
fonte
Você pode aplicar uma função a cada item em um vetor dizendo, por exemplo v + 1
, ou pode usar a função arrayfun
. Como posso fazer isso para cada linha / coluna de uma matriz sem usar um loop for?
Muitas operações integradas gostam sum
e prod
já são capazes de operar em linhas ou colunas, portanto, você pode refatorar a função que está aplicando para tirar vantagem disso.
Se essa não for uma opção viável, uma maneira de fazer isso é coletar as linhas ou colunas em células usando mat2cell
ou e num2cell
, em seguida, use cellfun
para operar na matriz de células resultante.
Como exemplo, digamos que você deseja somar as colunas de uma matriz M
. Você pode fazer isso simplesmente usando sum
:
M = magic(10); %# A 10-by-10 matrix
columnSums = sum(M, 1); %# A 1-by-10 vector of sums for each column
E aqui está como você faria isso usando a opção num2cell
/ mais complicada cellfun
:
M = magic(10); %# A 10-by-10 matrix
C = num2cell(M, 1); %# Collect the columns into cells
columnSums = cellfun(@sum, C); %# A 1-by-10 vector of sums for each cell
true = false
é uma declaração válida, tenho certeza de que há uma maneira de fazer isso (:sum(M, 1)
. Iniciantes podem pensar quesum
podem ser usados dessa forma para matrizes de tamanhos arbitrários e então ficar perplexos quando a matriz um dia for usada1-by-n
.Você pode querer a função mais obscura do Matlab, bsxfun . A partir da documentação do Matlab, bsxfun "aplica a operação binária elemento a elemento especificada pelo identificador de função divertido para os arrays A e B, com a expansão singleton habilitada."
@gnovice afirmou acima que soma e outras funções básicas já operam na primeira dimensão não única (ou seja, linhas se houver mais de uma linha, colunas se houver apenas uma linha, ou dimensões superiores se as dimensões inferiores tiverem tamanho == 1 ) No entanto, bsxfun funciona para qualquer função, incluindo (e especialmente) funções definidas pelo usuário.
Por exemplo, digamos que você tenha uma matriz A e um vetor linha BEg, digamos:
Você quer uma função power_by_col que retorna em um vetor C todos os elementos em A à potência da coluna correspondente de B.
No exemplo acima, C é uma matriz 3x3:
ie,
Você poderia fazer isso usando a força bruta usando repmat:
Ou você pode fazer isso da maneira clássica usando bsxfun, que cuida internamente da etapa repmat:
Portanto, o bsxfun economiza algumas etapas (você não precisa calcular explicitamente as dimensões de A). No entanto, em alguns testes informais meus, descobri que repmat é quase duas vezes mais rápido se a função a ser aplicada (como minha função de potência, acima) for simples. Portanto, você precisará escolher se deseja simplicidade ou velocidade.
fonte
Não posso comentar o quão eficiente isso é, mas aqui está uma solução:
fonte
Com base na resposta de Alex , aqui está uma função mais genérica:
Aqui está uma comparação entre as duas funções:
fonte
Para integridade / interesse, gostaria de acrescentar que o matlab tem uma função que permite operar em dados por linha em vez de por elemento. É chamado
rowfun
( http://www.mathworks.se/help/matlab/ref/rowfun.html ), mas o único "problema" é que funciona em tabelas ( http://www.mathworks.se/help/ matlab / ref / table.html ) em vez de matrizes .fonte
Somando-se à natureza evolutiva da resposta a esta pergunta, começando com r2016b, o MATLAB expandirá implicitamente as dimensões do singleton, removendo a necessidade de
bsxfun
em muitos casos.Das notas de lançamento do r2016b :
fonte
Nenhuma das respostas acima funcionou "fora da caixa" para mim, no entanto, a seguinte função, obtida copiando as ideias das outras respostas funciona:
Ele pega uma função
f
e a aplica a todas as colunas da matrizM
.Então, por exemplo:
fonte
Com as versões recentes do Matlab, você pode usar a estrutura de dados da tabela a seu favor. Há até uma operação 'rowfun', mas achei mais fácil fazer isso:
ou aqui está um mais antigo que eu tinha que não requer tabelas, para versões mais antigas do Matlab.
fonte
A resposta aceita parece ser primeiro converter em células e depois usar
cellfun
para operar em todas as células. Não conheço a aplicação específica, mas no geral acho que usarbsxfun
para operar sobre a matriz seria mais eficiente. Basicamente,bsxfun
aplica uma operação elemento por elemento em duas matrizes. Portanto, se você quiser multiplicar cada item de umn x 1
vetor por cada item de umm x 1
vetor para obter uman x m
matriz, poderá usar:Isso lhe dará uma matriz chamada
result
em que a entrada (i, j) será o iésimo elemento devec1
multiplicado pelo j-ésimo elemento devec2
.Você pode usar
bsxfun
para todos os tipos de funções internas e pode declarar as suas próprias. A documentação tem uma lista de muitas funções embutidas, mas basicamente você pode nomear qualquer função que aceite dois arrays (vetor ou matriz) como argumentos e fazê-la funcionar.fonte
Tropecei nesta pergunta / resposta enquanto procurava como calcular as somas das linhas de uma matriz.
Eu gostaria apenas de acrescentar que a função SUM do Matlab, na verdade, tem suporte para somar para uma dada dimensão, ou seja, uma matriz padrão com duas dimensões.
Portanto, para calcular as somas das colunas:
e para as somas de linha, basta fazer
Minha aposta é que isso é mais rápido do que programar um loop for e converter para células :)
Tudo isso pode ser encontrado na ajuda do matlab para SUM.
fonte
se você sabe o comprimento de suas linhas, pode fazer algo assim:
fonte