MATLAB: вычислите средний из каждого 1-минутного интервала временного ряда

У меня есть набор ряда времен каждый описанный двумя компонентами, вектор метки времени (в секундах) и вектор измеряемых значений. Вектор времени неоднороден (т.е. выбранный в неравных интервалах)

Я пытаюсь вычислить среднее / SD каждого 1-минутного интервала значений (возьмите интервал X минут, вычислите его среднее, возьмите следующий интервал...).

Моя текущая реализация использует циклы. Это - образец того, что я имею до сих пор:

t = (100:999)' + rand(900,1);       %' non-uniform time
x = 5*rand(900,1) + 10;             % x(i) is the value at time t(i)

interval = 1;         % 1-min interval
tt = ( floor(t(1)):interval*60:ceil(t(end)) )';  %' stopping points of each interval
N = length(tt)-1;

mu = zeros(N,1);
sd = zeros(N,1);

for i=1:N
    indices = ( tt(i) <= t & t < tt(i+1) ); % find t between tt(i) and tt(i+1)
    mu(i) = mean( x(indices) );
    sd(i) = std( x(indices) );
end

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

Любая справка приветствуется.


Спасибо всем за обратную связь.

Я исправил путь t сгенерирован, чтобы всегда монотонно увеличиться (отсортированный), это не было действительно проблемой..

Кроме того, я не мог заявить это ясно, но мое намерение состояло в том, чтобы иметь решение для любой длины интервала в минутах (1 минута была просто примером),

10
задан Shai 13 May 2013 в 19:46
поделиться

5 ответов

Единственный логичный решение кажется ...

Хорошо. Мне смешно, что для меня есть только одно логическое решение, но многие другие находят другие решения. Тем не менее, решение кажется простым. Учитывая векторы x и t, а также набор равноотстоящих точек разрыва tt,

t = sort((100:999)' + 3*rand(900,1));     % non-uniform time
x = 5*rand(900,1) + 10;             % x(i) is the value at time t(i)

tt = ( floor(t(1)):1*60:ceil(t(end)) )';

(обратите внимание, что я отсортировал t выше.)

Я бы сделал это в трех полностью векторизованных строках кода. Во-первых, если бы разрывы были произвольными и потенциально неравными по интервалам, я бы использовал histc, чтобы определить, в какие интервалы попадает ряд данных. Если они однородны, просто сделайте следующее:

int = 1 + floor((t - t(1))/60);

Опять же, если бы элементы t не были известны быть отсортированным, я бы использовал min (t) вместо t (1). Сделав это, используйте аккумулятор, чтобы уменьшить результаты до среднего и стандартного отклонения.

mu = accumarray(int,x,[],@mean);
sd = accumarray(int,x,[],@std);
11
ответ дан 3 December 2019 в 17:58
поделиться

Использование imagesavealpha () и прозрачного цвета bg должно сделать трюк...

На основе кода dfilkovi:

<?php
// Create a new true color image
$im = new imagecreatetruecolor(100, 100);

// Fill with alpha background
$alphabg = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $alphabg);

// Convert to palette-based with no dithering and 255 colors with alpha
imagetruecolortopalette($im, false, 255);
imagesavealpha($im, true);

// Save the image
imagepng($im, './paletteimage.png');
imagedestroy($im);
?>
-121--3702449-

Прост набор атрибут selected для опции:

$("#m").attr("selected", true);

Если вы также хотите отменить выбор других опций при выполнении этого действия, то самый простой вариант:

$("#m").attr("selected", true).siblings("option").removeAttr("selected");

Это не охватывает случай fieldsets. Чтобы охватить, что использовать что-то вроде:

$("#m").attr("selected", true).closest("select")
  .find("option").removeAttr("selected");
-121--4716211-

Вы можете вычислить индексы все сразу, используя bsxfun:

indices = ( bsxfun(@ge, t, tt(1:end-1)') & bsxfun(@lt, t, tt(2:end)') );

Это быстрее, чем закольцовывание, но требует сохранения их все одновременно (время и пространство компромисс)..

2
ответ дан 3 December 2019 в 17:58
поделиться

Вы можете попробовать создать массив ячеек и применить среднее и std через cellfun. Это на ~10% медленнее, чем ваше решение для 900 записей, но в ~10 раз быстрее для 90000 записей.

