代码之家  ›  专栏  ›  技术社区  ›  mropa

循环遍历数据集并处理缺少的值

  •  0
  • mropa  · 技术社区  · 15 年前

    我在一个大数据文件中循环,喜欢检测每列中变量的类型, 如果它是一个加强器或浮子等。 它工作得非常好,但是,目前它仍然是非常基本的,我想补充另一个想法。 到目前为止,变量的声明是基于数据集的第二行。 (第一个用作标题。) 以下是代码的开头:

    #!/usr/bin/perl
    
    use warnings;
    use diagnostics;
    use Getopt::Std;
    
    getopts("i:s:t:") or die "bad options: $!";
    
    if($opt_i) {
    open INFILE, "< $opt_i";
    chomp($headerline = <INFILE>);
    $second = <INFILE>;
    } else {
    die "the input file has to be given\n";
    }
    
    if($opt_t) {
    $tablename = $opt_t;
    } else {
    $tablename = $opt_i;
    $tablename =~ s/\.\w+//;
    }
    
    if($opt_s) {
    $sep = $opt_s;
    } else {
    $sep = ",";
    }
    
    $headerline =~ s/\"//g;
    $headerline =~ s/\./\_/g;
    @header = split/$sep/, $headerline;
    
    $second =~ s/\"//g ;
    @second = split/$sep/, $second;
    @terms = split/$sep/, $second;
    @types = split/$sep/, $second;
    

    $vartype[$j] .

    $j = 0;
    while($j <= $#second) {
    if ($types[$j] =~ /NULL/) {
    $vartype[$j] = "";
    } elsif($types[$j] =~ /[A-Za-z]/) {
    $vartype[$j] = "varchar";
    } elsif ($types[$j] =~ /\./) {
    $vartype[$j] = "double";
    } else {
    $vartype[$j] = "int";
    }
    $j++;
    }
    

    那么,我如何在现有循环中实现另一个循环结构,这样每当我在一列中有一个空值时,循环就会读取同一列中的下一个值,直到找到一个数字或一个单词为止。

    我的数据样本如下:

    Country.Name        Time.Name  AG.LND.AGRI.ZS   NY.GDP.MKTP.CD   NE.IMP.GNFS.ZS
    Brunei Darussalam   1960       NULL             1139121335.16    3.46
    Brunei Darussalam   1960       NULL             1677595756.64    0.9
    Brunei Darussalam   1960       NULL             1488339328.59    4.19
    Brunei Darussalam   1961       3.98             1869828587.8     3.14
    Brunei Darussalam   1961       3.98             2346769422.22    3.38
    Brunei Darussalam   1961       3.98             2363109706.3     3.17
    

    如前所述,for循环仅使用第二行来决定变量的类型。

    现在我想实现另一个循环,例如在第三列(AG.LND.AGRI.ZS)中,他遍历该列,直到检测到第一个实值,在本例中为3.98。识别空值,并在标记为空的时刻分配一个空值。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Sinan Ünür    15 年前

    NULL ,如果已确定字段类型,则跳过该字段,并在确定所有字段类型后退出循环。

    #!/usr/bin/perl
    
    use strict; use warnings;
    use Scalar::Util qw(looks_like_number);
    
    my @names = split ' ', scalar <DATA>;
    my @types;
    
    while ( <DATA> ) {
        chomp;
        my @values = split / {2,}/;
    
        for my $i ( 0 .. $#values ) {
            next if defined $types[$i];
            my $val = $values[$i];
            next if $val eq 'NULL';
            if ( $val =~ /^[0-9]+\z/ ) {
                $types[$i] = 'int';
            }
            elsif ( $val =~ /^[0-9.]+\z/
                    and looks_like_number($val) ) {
                $types[$i] = 'double';
            }
            else {
                $types[$i] = 'varchar';
            }
        }
        last unless grep { not defined } @types;
    }
    
    print "$_\n" for @types;
    
    
    __DATA__
    Country.Name        Time.Name  AG.LND.AGRI.ZS   NY.GDP.MKTP.CD   NE.IMP.GNFS.ZS
    Brunei Darussalam   1960       NULL             1139121335.16    3.46
    Brunei Darussalam   1960       NULL             1677595756.64    0.9
    Brunei Darussalam   1960       NULL             1488339328.59    4.19
    Brunei Darussalam   1961       3.98             1869828587.8     3.14
    Brunei Darussalam   1961       3.98             2346769422.22    3.38
    Brunei Darussalam   1961       3.98             2363109706.3     3.17
    

    输出:

    varchar
    int
    double
    double
    double
        2
  •  2
  •   Oesor    15 年前

    for my $variable (@types) {
      if ($variable =~ /NULL/) {
        push(@vartype, undef);
      }
      elsif ($variable =~ /[A-Za-z]/) {
        push(@vartype, "varchar");
      }
      elsif ($variable =~ /\./) {
        push(@vartype, "double";
      }
      else {
        push(@vartype, "int");
      }
    }
    

    不过,对于perl,实际上应该将相关数据存储在散列数据结构中。比如:

    my $data = [ { value => 'NULL', type => undef },
                 { value => 'a string', type => 'varchar' },
                 { value => 9.5, type => 'double'},
                 { value => 30, type => 'int'},
               ];