【问题标题】:Text file processing with not precise enough timestamps时间戳不够精确的文本文件处理
【发布时间】:2013-08-08 00:37:20
【问题描述】:

我有两个文本文件,每个文件的第一列包含覆盖相同时间但不同速率的时间戳(第二个文件有更多样本)。但是,由于缺乏精确性,我收集的一些数据(位于这些文本文件的其他列中)在同一时间戳内会有所不同。

例如,这是第二个文件的摘录

Timestamp RobotYaw
1375448725 -2.183439
1375448725 -2.173082
1375448725 -2.169424

和第一个文件:

Timestamp State
1375448725 8
1375448725 9

我想要做的是创建一个输出文件,它是第二个文件的副本(有更多样本),但有一个额外的列指定当前状态(在第一个文件中给出)。然而,在上述情况下,由于时间戳不够精确,我不知道从状态 8 到 9 的变化何时发生,并且我选择了具有该时间戳的前半部分样本具有状态 8,而另一半状态 9。

我正在努力用 Perl 做到这一点。现在,它将始终为具有该时间戳的所有样本提供可用的最新状态 (9)...

这是当前程序的骨架,只保留了最小值(这应该打印第二个文件中的所有时间戳以及当前状态):

my $state = 1;

while ( my $ligne = <SECONDFILE> )
{
    my ( $timestamp , $junk ) = split ( /\s/ , $ligne ) ;

    while ( my $checkline = <FIRSTFILE> )
    {
        my ( $stateTimestamp , $stateJunk ) = split ( /\s/ , $checkline ) ;
        if ( int($timestamp) < int($stateTimestamp) )
        {
            last;
        }
        else
        {
            $state = $stateJunk;
        }
    }
    print OUTPUT $timestamp;
    print OUTPUT " ";
    print OUTPUT $state;
    print OUTPUT "\n";
}

您知道如何在一个时间戳内轻松处理这种任意的状态变化吗?由于很难解释,感谢您的阅读,如果您有任何问题,我很乐意进一步解释...

【问题讨论】:

  • 我认为你解释得很充分。给定多个样本和多个状态,您希望状态在样本中均匀分布。您需要指定如何处理边缘情况(例如,状态多于样本),以及当状态数不均分样本数时如何分配余数。
  • 其实这个问题只有在文件一的同一时间戳内发生状态变化时才会出现。在这种情况下,我确实选择在第二个文件中平均分配与该时间戳对应的样本的状态。在其他情况下,我不需要这样做,并且使用我的代码获得的状态是正确的。

标签: perl file loops timestamp


【解决方案1】:

要知道为哪个偏航时间戳打印哪个样本,我们需要将每个文件读入一个哈希值。我们可以计算有多少偏航时间戳和多少样本时间戳,这样我们就可以计算出要使用的样本。这应该会起作用:

    my %first_file;
    my %second_file;

    ### Store in a hash the unique timestamp|state values in order. 
    while ( my $checkline = <FIRSTFILE> ) {
        my ( $stateTimestamp, $statenum ) = split /\s/, $checkline;
        $first_file{$stateTimestamp}{'number'}++;
        my $count = $first_file{$stateTimestamp}{'number'};
        $first_file{$stateTimestamp}{$count} = $statenum;
    }

    ### Store timestamp and yaw values
    while ( my $ligne = <SECONDFILE> ) {
        my ( $timestamp , $robotyaw ) = split /\s/, $ligne;
        $second_file{$timestamp}{'number'}++;
        $second_file{$timestamp}{$robotyaw} = $second_file{$timestamp}{'number'};
    }

    ### MATH TIME IS FUN TIME. Don't forget to sort those hashes!
    foreach ( sort { $a <=> $b } keys %second_file ) {
        my $tstamp = $_;
        my $valhash = $second_file{$tstamp};
        my $change_count = round_up($second_file{$tstamp}{'number'} / $first_file{$tstamp}{'number'});
        foreach ( sort { ${$valhash}{$a} <=> ${$valhash}{$b} } keys %{$valhash} ) {
            my $yaw = $_;
            if ($yaw eq 'number') { next; }
            my $state_num = round_up(${$valhash}{$yaw} / $change_count);
            print OUTPUT "$tstamp $yaw ", $first_file{$tstamp}{$state_num}, "\n";
        }
    }    

    ### We could have used POSIX's ceil here instead  
    sub round_up {
        my $n = shift;
        return(($n == int($n)) ? $n : int($n + 1));
    }

你也应该习惯使用3参数打开文件句柄::

open my $firstfile, '<', 'first_file.txt' or die "Can't open first file: $!";
open my $output, '>', 'output_file.txt' or die "Can't open output file: $!";

这样它们的范围就被正确地确定了。

【讨论】:

    猜你喜欢
    • 2023-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多