[t,sortIdx]=sort(t); %# we only need to sort in case t is not monotonously increasing
x = x(sortIdx);

tIdx = floor(t/60); %# convert seconds to minutes - can also convert to 5 mins by dividing by 300
tIdx = tIdx - min(tIdx) + 1; %# tIdx now is a vector of indices - i.e. it starts at 1, and should go like your iteration variable.

%# the next few commands are to count how many 1's 2's 3's etc are in tIdx
dt = [tIdx(2:end)-tIdx(1:end-1);1]; 
stepIdx = [0;find(dt>0)];
nIdx = stepIdx(2:end) - stepIdx(1:end-1); %# number of times each index appears

%# convert to cell array
xCell = mat2cell(x,nIdx,1);

%# use cellfun to calculate the mean and sd
mu(tIdx(stepIdx+1)) = cellfun(@mean,xCell); %# the indexing is like that since there may be missing steps
sd(tIdx(stepIdx+1)) = cellfun(@mean,xCell);

Примечание: мое решение не дает точно таких же результатов, как ваше, поскольку вы пропускаете несколько значений времени в конце (1:60:90 - это [1,61]), и поскольку начало интервала не совсем одинаково.

4
ответ дан 3 December 2019 в 17:58
поделиться

Вот способ, использующий двоичный поиск . Это в 6-10 раз быстрее для 9900 элементов и примерно в 64 раза быстрее для 99900 элементов. Было сложно получить надежное время, используя всего 900 элементов, поэтому я не уверен, что быстрее при таком размере. Он почти не использует дополнительную память, если вы рассматриваете возможность создания tx непосредственно из сгенерированных данных. Помимо этого, у него есть всего четыре дополнительных переменных с плавающей запятой (prevind, first, mid и last).

% Sort the data so that we can use binary search (takes O(N logN) time complexity).
tx = sortrows([t x]);

prevind = 1;

for i=1:N
    % First do a binary search to find the end of this section
    first = prevind;
    last = length(tx);
    while first ~= last
        mid = floor((first+last)/2);
        if tt(i+1) > tx(mid,1)
            first = mid+1;
        else
            last = mid;
        end;
    end;
    mu(i) = mean( tx(prevind:last-1,2) );
    sd(i) = std( tx(prevind:last-1,2) );
    prevind = last;
end;

Он использует все переменные, которые у вас были изначально. Я надеюсь, что это соответствует вашим потребностям. Это быстрее, потому что требуется O (log N), чтобы найти индексы с помощью двоичного поиска, но O (N), чтобы найти их так, как вы это делали.

3
ответ дан 3 December 2019 в 17:58
поделиться

Оговорка: я проработал это на бумаге, но еще не имел возможности проверить это "in silico"...

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

[t,sortIndex] = sort(t);  %# Sort the time points
x = x(sortIndex);         %# Sort the data values
interval = 60;            %# Interval size, in seconds

intervalIndex = floor((t-t(1))./interval)+1;  %# Collect t into intervals
nIntervals = max(intervalIndex);              %# The number of intervals
mu = zeros(nIntervals,1);                     %# Preallocate mu
sd = zeros(nIntervals,1);                     %# Preallocate sd

sumIndex = [find(diff(intervalIndex)) ...
            numel(intervalIndex)];  %# Find indices of the interval ends
n = diff([0 sumIndex]);             %# Number of samples per interval
xSum = cumsum(x);                   %# Cumulative sum of x
xSum = diff([0 xSum(sumIndex)]);    %# Sum per interval
xxSum = cumsum(x.^2);               %# Cumulative sum of x^2
xxSum = diff([0 xxSum(sumIndex)]);  %# Squared sum per interval

intervalIndex = intervalIndex(sumIndex);  %# Find index into mu and sd
mu(intervalIndex) = xSum./n;                             %# Compute mean
sd(intervalIndex) = sqrt((xxSum-xSum.*xSum./n)./(n-1));  %# Compute std dev

Приведенный выше код вычисляет стандартное отклонение, используя упрощение формулы, найденной на этой странице Википедии.

2
ответ дан 3 December 2019 в 17:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: