对于命令+插值:需要一些提示

时间:2012-06-07 07:24:33

标签: matlab datetime loops interpolation

我有一个矩阵A,其中包含三列:每日日期,价格和小时数 - 所有相同大小的向量 - 有多个价格与一天中的小时数相关联。

以下示例数据:

A_dates =          A_hours=        A_prices=
[20080902         [9.698           [24.09
20080902          9.891             24.59
200080902         10.251            24.60 
20080903          9.584             25.63
200080903         10.45             24.96
200080903         12.12             24.78
200080904          12.95            26.98 
20080904           13.569           26.78
20080904]          14.589]          25.41]
  • 请记住,我有大约两年的每日数据,每天约10 000个价格,几乎每天从上午9:30到下午16:00的每一分钟。实际上我的初始数据集时间是以毫秒为单位。然后我在几小时内转换了我的毫秒数。我有几个小时像14.589重复三次,有3种不同的价格。因此我做了以下事情:

    时间= [A_dates,A_hours,A_prices]; [timeinhr,价格] =合并器(时间,A_prices, '平均');其中timeinhr是矢量A_dates和A_hours

每个人说14.589小时的平均价格。 然后对于.25 .50 .75和整数小时的任何缺失时间 - 我希望插值。

对于每个日期,小时重复,我需要线性插入我没有的一些“通缉​​”时间的价格。但是,如果我的时间在我的专栏中重复,我当然不能使用命令interp1,因为我有多天。所以说:

%# here I want hours in 0.25unit increments (like 9.5hrs)
new_timeinhr = 0:0.25:max(A_hours));

day_hour = rem(new_timeinhour, 24);

%# Here I want only prices between 9.5hours and 16hours
new_timeinhr( day_hour <= 9.2 | day_hour >= 16.1 ) = [];  

然后我创建了一个独特的向量向量,并希望使用for和if命令来插入daily,然后将新价格一个接一个地堆叠在一个向量中:

days = unique(A_dates);
for j = 1:length(days);
    if A_dates == days(j)
       int_prices(j) = interp1(A_hours, A_prices, new_timeinhr);
    end;
end;

我的错误是:

  

In an assignment A(I) = B, the number of elements in B and I must be the same.

如何将int_prices(j)写入堆栈?

3 个答案:

答案 0 :(得分:3)

我建议您将输入转换为单个单调时间值。使用MATLAB datenum格式,它代表一天为1.这有很多优点:你得到了内置的MATLAB时间/日期函数,你可以通过{{1}得到格式标签很好地格式化为日期/时间},插值才有效。没有测试数据,我无法测试此代码,但这是一般的想法。

根据您的新信息,日期存储为20080902(我假设是yyyymmdd),我已经更新了初始转换代码。此外,由于A的布局导致混淆,我将把A的列称为向量datetickA_pricesA_hours

A_dates

我再说一遍,因为没有测试数据,我无法测试代码。我强烈建议您使用% This datenum vector matches A. I'm assuming they're already sorted by date and time At = datenum(num2str(A_dates), 'yyyymmdd') + datenum(0, 0, 0, A_hours, 0, 0); incr = datenum(0, 0, 0, 0.25, 0, 0); % 0.25 hour t = (At(1):incr:At(end)).'; % Full timespan of dataset, in 0.25 hour increments frac_hours = 24*(t - floor(t)); % Fractional hours into the day t_business_day = t((frac_hours > 9.4) & (frac_hours < 16.1)); % Time vector only where you want it P = interp1(At, A_prices, t_business_day); 返回从datenum转换为可读日期来测试日期转换代码。

答案 1 :(得分:1)

按照@Peter的建议,将天/小时转换为序列号数字绝对是可行的方法。基于他的代码(我已经投票),我在下面给出一个简单的例子。

首先,我首先创建一些类似于你所描述的假数据(还有一些缺失的部分):

%# three days in increments of 1 hour
dt = datenum(num2str((0:23)','2012-06-01 %02d:00'), 'yyyy-mm-dd HH:MM');   %#'
dt = [dt; dt+1; dt+2];

%# price data corresponding to each hour
p = cumsum(rand(size(dt))-0.5);

%# show plot
plot(dt, p, '.-'), datetick('x')
grid on, xlabel('Date/Time'), ylabel('Prices')

%# lets remove some rows as missing
idx = ( rand(size(dt)) < 0.1 );
hold on, plot(dt(idx), p(idx), 'ro'), hold off
legend({'prices','missing'})
dt(idx) = [];
p(idx) = [];

%# matrix same as yours: days,prices,hours
ymd = str2double( cellstr(datestr(dt,'yyyymmdd')) );
hr = str2double( cellstr(datestr(dt,'HH')) );
A = [ymd p hr];

%# let clear all variables except the data matrix A
clearvars -except A

接下来,我们以15分钟为增量在整个范围内插入价格数据:

%# convert days/hours to serial date number
dt = datenum(num2str(A(:,[1 3]),'%d %d'), 'yyyymmdd HH');

%# create a vector of 15 min increments
t_15min = (0:0.25:(24-0.25))';                  %#'
tt = datenum(0,0,0, t_15min,0,0);

%# offset serial date across all days
ymd = datenum(num2str(unique(A(:,1))), 'yyyymmdd');
tt = bsxfun(@plus, ymd', tt);                   %#'
tt = tt(:);

%# interpolate data at new datetimes
pp = interp1(dt, A(:,2), tt);

%# extract desired period of time from each day
idx = (9.5 <= t_15min & t_15min <= 16);
idx2 = bsxfun(@plus, find(idx), (0:numel(ymd)-1)*numel(t_15min));
P = pp(idx2(:));

%# plot interpolated data, and show extracted periods
figure, plot(tt, pp, '.-'), datetick('x'), hold on
plot([tt(idx2);nan(1,numel(ymd))], [pp(idx2);nan(1,numel(ymd))], 'r.-')
hold off, grid on, xlabel('Date/Time'), ylabel('Prices')
legend({'interpolated prices','period of 9:30 - 16:00'})

以下是显示原始和插值数据的两个图:

original_data interpolated_data

答案 2 :(得分:0)

我想我可能已经解决了这个问题:

new_timeinhr = 0:0.25:max(A(:,2));
day_hour = rem(new_timeinhr, 24);
new_timeinhr( day_hour <= 9.4 | day_hour >= 16.1 ) = [];

days=unique(data(:,1));
P=[];
for j=1:length(days);
    condition=A(:,1)==days(j);
    intprices = interp1(A(condition,2), A(condition,3), new_timeinhr);
    P=vertcat(P,intprices');
end;