2013-08-13 15 views
5

My sytuacji jest to, że I jak mapować skalarne macierzy A przez funkcję z uchwytem fun wysyłającego wektor rzędzie do wektora rzędu, do nabycia B, tak że B(i,:) = fun(A(i,:)).arrayfun gdy każdy wiersz tablicy jest wejście

Najbardziej rozsądnym rozwiązaniem mogłoby myślę wygląda następująco:

temp = mat2cell(A,ones(1,size(A,1)),size(A,2)); 
B = cell2mat(cellfun(fun,temp,'UniformOutput',0)); 

Jednak konwersja do komórek iz powrotem wydaje się przesadą (i jest Przypuszczalnie kosztowne obliczeniowo). Nie jest też dla mnie jasne, dlaczego cellfun narzeka na niejednolite wyniki. Czy bardziej efektywny sposób przeskakuje na myśl?

+0

Powiązane pytanie: [? Jak zastosować funkcję do każdego wiersza w Matlab] (http://stackoverflow.com/q/2307249/1336150) –

Odpowiedz

3

Istnieje inne rozwiązanie, które zatrudnia accumarray. Choć nie tak wyszukane jak bsxfun, że nie wymaga deklarowania funkcji pomocnika:

subs = ndgrid(1:size(A, 1)); 
B = accumarray(subs(:), A(:), [], @fun); %// @fun is the function handle 
2

Myślę, że można zrobić w następujący sposób, jeśli dobrze rozumiem, co u chcą zrobić:

A = rand(3, 5); 
fun = @(x) x*2; 
B = cell2mat(arrayfun(@(i) fun(A(i, :)), 1:size(A, 1), 'UniformOutput', false)'); 

% example results: 
A = 

    0.5669 0.4315 0.4515 0.7664 0.5923 
    0.8337 0.7317 0.4898 0.2535 0.7506 
    0.3321 0.5424 0.4585 0.8004 0.9564 


B = 

    1.1338 0.8630 0.9030 1.5328 1.1845 
    1.6675 1.4635 0.9795 0.5071 1.5013 
    0.6642 1.0848 0.9169 1.6008 1.9128 

ten będzie miał zastosowanie fun do każdego elementu wiersza A. Jest to oparte na stanowisku here. Znajdziesz tam również więcej informacji i objaśnienia, co się dzieje lub alternatywne sposoby zastosowania funkcji do wierszy w tablicy.

+0

Implementacja wygląda identycznie jak mój. Sprawdzę drugi wątek, aby uzyskać więcej informacji - wciąż ciekawych głównie, czy przekształcenie w komórki jest najbardziej rozsądnym sposobem postępowania. –

+0

Dzięki, wpadł na ten sam problem, to wydaje się być najprostszym sposobem, aby osiągnąć odpowiedni wynik. – Realhermit

3

Możesz to zrobić bez użycia tablic komórkowych w ogóle za pomocą bsxfun.

Korzystanie z przykładowych danych i funkcji Marcina:

A =[ 0.5669 0.4315 0.4515 0.7664 0.5923; ... 
    0.8337 0.7317 0.4898 0.2535 0.7506; ... 
    0.3321 0.5424 0.4585 0.8004 0.9564]; 

fun = @(x,y) x*2; 
B= bsxfun(fun,A,1); 

B = 

    1.1338 0.8630 0.9030 1.5328 1.1846 
    1.6674 1.4634 0.9796 0.5070 1.5012 
    0.6642 1.0848 0.9170 1.6008 1.9128 

Edit:

Jak zauważył Eitan, zabawy powyżej, konieczne może być owijka na „prawdziwe” funkcji anonimowej więc byłoby pełniejsze do pokaż moje rozwiązanie jako:

fun = @(x) x *2;  % Replace with actual anonymous function 
fun2 = @(x,y) fun(x); % Wrapper on fun to discard unused 2nd parameter 
B= bsxfun(fun2,A,1); 
+0

Przyjemne użycie bsxfun, ale dotyczy to funkcji do jednej wartości w czasie lub do jednego wiersza w tym czasie? – Marcin

+0

@Marcin Jeśli skalar zostanie przekazany do 'bsxfun' jako jednej z tablic,' bsxfun' wykona skalarną ekspansję i zastosuje ją do każdego elementu innej tablicy ([ostatnie pytanie] (http://stackoverflow.com/q/18079629/1336150) zajmuje się tym problemem). –

+0

@grantnz +1, ale "zabawa" w pytaniu jest jednoznaczna. Zwróć uwagę, że twoja 'zabawa' jest funkcją opakowania zdefiniowaną do użycia w' bsxfun' ... –

2

Wiem, że to stary post, ale w przypadku, gdy ktoś inny nie widzi tego, Matlab dodany rowfun do uwolnienia 2013b, który może ocenić wiersze tabel i zwraca wektor kolumnowy. Oto przykład:

f = @(c) sum(c.^2); 

x=[1 2; 
    3 4; 
    5 6]; 

z=table2array(rowfun(f,table(x))) 

z= 
    5 
    25 
    61 
Powiązane problemy