【问题标题】:How to combine data according to timestamps?如何根据时间戳组合数据?
【发布时间】:2018-04-28 11:11:55
【问题描述】:

我有一系列文本文件,其中包含具有两个独立时间戳的数据,并且想找出给定时间所有值的总和。这些文件可能有不同数量的行,但总是三列:value timestamp1 timestamp2,带有诸如

之类的条目
6.2 1 4 
4.3 2 9 
7.2 3 10 

1.2 2 3 
0.3 3 9 
0.1 5 12 

下面是输出是如何形成的解释:

  1. 来自两个输入的时间戳被统一为一个唯一值向量(因此对于上面的示例{1,2,3}∪{2,3,5} -> {1,2,3,5}{4,9,10}∪{3,9,12} -> {3,4,9,10,12})。
  2. 对于每个唯一的时间戳,从每个输入中选择一个数据点,这样:

    • 如果查询到的时间戳低于可用的最小时间戳,则取第一个数据值。
    • 否则,取时间戳较低或相等的数据值。
  3. 将两个值相加并处理下一个唯一时间戳(如果可用)。

如果我使用timestamp1 将这个算法应用于上面的示例数据,我会得到:

7.4 1  %6.2+1.2
5.5 2  %4.3+0.3
7.5 3  %7.2+0.3
7.3 5  %7.2+0.1 

对于timestamp2

7.4 3  %6.2+1.2
7.4 4  %6.2+1.2
4.6 9  %4.3+0.3
7.5 10 %7.2+0.3
7.3 12 %7.2+0.1

我想我需要对time series 做点什么,因此我已经有了以下转换器代码:

logs = dir('log1/*.txt');
k=1
for log = logs' 

    t{k}=timeseries(load(log.name))
    k=k+1
end

我猜下一步应该是sum(t) 之类的东西,但这不起作用。有人知道如何像上面那样组合它们吗?

对于任何感兴趣的人,这些是 CPU 和实时时间戳(自算法开始以来),用于衡量算法的性能。

【问题讨论】:

  • 我不明白你是如何从两组三个时间戳变成四个或五个时间戳的,以及第二列和第三列发生了什么。
  • @Steve 最终设置的时间戳将与输入数据中唯一时间戳的数量相同。第一列也是值而不是时间戳。
  • 好的,我看看你在新数据中添加了哪些行;我不明白为什么 combined relative to timestamp1 的第一行是6.2 + 1.21.2 不是来自旧数据),而最后一行是7.2 + 0.1(与一个旧数据相结合)点,但不是全部)。
  • @Steve 第一个是因为我需要第一个数据集的值,而丢失数据集的第一个数据点必须这样做,第二个对我来说并不奇怪,在时刻 5,我们有两个数据集的最后一行。
  • @Steve the 5 来自第二个数据集,特别是这一行 0.1 5 12

标签: matlab indexing sum timestamp benchmarking


【解决方案1】:

我一直在考虑这个问题,最后想出了下面的解决方案。虽然它在概念上与Steve's answer 没有什么不同,但至少它是矢量化的:)

%% Preparations:
%{
In the same folder:

data1.txt:
6.2 1 4
4.3 2 9
7.2 3 10

data2.txt:
1.2 2 3
0.3 3 9
0.1 5 12
%}

function out = q47303825(fname1,fname2,whichStamp)
%% Input handling:
if nargin < 3
  whichStamp = 1;
end
if nargin == 0
  fname1 = 'data1.txt';
  fname2 = 'data2.txt';
end
%% Reading the data :
d1 = dlmread(fname1,' ');
d2 = dlmread(fname2,' ');
%% Preallocation:
out = union(d1(:,whichStamp+1), d2(:,whichStamp+1)) .* [NaN,1];
%% Modifying the data slightly to allow vectorization:
d1 = [d1(1), -Inf, -Inf; d1; d1(size(d1,1)), +Inf, +Inf];
d2 = [d2(1), -Inf, -Inf; d2; d2(size(d2,1)), +Inf, +Inf];
%% Find indices:
[~,I1] = min(d1(:,whichStamp+1) <= out(:,2).',[],1);
[~,I2] = min(d2(:,whichStamp+1) <= out(:,2).',[],1);
I1 = I1-1; I2 = I2-1;
%% Generate final output:
out(:,1) = d1(I1) + d2(I2);

【讨论】:

    【解决方案2】:

    在我看来,两个不同的时间戳是一个红鲱鱼 - 您可以为一个时间戳定义您的问题,而忽略另一个。

    据我了解,您希望:

    • 考虑出现在两个数据集中的所有时间(这里,只考虑 timestamp1,是 [1,2,3,5]
    • 使用最近邻对两个列表中的任何缺失数据点进行插值/外推:(第一个数据集中缺少5,第二个数据集中缺少1
    • 返回填充缺失点的值的总和。

    没有读取操作,我是这样看待你的处理的:

    times1 = [1,2,3];
    values1 = [6.2, 4.3, 7.2];
    
    times2 = [2, 3, 5];
    values2 = [1.2, 0.3, 0.1];
    
    all_times = union(times1, times2)';
    values1_interp = interp1(times1, values1, all_times, 'nearest', 'extrap');
    values2_interp = interp1(times2, values2, all_times, 'nearest', 'extrap');
    v_sum = values1_interp + values2_interp;
    

    可以看到结果:

    >> table(v_sum, all_times)
    
    ans = 
    
        v_sum    all_times
        _____    _________
    
        7.4      1        
        5.5      2        
        7.5      3        
        7.3      5     
    

    如果我们要使用

    times1 = [4, 9, 10];
    times2 = [3, 9, 12];
    

    那么我们会得到

    >> table(v_sum, all_times)
    
    ans = 
    
        v_sum    all_times
        _____    _________
    
        7.4       3       
        7.4       4       
        4.6       9       
        7.5      10       
        7.3      12  
    

    编辑:OP's comment,我们不想要最近的邻居,而是最近的邻居,但如果我们是,我们使用第一点在我们的时代开始之前推断一个时间(例如,当我们的times1[2,3,4] 时,推断values1 到时间1):为此,您可以使用类似

    function [vq] = interp_left(x, v, xq)
    %INTERP_LEFT Interpolate to the left-nearest point
    % x must be sorted.
    vq = nan(size(xq));
    for ii = 1:length(xq)
      % Find the index in x nearest to xq, only considering smaller x
      [~,jj] = max(x(x<=xq(ii)));
      % Special case, there are no smaller x; extrapolate using [x(1),v(1)]
      if isempty(jj)
        vq(ii) = v(1);
      else
        vq(ii) = v(jj);
      end % if
    end % for
    end % function
    

    然后使用

    times1 = [1,2,3];
    values1 = [6.2, 4.3, 7.2];
    
    times2 = [2, 3, 5];
    values2 = [1.2, 0.3, 0.1];
    
    all_times = union(times1, times2)';
    values1_interp = interp_left(times1, values1, all_times);
    values2_interp = interp_left(times2, values2, all_times);
    v_sum = values1_interp + values2_interp;
    

    【讨论】:

    • 几乎,我正在寻找前一个数据点,而不是最近的数据点(除了第一个不存在前一个数据点的数据点)。
    • @Thijser 我已经添加了具有您所描述行为的插值函数。
    • 谢谢,我明天看看,今天就写完了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 2021-10-02
    相关资源
    最近更新 更多