1

我有以下格式的时间序列:

time       data value
733408.33  x1
733409.21  x2
733409.56  x3
etc..

数据运行时间约为 2008 年 1 月 1 日至 2010 年 12 月 31 日。我想将数据分成每月长度的列。

例如,第一列(2008 年 1 月)将包含相应的数据值:

(first 01-Jan-2008 data value):(data value immediately preceding the first 01-Feb-2008 value)

然后是第二列(2008 年 2 月):

(first 01-Feb-2008 data value):(data value immediately preceding the first 01-Mar-2008 value)

等等...

我一直在考虑但不知道如何组合的一些想法:

  1. 将所有序列时间数字(例如 733408.33)转换为字符串datestr
  2. 用于strmatch('01-January-2008',DatesInChars)查找对应于 2008 年 1 月 1 日的行的索引
  3. 棘手的部分(?)TransformedData(:,i) = OriginalData(start:end):?end = strmatch(1) - 1start = 1。然后start在循环结束时更改为strmatch(1),然后再次运行第 2 步以找到下一个“起始索引”并更改end为“新” strmatch(1)-1

优化速度会很好;我将把它应用到采样约 200 万次的数据上。

谢谢!

4

3 回答 3

3

我将使用histc一个列表作为第二个参数的月份最后几天的列表(注意:histc与两个返回函数一起使用)。datenum可以使用或轻松创建边缘列表datevec

这样你就不需要对字符串进行操作,而且你应该很快。

编辑:导致简单数据结构的示例(包括来自@Rody的一些代码):

% Generate some test times/data

tstart = datenum('01-Jan-2008');
tend   = datenum('31-Dec-2010');

tspan = tstart : tend;
tspan = tspan(:) + randn(size(tspan(:))); % add some noise so it's non-uniform

data = randn(size(tspan));

% Generate list of edge
edge = [];
for y = 2008:2010
    for m = 1:12
        edge = [edge datenum(y, m, 1)];
    end
end

% Histogram
[number, bin] = histc(tspan, edge);

% Setup of result
result = {};

for n = 1:length(edge)
    result{n}  = [tspan(bin == n), data(bin == n)];    
end

% Test
% 04-Aug-2008 17:25:20
datestr(result{8}(4,1))
tspan(data ==  result{8}(4,2))
datestr(tspan(data ==  result{8}(4,2)))
于 2012-11-27T10:36:09.287 回答
0

假设您已经对非等距日期数字进行了排序,那么这里的方法是将相关数据放在一个单元格数组中,以便每个条目对应下一个月,并且可以容纳不同数量的元素。

以下是如何非常有效地做到这一点:

% generate some test times/data

tstart = datenum('01-Jan-2008');
tend   = datenum('31-Dec-2010');

tspan = tstart : tend;
tspan = tspan(:) + randn(size(tspan(:))); % add some noise so it's non-uniform

data = randn(size(tspan));


% find month numbers
[~,M] = datevec(tspan);

% find indices where the month changes
inds = find(diff([0; M]));

% extract data in columns
sz = numel(inds)-1;
cols = cell(sz,1);
for ii = 1:sz-1
    cols{ii} = data( inds(ii) : inds(ii+1)-1 );
end

请注意,可能很难确定哪个条目cols属于哪个月、哪个年,因此以下是如何以更易于阅读的方式进行操作:

% change this line: 
[y,M] = datevec(tspan);

% and change these lines: 
cols = cell(sz,3);
for ii = 1:sz-1
    cols{ii,1} = data( inds(ii) : inds(ii+1)-1 );

    % also store the year and month 
    cols{ii,2} = y(inds(ii)); 
    cols{ii,3} = M(inds(ii)); 
end
于 2012-11-27T10:31:36.187 回答
0

我假设你有timeVals一个 Nx1 双向量来保存每个数据的时间值。假设data也是一个 Nx1 数组。我还假设data并按timeVals时间排序:也就是说,您拥有的样品是根据它们被采集的时间排序的。

怎么样:

subs = @(x,i) x(:,i);
months = subs( datevec(timeVals), 2 ); % extract the month of year as a number from the time
r = find( months ~= [months(2:end), months(end)+1] );
monthOfCell = months( r );
r( 2:end ) = r( 2:end ) - r( 1:end-1 );
dataByMonth = mat2cell( data', r ); % might need to transpose data or r here...
timeByMonth = mat2cell( timeVal', r );

运行此代码后,您将拥有一个元胞数组,dataByMonth每个元胞都包含与特定月份相关的所有数据。对应的单元格timeByMonth保存了各个月份数据的采样时间。最后,monthOfCell告诉您每个单元格的月份编号(1-12)是多少。

于 2012-11-27T11:46:22.203 回答