2015-06-10 12 views
7

Khi tôi xuất tập dữ liệu sang định dạng Stata bằng cách sử dụng PROC EXPORT, SAS 9.4 tự động mở rộng thêm byte thừa (trống) vào mọi quan sát của mọi biến chuỗi. Ví dụ, trong tập dữ liệu này:Làm cách nào để ngăn không cho SAS thêm một byte trống thừa vào mọi biến chuỗi khi tôi sử dụng PROC EXPORT?

data test1; 
    input cust_id $ 1 
      month  3-8 
      category $ 10-12 
      status $ 14-14 
; 
datalines; 
A 200003 ABC C 
A 200004 DEF C 
A 200006 XYZ 3 
B 199910 ASD X 
B 199912 ASD C 
; 
quit; 

proc export data = test1 
    file = "test1.dta" 
    dbms = stata replace; 
quit; 

các biến cust_id, category, và status nên str1, str3, và str1 trong file Stata thức, và do đó mất 1 byte, 3 byte và 1 byte , tương ứng, cho mọi quan sát. Tuy nhiên, SAS tự động thêm một byte trống bổ sung vào mỗi quan sát, mở rộng các loại dữ liệu của chúng thành các loại dữ liệu str2, str4str2 trong tệp Stata được xuất ra.

Điều này cực kỳ có vấn đề vì đó là một byte phụ được thêm vào mỗi quan sát mỗi biến số chuỗi. Đối với các tập dữ liệu lớn (tôi có một số với ~ 530 triệu quan sát và nhiều biến chuỗi), điều này có thể thêm vài gigabyte vào tệp đã xuất. Sau khi tệp được tải vào Stata, lệnh compress trong Stata có thể tự động xóa các byte trống này và thu nhỏ tệp, nhưng đối với các tập dữ liệu lớn, PROC EXPORT thêm rất nhiều byte vào tệp mà tôi không luôn có đủ bộ nhớ để tải bộ dữ liệu vào Stata ở nơi đầu tiên.

Có cách nào để ngăn SAS lồng các biến chuỗi vào vị trí đầu tiên không? Khi tôi xuất một tệp với một biến chuỗi ký tự (ví dụ), tôi muốn biến đó được lưu dưới dạng một biến chuỗi ký tự trong tệp đầu ra.

+0

Tôi nghi ngờ SAS đang thêm một trình kết thúc chuỗi, mặc dù tại sao tôi không có đầu mối. – Joe

+1

Nhìn vào tài liệu Stata, nó hỗ trợ terminator chuỗi '\ 0' (cho hoạt động kiểu" Varchar "). Tôi nghi ngờ SAS chỉ đặt sau chuỗi * mỗi *, nếu tôi phải đoán.Tôi khuyên bạn nên đặt một vé hỗ trợ với sự hỗ trợ kỹ thuật của SAS; họ có thể có khả năng a) xác nhận điều này và b) cho bạn biết nếu có cách giải quyết khác. Tôi không nhìn thấy một dựa trên một cái nhìn ngắn gọn. – Joe

+1

Và nếu bạn nhận được phản hồi từ sự hỗ trợ kỹ thuật của SAS - vui lòng thêm câu trả lời với bất kỳ thông tin nào bạn nhận được, vì vậy nó có sẵn cho những người tìm kiếm khác! – Joe

Trả lời

0

Nếu bạn sẵn sàng chấp nhận một câu trả lời tập tin phẳng, tôi đã tìm ra một cách khá đơn giản tạo ra một mà tôi nghĩ rằng có các thuộc tính bạn cần:

data test1; 
    input cust_id $ 1 
      month  3-8 
      category $ 10-12 
      status $ 14-14 
; 
datalines; 
A 200003 ABC C 
A 200004 DEF C 
A 200006 XYZ 3 
B 199910 SD X 
B 199912 D C 
; 
run; 

data _null_; 
file "/folders/myfolders/test.txt"; 
set test1; 
put @; 
_FILE_ = cat(of _all_); 
put; 
run; 

