Проблема с циклом MATLAB - PullRequest
       14

Проблема с циклом MATLAB

1 голос
/ 02 июня 2010
no  time  scores
1    10    123
2    11    22
3    12    22
4    50    55
5    60    22
6    70    66
.    .     .
.    .     .
n    n     n 

Над содержимым моего текстового файла (тысяч строк).

1st column - number of samples
2nd column - time (from beginning to end ->accumulated)
3rd column - scores

Я хотел создать новый файл, который будет суммировать каждые три выборки баллов, деленные на разницу во времени того же образца.

e.g. (123+22+22)/ (12-10) = 167/2 = 83.5
     (55+22+66)/(70-50) = 143/20 = 7.15

новый текстовый файл

83.5
7.15
.
.
.
n

пока у меня есть этот код:

fid=fopen('data.txt')
data = textscan(fid,'%*d %d %d')
time = (data{1})
score= (data{2})
for sample=1:length(score)
     ..... // I'm stucked here ..
end
....

Ответы [ 4 ]

7 голосов
/ 02 июня 2010

Если вы чувствуете себя авантюрным, вот векторизованное однострочное решение с использованием ACCUMARRAY (при условии, что вы уже прочитали файл в матричной переменной data, как это показали другие):

NUM = 3;
result = accumarray(reshape(repmat(1:size(data,1)/NUM,NUM,1),[],1),data(:,3)) ...
    ./ (data(NUM:NUM:end,2)-data(1:NUM:end,2))

Обратите внимание, что здесь количество выборок NUM=3 является параметром и может быть заменено любым другим значением.

Кроме того, прочитав ваш комментарий выше, если количество выборок не кратно этому числу (3), просто отбросьте оставшиеся образцы, выполнив это заранее:

data = data(1:fix(size(data,1)/NUM)*NUM,:);

Извините, вот намного проще: P

result  = sum(reshape(data(:,3), NUM, []))' ./ (data(NUM:NUM:end,2)-data(1:NUM:end,2));
2 голосов
/ 02 июня 2010
%# Easier to load with importdata
data = importdata('data.txt',' ',1);
%# Get the number of rows
n = size(data,1);
%# Column IDs
time = 2;score = 3;
%# The interval size (3 in your example)
interval = 3;
%# Pre-allocate space
new_data = zeros(numel(interval:interval:n),1);
%# For each new element in the new data
index = 1;
%# This will ignore elements past the closest (floor) multiple of 3 as requested
for i = interval:interval:n
    %# First and last elements in a batch
    a = i-interval+1;
    b = i;
    %# Compute the new data
    new_data(index) = sum( data(a:b,score) )/(data(b,time)-data(a,time));
    %# Increment
    index = index+1;
end
0 голосов
/ 02 июня 2010

Я предлагаю вам использовать функцию importdata(), чтобы получить данные в вашу переменную с именем data. Примерно так:

data = importdata('data.txt',' ', 1)

замените ' ' на разделитель, используемый вашим файлом, 1 указывает, что Matlab должен игнорировать 1 строку заголовка. Затем, чтобы вычислить ваши результаты, попробуйте следующее утверждение:

(data(1:3:end,3)+data(2:3:end,3)+data(3:3:end,3))./(data(3:3:end,2)-data(1:3:end,2))

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

Затем используйте save(), чтобы записать результаты обратно в файл.

PS Если вы обнаруживаете, что пишете циклы в Matlab, вы, вероятно, делаете что-то не так.

0 голосов
/ 02 июня 2010

Что бы это ни стоило, вот как вы собираетесь делать это в Python. Это, вероятно, адаптируется к Matlab.

import numpy
no, time, scores = numpy.loadtxt('data', skiprows=1).T

 # here I assume that your n is a multiple of 3! otherwise you have to adjust
sums = scores[::3]+scores[1::3]+scores[2::3]
dt = time[2::3]-time[::3]

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