Виртуальные cеминары и неформальное общение по солнечно-земной физике. Солнечный ветер, магнитосферы, магнитные возмущения, ... 2007 - Международный гелиофизический год

Форум по солнечно-земным связям

Объявление

Добро пожаловать на форум по солнечно-земной физике! Заходите, читайте, регистрируйтесь, пишите!
PS После регистрации Вы увидите больше разделов и тем (но не мгновенно).

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Форум по солнечно-земным связям » MATLAB » Боремся с циклами


Боремся с циклами

Сообщений 1 страница 10 из 10

1

Известно, что MATLAB циклов не любит и считает с ними медленно до неприличия. Во многих случаях их обходить довольно легко, но вот в некоторых я так и не придумала ничего осмысленного. Задача простая и часто встречающаяся в обработке.

Есть два массива данных, которые надо объединить по одинаковым значениям в одной из колонок (физически обычно это время, но это неважно). Пусть сам шаг уже приведен к одинаковому, и надо только выбрать совпадающие моменты. Можно ди это сделать совсем без цикла? У меня один внешний все же остается, а внутренний заменяется командой find.

2

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

3

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

% Chooses rows with the same time in 2 n-column matrixes
function [ch_row]=ch_row(fil_1,fil_2,e_ps)
t_1=fil_1(:,1);
t_2=fil_2(:,1);
sz_2=size(t_2);
l_2=sz_2(1,1);
k_r=0;

for i_r=1:l_2
   f_q=find(abs(t_1-t_2(i_r))<e_ps);
   if isempty(f_q)==0
      k_r=k_r+1;
      fil_out{2}(k_r,: )=fil_2(i_r,: );
      sz_q=size(f_q);
      l_q=sz_q(1,1);
      if l_q==1
         fil_out{1}(k_r,: )=fil_1(f_q,: );
      else
         fil_out{1}(k_r,: )=mean(fil_1(f_q,: ));
      end
   end
end
f2=fil_out{2}; s2=size(f2); w2=s2(1,2);
ch_row=[fil_out{1},f2(:,2:w2)];

Про ходу выяснилась забавная проблема. Форум вместо двоеточия со скобкой ставит рожицы. Пришлось во всех таких местах пробелы вставлять.

4

Так а Вы в своем профайле отключите галочку в меню "отображения"  -  "Преобразовывать смайлики в изображения, по умолчанию."

5

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

% Chooses rows with the same time in 2 n-column matrixes
function [ch_row] = ch_row(fil_1, fil_2, e_ps)

t_1 = fil_1(:,1);
t_2 = fil_2(:,1);

k = 0;
for ( i = 1 : length(t_2) )
   
   [i] = find(abs(t_1 - t_2(i)) < e_ps);
   
   if ( isempty(I) == 0 )
       
      k = k + 1;     
      fil_out{2}(k) = fil_2(i);
      fil_out{1}(k) = mean(fil_1(I));
     
   end;
   
end;

% это я не поняла, что такое
f2 = fil_out{2};
s2 = size(f2);
w2 = s2(1,2);

ch_row = [fil_out{1},f2(:,2:w2)];

6

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

PS А я, кажется, придумала, Сейчас попробую реализовать и сброшу. Дуаю, что может пригодиться и не только мне,  потому что проблема сортировки довольно часто встречатесяч и особенно, если циклов несколько, сильно тормозит.

Отредактировано n_y (2007-05-20 14:09:35)

7

Интересно. Ждем.

8

Надь, а вот еще быстрей будет, если память отводить до начала цикла. Это самое действенное.

function [ch_row] = ch_row(fil_1, fil_2, e_ps)

t_1 = fil_1(:,1);
t_2 = fil_2(:,1);

fil_out{1} = zeros(length(t_2), 1);
fil_out{2} = zeros(length(t_2), 1);
k = 0;
for ( i = 1 : length(t_2) )
   
   [i] = find(abs(t_1 - t_2(i)) < e_ps);
   
   if ( isempty(I) == 0 )
       
      k = k + 1;     
      fil_out{2}(k) = fil_2(i);
      fil_out{1}(k) = mean(fil_1(I));
     
   end;
   
end;

if( k < length(t_2) )
    fil_out{1}(k+1:end) = [];
    fil_out{2}(k+1:end) = [];
end;

9

Спасибо, Оль, про это тоже не знала. Я что-то закопалась в других делах и программку не написала пока, но выложу обязательно.

10

А вот и программа без циклов. При сколько-нибудь длинных файлах выигрыш очень заметный. Предполагается, что точность e_ps мала по сравнению с минимальным шагом по времени в одном файле min(diff(fil_1(:,1)))

% Choose rows with the same time in 2 n-column matrixes
function [ch_row,fr_1,fr_2]=ch_row(fil_1,fil_2,e_ps)
% looks for close times in two files and for them
% ch_row=[fil_1,fil_2];
s_1=size(fil_1);
L_1=s_1(1,1);
w_1=s_1(1,2)-1;
s_2=size(fil_2);
L_2=s_2(1,1);
w_2=s_2(1,2)-1;
w_t=w_1+w_2;
v_1=[1:L_1]';  % row number in the initial file #1
v_2=[1:L_2]';  % row number in the initial file #2
b_1=[fil_1(:,1),ones(L_1,1),v_1];  % 2-nd column - file number
b_2=[fil_2(:,1),ones(L_2,1)*2,v_2]; 
b_t=[b_1;b_2];  % join files
b_ts=sortrows(b_t,1);   % sort along the 1-st (time) column
f_eq=find(diff(b_ts(:,1))<=e_ps);  % look for approximately equal times
L_eq=length(f_eq);
b_r=[b_ts(f_eq,:),b_ts(f_eq+1,2:3)]; % form an array with file and row numbers for equal times
f_dir=find(b_r(:,2)==1 & b_r(:,4)==2); % times with t_1<t_2
f_inv=find(b_r(:,2)==2 & b_r(:,4)==1);  % times with t_2<t_1
ch_row=[b_r(:,1),zeros(L_eq,w_t)];  % blank for the output array
v_eq_11=b_r(f_dir,3); % row numbers in fil_1 for t_1<t_2
v_eq_12=b_r(f_dir,5);  % row numbers in fil_2 for t_1<t_2
v_eq_21=b_r(f_inv,5); % row numbers in fil_2 for t_2<t_1
v_eq_22=b_r(f_inv,3); % row numbers in fil_1 for t_2<t_1
ch_row(f_dir,2:w_1+1)=fil_1(v_eq_11,2:w_1+1);  % fill the blank for t_1<t_2
ch_row(f_dir,w_1+2:w_t+1)=fil_2(v_eq_12,2:w_2+1);
ch_row(f_inv,2:w_1+1)=fil_1(v_eq_21,2:w_1+1);  fill the blank for t_2<t_1
ch_row(f_inv,w_1+2:w_t+1)=fil_2(v_eq_22,2:w_2+1);
fr_10=[v_eq_11;v_eq_22];
fr_1=sort(fr_10);  % row numbers in fil_1
fr_20=[v_eq_12;v_eq_21];
fr_2=sort(fr_20);  % row numbers in fil_1
end

________________
:) © n_y 2007.06.05.


Вы здесь » Форум по солнечно-земным связям » MATLAB » Боремся с циклами