2015-02-05 6 views
5

나는 세미콜론을 구분 기호로 사용하고 쉼표를 소수 구분 기호로 사용하는 많은 CSV 파일을 갖고있다. 지금까지 proc import를 사용하여 SAS로 이러한 파일을 가져 오는 방법을 찾지 못했습니다. 또는 변수 이름을 수동으로 사용하지 않고 다른 자동화 된 방식으로 파일을 가져올 수 없었습니다.구분 기호가 ";"인 CSV 파일을 가져 오는 방법 및 소수점 구분 기호 ","로 SAS?

하면 일부 샘플 데이터 생성 :

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

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

임포트 코드 : 가져에서 350.58에 대응 같은 350,58 변수 "AMOUNT"값 (이후

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

US 형식)은 SAS에서 35,058 (의미는 서른 개임)을 나타낼 것입니다 (그리고 독일 EXCEL로 다시 가져온 후 35.058,00처럼 보일 것입니다).

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

내가 (구분 기호의 사양 유사) CVS-수입에 대한 소수 구분을 정의하는 간단한 방법이 있는지 궁금 : 간단하지만 더러운 해결 방법은 다음과 같이 될 것이다. .. 또는 내 다른 해결 방법에 비해 다른 "청소기"솔루션. 미리 감사드립니다.

+0

35.358,00,이 문자열 변수처럼 보이는
substitute_commasep.perl는 펄 프로그램

펄 코드의 이름입니다. 35,058,00입니까? –

+0

감사합니다. 나는 내 게시물을 편집했습니다! – Joz

답변

5

기술적으로는 dbms=dlm이 아닌 dbms=csv을 사용해야합니다. CSV는 "쉼표로 구분 된 값"을 의미하고 DLM은 "구분 된"을 의미하며 올바른 값입니다.

SAS를 PROC IMPORT을 통해 쉼표로 읽어들이는 직접적인 방법은 없을 것이라고 생각합니다. 데이터를 읽을 때 NUMXw.d 정보를 사용하도록 SAS에 지시해야하며 SAS에서 강제로 설정하는 방법이 없습니다. (이 쉼표, NLDECSEPARATOR출력에 대한 옵션입니다,하지만 난 여기에 작동 할 수 있다고 생각하지 않습니다.)

가장 좋은 방법 중 하나는 데이터 단계 코드를 직접 작성하거나 PROC IMPORT을 실행하는 것입니다의로 이동 로그하고, 읽은 코드를 프로그램에 복사/붙여 넣기하십시오. read-in 레코드 각각에 대해 :NUMX10. 또는 필드의 적절한 최대 너비가 무엇이든을 추가하십시오. 결국 다음과 같이 보일 것입니다 :

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

또한 많은 정보 및 형식 코드를 생성합니다. read-in에 informat를 추가하는 대신 BEST. 대신 informats를 NUMX10.으로 번갈아 전환 할 수 있습니다. 날짜 필드가없는 한 정보를 삭제할 수도 있습니다.

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

+0

SAS가 처리 할 수 ​​있고 Joe가 어떻게 당신을 보여줬습니까? PROC 가져 오기는 기본 파일을 읽는 유틸리티 일뿐입니다. 파일을 읽는 데이터 단계를 작성합니다. 파일이 "기본"이라는 아이디어에 부합하지 않으면 데이터 단계를 작성해야합니다. – DomPazz

+0

편집 : SAS가 이러한 일상적인 문제를 자동화 된 방식으로 처리 할 수 ​​없다고 생각하기가 어렵습니다. 하지만 저는 현재 Joe의 솔루션을 사용하고 있습니다. 다시 한 번 감사드립니다. – Joz

0

가장 좋은 방법은 하나 직접 데이터 단계의 코드를 작성하거나, 에게 PROC 가져 오기를 실행 로그로 이동 및 복사/ 프로그램에 코드 읽기를 붙여

이것은 단점이 있습니다. csv 파일의 구조에 변경이있는 경우 (예 : 변경된 열 순서) SAS 프로그램에서 코드를 변경해야합니다.
따라서 쉼표를 점으로 대체하고 수정 된 입력을 SAS로 전달하여 입력을 변경하는 것이 더 안전합니다.

첫 번째 아이디어는 perl 프로그램을 사용하여 수정 한 입력을 읽기 위해 파이프가있는 파일 이름을 SAS에 사용하는 것이 었습니다.
PROC 가져 오기에 SAS 제한 사항이 있습니다. IMPORT 절차는 DISK를 제외한 FILENAME 문의 장치 유형이나 액세스 방법을 지원하지 않습니다.
그래서 조정 된 입력으로 디스크에 작업 파일을 만들어야합니다.

CVS_PP 패키지를 사용하여 CSV 파일을 읽었습니다.
testdata.csv에는 읽을 CSV 데이터가 들어 있습니다.

# 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; 
관련 문제