MATLAB:将年长变化分辨率的时间向量分为几个月

时间:2012-11-27 10:03:24

标签: matlab octave

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

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. 的字符串
  3. 使用strmatch('01-January-2008',DatesInChars)查找与2008年1月1日对应的行的索引
  4. 棘手的部分(?):TransformedData(:,i) = OriginalData(start:end)end = strmatch(1) - 1start = 1。然后在循环结束时将start更改为strmatch(1),然后再次运行第2步以查找下一个“起始索引”并将end更改为“新”strmatch(1)-1
  5. 快速优化它会很好;我将把它应用于大约200万次采样的数据。

    谢谢!

3 个答案:

答案 0 :(得分:3)

我会使用histc一个列表,列出一个月的最后几天作为第二个参数(注意:使用histc和两个返回函数)。 可以使用datenumdatevec轻松创建边缘列表。

这样你就不会对字符串进行操作而你应该很快。

编辑: 结果为简单数据结构的示例(包括来自@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)))

答案 1 :(得分: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

答案 2 :(得分:0)

我假设你有一个timeVals个Nx1双向量,它保存每个数据的时间值。假设data也是Nx1数组。我还假设datatimeVals按时间排序:也就是说,您拥有的样本是根据拍摄时间排序的。

怎么样:

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)。