/* Print contents of the file to the log (for debugging only)*/ 
data _null_; 
infile "/folders/myfolders/test.txt"; 
input; 
put _infile_; 
run; 

này nên làm việc như nó vốn có , với điều kiện tổng chiều dài được gán của tất cả các biến trong tập dữ liệu của bạn nhỏ hơn 32767 (giới hạn của hàm cat trong môi trường bước dữ liệu - giới hạn ký tự dưới 200 không áp dụng, vì chỉ khi bạn sử dụng cat để tạo biến chưa được gán độ dài). Ngoài ra, bạn có thể bắt đầu chạy vào các vấn đề cắt ngắn. Một giải pháp khác xảy ra là chỉ có cat cùng một số lượng giới hạn các biến cùng một lúc - một quy trình thủ công, nhưng ít tốn kém hơn việc viết các câu lệnh đặt dựa trên độ dài của tất cả các biến và tùy thuộc vào dữ liệu của bạn. đi lên. Ngoài ra, bạn có thể đi xuống một tuyến đường macro phức tạp hơn, nhận được độ dài biến đổi từ một trong hai hàm vlength hoặc dictionary.columns và sử dụng các tên đó cộng với tên biến để xây dựng các câu lệnh put được yêu cầu.

+0

Tôi thích ý tưởng của bạn về việc CAT định dạng đường nhưng nó không hoạt động đối với các biến số. Bạn không thể dựa vào số để chuyển đổi ký tự để tạo ra các giá trị có cùng chiều rộng. Điều gì sẽ làm cho công việc này (tôi nghĩ) là một phiên bản chức năng CAT định dạng tất cả các vars bằng cách sử dụng hàm VVALUE. –

+0

@data_null_ - tiếc là không có hàm 'catv' giả định tồn tại, và' vvalue' và các hàm tương tự không thể được sử dụng trong định nghĩa 'proc fcmp' vì chúng chỉ hợp lệ trong một bước dữ liệu. Một số mảng và logic vĩ mô sẽ là cần thiết để chuyển đổi các vars số thành văn bản chiều rộng cố định. – user667489

1

Đây là cách bạn có thể thực hiện bằng các chức năng hiện có.

filename FT41F001 temp; 
data _null_; 
    file FT41F001; 
    set test1; 
    put 256*' ' @; 
    __s=1; 
    do while(1); 
     length __name $32.; 
     call vnext(__name); 
     if missing(__name) or __name eq: '__' then leave; 
     substr(_FILE_,__s) = vvaluex(__name); 
     putlog _all_; 
     __s = sum(__s,vformatwx(__name)); 
     end; 
    _file_ = trim(_file_); 
    put; 
    format month f6.; 
    run; 

Để tránh sử dụng _FILE_;

data _null_; 
    file FT41F001; 
    set test1; 
    __s=1; 
    do while(1); 
     length __name $32. __value $128 __w 8; 
     call vnext(__name); 
     if missing(__name) or __name eq: '__' then leave; 
     __value = vvaluex(__name); 
     __w = vformatwx(__name); 
     put __value $varying128. __w @; 
     end; 
    put; 
    format month f6.; 
    run; 
+0

'gọi vnext' và' vformatwx' là những mảnh ghép mà tôi đã bỏ lỡ - khó có thể đặt mọi thứ lại với nhau một cách gọn gàng mà không có chúng. Tuy nhiên, sẽ tốt hơn nếu tránh sử dụng '_file_' vì điều này giới hạn mỗi dòng đầu ra thành 32767 ký tự. – user667489

+0

Tôi cũng khuyên bạn nên sử dụng 'substr' thay vì' trim' cho bước cuối cùng, vì điều này sẽ tránh xóa bất kỳ khoảng trống cuối hợp lệ nào từ biến cuối cùng trong tập dữ liệu nguồn. – user667489

+0

Tìm kiếm rất tốt ngay bây giờ - tinh chỉnh duy nhất tôi muốn thực hiện sẽ là đặt 'lrecl = 1000000' hoặc tương tự để tránh các dòng đầu ra dài bị cắt ngắn thành độ dài mặc định. – user667489

Các vấn đề liên quan