Örneğin, diyerek bir vektördeki her öğeye bir işlev uygulayabilir v + 1
veya işlevi kullanabilirsiniz arrayfun
. For döngüsü kullanmadan bir matrisin her satırı / sütunu için bunu nasıl yapabilirim?
Örneğin, diyerek bir vektördeki her öğeye bir işlev uygulayabilir v + 1
veya işlevi kullanabilirsiniz arrayfun
. For döngüsü kullanmadan bir matrisin her satırı / sütunu için bunu nasıl yapabilirim?
Yanıtlar:
Birçok yerleşik işlem gibi sum
ve prod
halihazırda satırlar veya sütunlar arasında çalışabilir, bu nedenle bundan yararlanmak için uyguladığınız işlevi yeniden düzenleyebilirsiniz.
Bu uygun bir seçenek değilse, bunu yapmanın bir yolu, satırları veya sütunları mat2cell
veya kullanarak hücrelere toplamaktır num2cell
, ardından cellfun
elde edilen hücre dizisi üzerinde çalışmak için kullanmaktır .
Örnek olarak, bir matrisin sütunlarını toplamak istediğinizi varsayalım M
. Bunu basitçe kullanarak yapabilirsiniz sum
:
M = magic(10); %# A 10-by-10 matrix
columnSums = sum(M, 1); %# A 1-by-10 vector of sums for each column
Ve işte bunu daha karmaşık num2cell
/ cellfun
seçeneği kullanarak nasıl yapacağınız :
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
Geçerli bir ifadenin olduğu bir dilde , bunu yapmanın bir yolu olduğuna eminim (:
sum(M, 1)
. Yeni başlayanlar sum
, keyfi boyutlu matrisler için bu şekilde kullanılabileceğini düşünebilir ve matris bir gün olduğunda şaşkına dönebilir 1-by-n
.
Daha belirsiz olan Matlab bsxfun işlevini isteyebilirsiniz . Matlab belgelerine göre, bsxfun "işlev tanıtıcısı tarafından belirtilen öğe-öğe ikili işlemi, tekil genişletme etkinleştirilmiş olarak A ve B dizilerine uygular."
@gnovice, yukarıda toplam ve diğer temel işlevlerin tekil olmayan ilk boyutta (yani birden fazla satır varsa satırlar, yalnızca bir satır varsa sütunlar veya daha düşük boyutların hepsinin boyuta sahipse daha yüksek boyutlarda == 1) çalıştığını belirtti. ). Ancak, bsxfun, (ve özellikle) kullanıcı tanımlı işlevler dahil olmak üzere herhangi bir işlev için çalışır.
Örneğin, bir A matrisiniz ve BEg satır vektörünüz olduğunu varsayalım, diyelim:
A = [1 2 3;
4 5 6;
7 8 9]
B = [0 1 2]
Bir C vektöründe A'daki tüm öğeleri karşılık gelen B sütununun üssüne döndüren bir power_by_col işlevi istiyorsunuz.
Yukarıdaki örnekten C, 3x3 bir matristir:
C = [1^0 2^1 3^2;
4^0 5^1 6^2;
7^0 8^1 9^2]
yani
C = [1 2 9;
1 5 36;
1 8 81]
Repmat kullanarak bunu kaba kuvvet yöntemiyle yapabilirsiniz:
C = A.^repmat(B, size(A, 1), 1)
Veya bunu, repmat adımını dahili olarak halleden bsxfun kullanarak klas bir şekilde yapabilirsiniz:
C = bsxfun(@(x,y) x.^y, A, B)
Yani bsxfun size bazı adımlar kazandırır (A'nın boyutlarını açık bir şekilde hesaplamanıza gerek yoktur). Bununla birlikte, bazı gayri resmi testlerimde, uygulanacak fonksiyon (yukarıdaki güç fonksiyonum gibi) basitse, repmat'ın kabaca iki kat daha hızlı olduğu ortaya çıkıyor. Bu yüzden basitlik mi yoksa hız mı istediğinizi seçmeniz gerekecek.
Bunun ne kadar verimli olduğu hakkında yorum yapamam ama işte bir çözüm:
applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :))
applyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1))'
% Example
myMx = [1 2 3; 4 5 6; 7 8 9];
myFunc = @sum;
applyToRows(myFunc, myMx)
Alex'in cevabına dayanarak , işte daha genel bir işlev:
applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :));
newApplyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1), 'UniformOutput', false)';
takeAll = @(x) reshape([x{:}], size(x{1},2), size(x,1))';
genericApplyToRows = @(func, matrix) takeAll(newApplyToRows(func, matrix));
İşte iki işlev arasında bir karşılaştırma:
>> % Example
myMx = [1 2 3; 4 5 6; 7 8 9];
myFunc = @(x) [mean(x), std(x), sum(x), length(x)];
>> genericApplyToRows(myFunc, myMx)
ans =
2 1 6 3
5 1 15 3
8 1 24 3
>> applyToRows(myFunc, myMx)
??? Error using ==> arrayfun
Non-scalar in Uniform output, at index 1, output 1.
Set 'UniformOutput' to false.
Error in ==> @(func,matrix)arrayfun(applyToGivenRow(func,matrix),1:size(matrix,1))'
Tamlık / ilgi açısından, matlab'ın öğe başına değil, satır başına veri üzerinde işlem yapmanıza izin veren bir işlevi olduğunu eklemek isterim. Adı rowfun
( http://www.mathworks.se/help/matlab/ref/rowfun.html ), ancak tek "sorun" tablolar üzerinde çalışmasıdır ( http://www.mathworks.se/help/ matlab / ref / table.html ) matrisler yerine .
Bu sorunun cevabının gelişen doğasına ek olarak, r2016b'den başlayarak, MATLAB bsxfun
birçok durumda ihtiyacı ortadan kaldırarak örtük olarak tekli boyutları genişletecektir .
Gönderen r2016b sürüm notlarına :
Örtülü Genişletme: Uzunluk 1'in boyutlarının otomatik olarak genişletilmesiyle dizilere eleman bazlı işlemler ve işlevler uygulayın
Örtük genişleme, skaler genişlemenin bir genellemesidir. Skaler genişletme ile, eleman bazlı işlemleri kolaylaştırmak için bir skaler başka bir diziyle aynı boyuta genişler. Örtük genişletme ile, burada listelenen eleman bazlı operatörler ve işlevler, diziler uyumlu boyutlara sahip olduğu sürece girdilerini aynı boyutta olacak şekilde örtük olarak genişletebilir. Her boyut için girişlerin boyut boyutları aynı ise veya bunlardan biri 1 ise, iki dizinin uyumlu boyutları vardır. Daha fazla bilgi için Temel İşlemler için Uyumlu Dizi Boyutları ve Matris İşlemlerine Karşı Diziye bakın.
Element-wise arithmetic operators — +, -, .*, .^, ./, .\ Relational operators — <, <=, >, >=, ==, ~= Logical operators — &, |, xor Bit-wise functions — bitand, bitor, bitxor Elementary math functions — max, min, mod, rem, hypot, atan2, atan2d
Örneğin, bir A matrisindeki her sütunun ortalamasını hesaplayabilir ve ardından ortalama değerlerin vektörünü her sütundan A - ortalama (A) ile çıkarabilirsiniz.
Daha önce, bu işlevsellik bsxfun işlevi aracılığıyla mevcuttu. Artık bsxfun'un çoğu kullanımını örtük genişletmeyi destekleyen işlevlere ve işleçlere doğrudan çağrılarla değiştirmeniz önerilir. Bsxfun kullanımına kıyasla, örtük genişletme daha yüksek hız, daha iyi bellek kullanımı ve iyileştirilmiş kod okunabilirliği sunar.
Yukarıdaki cevapların hiçbiri benim için "kutunun dışında" işe yaramadı, ancak diğer cevapların fikirlerini kopyalayarak elde edilen aşağıdaki fonksiyon işe yarıyor:
apply_func_2_cols = @(f,M) cell2mat(cellfun(f,num2cell(M,1), 'UniformOutput',0));
Bir işlevi alır f
ve matrisin her sütununa uygular M
.
Yani mesela:
f = @(v) [0 1;1 0]*v + [0 0.1]';
apply_func_2_cols(f,[0 0 1 1;0 1 0 1])
ans =
0.00000 1.00000 0.00000 1.00000
0.10000 0.10000 1.10000 1.10000
Matlab'ın son sürümleri ile Tablo veri yapısını kendi avantajınıza kullanabilirsiniz. Bir 'rowfun' operasyonu bile var ama bunu yapmayı daha kolay buldum:
a = magic(6);
incrementRow = cell2mat(cellfun(@(x) x+1,table2cell(table(a)),'UniformOutput',0))
ya da burada eski Matlab sürümleri için tablo gerektirmeyen daha eski bir tane var.
dataBinner = cell2mat(arrayfun(@(x) Binner(a(x,:),2)',1:size(a,1),'UniformOutput',0)')
Kabul edilen cevap, önce hücrelere dönüştürmek ve ardından cellfun
tüm hücreler üzerinde çalışmak için kullanmak gibi görünüyor . Spesifik uygulamayı bilmiyorum, ancak genel bsxfun
olarak matris üzerinde işlem yapmak için kullanmanın daha verimli olacağını düşünürdüm. Temel olarak bsxfun
, iki dizide bir işlem öğesi tek tek uygular. Dolayısıyla , bir dizi elde etmek için bir vektördeki n x 1
her öğeyi bir vektördeki her öğeyle çarpmak isterseniz, şunu kullanabilirsiniz:m x 1
n x m
vec1 = [ stuff ]; % n x 1 vector
vec2 = [ stuff ]; % m x 1 vector
result = bsxfun('times', vec1.', vec2);
Bu size result
(i, j) girdisinin j'inci elemanı ile vec1
çarpılan i'inci elemanı olacağı adı verilen matrisi verecektir vec2
.
Her bsxfun
türlü yerleşik işlev için kullanabilir ve kendinizinkini ilan edebilirsiniz. Belgelerde birçok yerleşik işlevin bir listesi vardır, ancak temelde iki diziyi (vektör veya matris) bağımsız değişken olarak kabul eden herhangi bir işlevi adlandırabilir ve çalışmasını sağlayabilirsiniz.
Bir matrisin satır toplamlarının nasıl hesaplanacağını ararken bu soruya / cevaba tökezledi.
Matlab'ın SUM işlevinin aslında belirli bir boyut için toplama desteğine sahip olduğunu eklemek isterim, yani iki boyutlu standart bir matris.
Yani sütun toplamlarını hesaplamak için şunları yapın:
colsum = sum(M) % or sum(M, 1)
ve satır toplamları için
rowsum = sum(M, 2)
Bahse girerim bu hem for döngüsü programlamaktan hem de hücrelere dönüştürmekten daha hızlıdır :)
Bütün bunlar SUM için matlab yardımında bulunabilir.
Satırlarınızın uzunluğunu biliyorsanız, şöyle bir şey yapabilirsiniz:
a=rand(9,3);
b=rand(9,3);
arrayfun(@(x1,x2,y1,y2,z1,z2) line([x1,x2],[y1,y2],[z1,z2]) , a(:,1),b(:,1),a(:,2),b(:,2),a(:,3),b(:,3) )