我正在循環訪問一個大數據文件,並希望檢測每列中的變量類型,例如,如果它是一個Integer或一個浮點數等。 它工作得很好,但是,目前它還是非常基本的,我想補充一點。 到目前爲止,變量的聲明基於數據集的第二行。 (第一個是用作報頭) 這裏是代碼的開頭:循環訪問數據集並處理缺失值
#!/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;
現在我已經實施了小環。 問題是我不知道如何處理用NULL聲明的缺失值。目前,循環只是簡單地將變量「012」分配給變量$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++;
}
所以,我怎麼能實現另一個循環結構到現有的循環,這樣,每當我在一列中有NULL值的循環讀取在同一列的下一個值,並這樣做,直到他發現一個號碼或字。
我的數據的樣本是例如:
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。此時,循環識別出標有NULL的缺失值,並分配一個空值。
是的,那正是我想要做的。我有幾個數據集,我喜歡加載到數據庫中,我喜歡編寫一個perl腳本,它會自動檢測每個列的類型。因此我不必打開每個數據集並自己瀏覽這些列。 感謝您的幫助,我看看您的答案! – mropa 2010-02-03 17:18:45
@Sinan:Oesor建議使用Text :: CSV模塊。這是否會減少代碼量和推薦方法? – mropa 2010-02-03 18:24:20
@mropa無論您使用的是「Text :: CSV」,它與您的問題或多或少都是正交的。如果數據字段是製表符分隔的(而不是明顯的多個空格),並且這些字段可能包含帶引號的字符串,那麼使用它將使您的生活更輕鬆。它不會減少代碼量。我的代碼的重點是向您展示從字段內容中推導字段類型的邏輯。 – 2010-02-03 18:43:54