2015-06-10 38 views
7

Kiedy eksportuję zestaw danych do formatu Stata przy użyciu PROC EXPORT, automatycznie rozszerza się SAS 9.4, dodając dodatkowy (pusty) bajt do każdej obserwacji każdej zmiennej łańcuchowej. Na przykład w zestawie danych:Jak zatrzymać SAS dodawanie dodatkowego pustego bajtu do każdej zmiennej łańcuchowej, gdy używam 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; 

Zmienne cust_id, category i status należy str1, str3 i str1 w końcowym pliku Stata, a tym samym zajmują 1 bajt, 3 bajty i 1 bajt , odpowiednio, dla każdej obserwacji. Jednak SAS automatycznie dodaje dodatkowy pusty bajt do każdej obserwacji, która rozszerza typy danych na typy danych str2, str4 i str2 w wyjściowym pliku Stata.

Jest to bardzo problematyczne, ponieważ to dodatkowy bajt dodany do każdy obserwacja każda zmienna ciąg. W przypadku dużych zestawów danych (mam kilka z ~ 530 milionami obserwacji i licznymi zmiennymi łańcuchowymi), można dodać kilka gigabajtów do eksportowanego pliku.

Gdy plik zostanie załadowany do Stata, komenda w Stata compress może automatycznie usunąć te puste bajty i kurczyć pliku, ale w przypadku dużych zbiorów danych, PROC EXPORT dodaje tak wiele dodatkowych bajtów do pliku, że nie zawsze mają wystarczająco pamięć do załadowania zbioru danych do Stata.

Czy istnieje sposób, aby zatrzymać SAS przed wypełnianiem zmiennych łańcuchowych w pierwszej kolejności? Kiedy eksportuję plik ze zmienną łańcuchową o jednym znaku (na przykład), chcę, aby ta zmienna była przechowywana jako zmienna łańcuchowa o jednym znaku w pliku wynikowym.

+0

Podejrzewam, że SAS dodaje terminator ciągów znaków, ale dlaczego nie mam pojęcia. – Joe

+1

Patrząc na dokumentację Staty, obsługuje terminator ciągu '\ 0' (dla operacji typu" Varchar "). Podejrzewam, że SAS po prostu kładzie to po * każdym * łańcuchu, jeśli muszę zgadywać.Zaleciłbym umieszczenie biletu pomocniczego przy wsparciu technicznym SAS; mogą one prawdopodobnie a) potwierdzić to i b) poinformować, czy istnieje obejście. Nie widzę jednego na podstawie krótkiego spojrzenia. – Joe

+1

A jeśli usłyszysz od SAS wsparcie techniczne - proszę dodać odpowiedź, niezależnie od otrzymywanych informacji, aby była dostępna dla innych użytkowników! – Joe

Odpowiedz

0

Jeśli jesteś skłonny zaakceptować płaską pliku odpowiedzi, mam wymyślić dość prosty sposób generowania jeden, który moim zdaniem ma właściwości, które wymagają:

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; 

to powinno działać jak jest , pod warunkiem, że całkowita przypisana długość wszystkich zmiennych w zestawie danych jest mniejsza niż 32767 (limit funkcji cat w środowisku kroku danych - dolny limit 200 znaków nie ma zastosowania, ponieważ jest to tylko wtedy, gdy używa się cat do utworzenia zmienna, której nie przypisano długości). Poza tym możesz zacząć napotkać problemy związane z przycinaniem. Obejście tego problemu polega na tym, że tylko cat razem z ograniczoną liczbą zmiennych naraz - proces ręczny, ale o wiele mniej pracochłonny niż wypowiadanie instrukcji put na podstawie długości wszystkich zmiennych, a w zależności od twoich danych może nigdy nie być wchodzić na górę.

Można również zejść z bardziej złożonej makrowej trasy, pobierając zmienne długości z funkcji vlength lub dictionary.columns i korzystając z nich oraz z nazw zmiennych, aby utworzyć wymagane oświadczenia (put).

+0

Podoba mi się twój pomysł, aby CAT sformatować linię, ale nie działa dla zmiennych numerycznych. Nie można liczyć na konwersję wartości liczbowych, aby uzyskać wartości o tej samej szerokości. Co sprawiłoby, że ta praca (jak sądzę) jest wersją funkcji CAT, która formatuje wszystkie vary za pomocą funkcji VVALUE. –

+0

@data_null_ - niestety nie istnieje taka hipotetyczna funkcja 'catv', a' vvalue' i podobne funkcje nie mogą być używane w ramach definicji 'proc fcmp', ponieważ są one ważne tylko w kroku danych. Niektóre tablice i logika makro będą potrzebne do konwersji liczbowych znaków na tekst o stałej szerokości. – user667489

1

W ten sposób można to zrobić przy użyciu istniejących funkcji.

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; 

Aby uniknąć użycia _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

'call vnext' i' vformatwx' to kawałki układanki, których mi brakowało - o wiele trudniej jest je złożyć bez nich. Jednak lepiej byłoby unikać użycia '_file_', ponieważ ogranicza to liczbę linii wyjściowych do 32767 znaków. – user667489

+0

Proponuję również użycie 'substr' zamiast' trim' dla końcowego etapu sprzątania, ponieważ pozwoli to uniknąć usunięcia wszelkich ważnych końcowych białych znaków z ostatniej zmiennej w źródłowym zestawie danych. – user667489

+0

Wyglądając teraz bardzo dobrze - jedyne usprawnienie, jakie zrobiłbym, to ustawienie 'lrecl = 1000000' lub podobnego, aby uniknąć długich linii wyjściowych obciętych do domyślnej długości. – user667489