2015-02-05 112 views
5

I`ve了(和將接受在未來)使用分號作爲分隔符和逗號作爲小數點分隔符許多CSV文件。 到目前爲止,我無法找到如何將這些文件導入SAS使用PROC進口 - 或任何其他自動方式,無需手動與變量名亂搞。如何將帶分隔符的CSV文件導入爲「;」和小數點分隔符爲「,」到SAS?

創建一些示例數據:

%let filename = %sysfunc(pathname(work))\sap.csv; 

data _null_; 
    file "&filename"; 
    put 'a;b'; 
    put '12345,11;67890,66'; 
run; 

導入代碼:

proc import out = sap01 
datafile= "&filename" 
dbms = dlm; 
delimiter = ";"; 
GETNAMES = YES; 
run; 

導入爲變量「量」如350,58(一個值,其對應於350.58在後美國格式)在SAS中看起來像35,058(意思是三十五萬...)並且在再出口到德國EXCEL之後,它看起來像35.058,00)。 一個簡單而骯髒的解決方法是以下幾點:

data sap02; set sap01; 
AMOUNT = AMOUNT/100; 
format AMOUNT best15.2; 
run; 

我不知道是否有一個簡單的方法來定義的CVS導入小數點分隔符(類似於分隔符的規格)。 ..或任何其他「清潔」解決方案相比,我的解決方法。 非常感謝提前!

+0

35.358,00,這看起來像一個字符串變量。是35,058,00嗎? – 2015-02-05 15:34:12

+0

謝謝,我編輯了我的帖子! – Joz 2015-02-05 16:43:15

回答

5

你應該在技術上使用dbms=dlmdbms=csv,儘管它理出頭緒。 CSV意味着「逗號分隔值」,而DLM意味着「分隔」,這在這裏是正確的。

我不認爲有一個直接的方式,使SAS通過PROC IMPORT用逗號讀入。你需要告訴SAS在數據讀取時使用的NUMXw.d了信息,我不明白的方式來強制SAS該設置。 (有用於輸出用逗號,NLDECSEPARATOR一種選擇,但我不認爲在這裏工作。)

您最好的選擇是要麼自己寫數據的步驟的代碼,或者運行PROC IMPORT,轉到記錄並將讀入的代碼複製/粘貼到程序中;那麼對於每個讀入記錄添加:NUMX10.或該字段的適當最大寬度。它最終會看起來像這樣:

data want; 
    infile "whatever.txt" dlm=';' lrecl=32767 missover; 
    input 
    firstnumvar :NUMX10. 
    secondnumvar :NUMX10. 
    thirdnumvar :NUMX10. 
    fourthnumvar :NUMX10. 
    charvar :$15. 
    charvar2 :$15. 
    ; 
run; 

它也會生成大量的信息和格式代碼;您可以將informats交替轉換爲NUMX10.而不是BEST.,而不是添加了信息的讀入的。除非您有日期字段,否則您也可以刪除信息。

data want; 
    infile "whatever.txt" dlm=';' lrecl=32767 missover; 
    informat firstnumvar secondnumvar thirdnumvar fourthnumvar NUMX10.; 
    informat charvar $15.; 
    format firstnumvar secondnumvar thirdnumvar fourthnumvar BEST12.; 
    format charvar $15.; 
    input 
    firstnumvar 
    secondnumvar 
    thirdnumvar 
    fourthnumvar 
    charvar $ 
    ; 
run; 
+0

謝謝你的幫助,喬!我剛剛編輯過我的帖子,關於dbms選項。你的其他想法很有意思,但仍然是解決方法。很難相信SAS不能處理這樣一個普通的問題。但我擔心你可能是對的...... – Joz 2015-02-05 15:32:09

+0

SAS可以處理它,喬向你展示瞭如何。 PROC IMPORT不過是一種在基本文件中讀取的實用程序 - 它會寫入一個Data Step來讀取文件。如果該文件不符合其「基本」的想法,那麼您需要編寫數據步驟。 – DomPazz 2015-02-05 16:19:15

+0

編輯:很難相信SAS不能自動處理這樣一個世俗的問題。但我目前正在與喬的解決方案合作,再次感謝! – Joz 2015-02-05 16:28:56

0

您最好的選擇是要麼自己寫數據的步驟的代碼,或運行 的PROC IMPORT,轉到日誌和複製/代碼讀取粘貼到 程序

這有一個缺點。如果csv文件的結構發生變化,例如更改了列順序,則必須更改SAS程序中的代碼。
因此,更改輸入更安全,在數字字段中用點替換逗號並將修改後的輸入傳遞給SAS。

第一個想法是爲此使用perl程序,然後在SAS中使用帶有管道的文件名來讀取修改的輸入。
不幸的是,proc導入中存在一個SAS限制:IMPORT過程不支持除DISK外的FILENAME語句的設備類型或訪問方法。
所以必須在調整後的輸入上創建磁盤上的工作文件。

我使用CVS_PP包來讀取csv文件。
testdata.csv包含要讀取的csv數據。
substitute_commasep.perl是perl程序

Perl代碼的名稱:

# use lib "/........"; # specifiy, if Text::CSV_PP is locally installed. Otherwise error message: Can't locate Text/CSV_PP.pm in ....; 
use Text::CSV_PP; 
use strict; 
    my $csv = Text::CSV_PP->new({ binary => 1 
           ,sep_char => ';' 
          }) or die "Error creating CSV object: ".Text::CSV_PP->error_diag(); 
    open my $fhi, "<", "$ARGV[0]" or die "Error reading CSV file: $!"; 
    while (my $colref = $csv->getline($fhi)) { 
     foreach (@$colref) {    # analyze each column value 
     s/,/\./ if /^\s*[\d,]*\s*$/; # substitute, if the field contains only numbers and , 
     } 
     $csv->print(\*STDOUT, $colref); 
     print "\n"; 
    } 
    $csv->eof or $csv->error_diag(); 
    close $fhi; 

SAS代碼:

filename readcsv pipe "perl substitute_commasep.perl testdata.csv"; 
filename dummy "dummy.csv"; 
data _null_; 
    infile readcsv; 
    file dummy; 
    input; 
    put _infile_; 
run; 
proc import datafile=dummy 
    out=data1 
    dbms=dlm 
    replace; 
    delimiter=';'; 
    getnames=yes; 
    guessingrows=32767; 
run; 
相關問題