2015-06-10 15 views
7

Quando esporto un set di dati in formato Stata utilizzando PROC EXPORT, SAS 9.4 si espande automaticamente aggiunge un byte aggiuntivo (vuoto) a ogni osservazione di ogni variabile stringa. Ad esempio, in questo insieme di dati:Come posso impedire a SAS di aggiungere un byte vuoto extra a ogni variabile stringa quando utilizzo 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; 

variabili cust_id, category e status dovrebbe essere str1, str3, e str1 nel file finale Stata, e quindi occupano 1 byte, 3 byte, ed 1 byte , rispettivamente, per ogni osservazione. Tuttavia, SAS aggiunge automaticamente un byte extra vuoto a ciascuna osservazione, che espande i loro tipi di dati al tipo di dati str2, str4 e str2 nel file Stata emesso.

questo è estremamente problematico perché è un byte extra aggiunto al ogni osservazione di tutte le variabili stringa. Per dataset di grandi dimensioni (ne ho alcuni con ~ 530 milioni di osservazioni e numerose variabili stringa), questo può aggiungere diversi gigabyte al file esportato.

Una volta che il file viene caricato in Stata, il comando compress in Stata può rimuovere automaticamente questi byte vuoti e compattare il file, ma per i grandi insiemi di dati, PROC EXPORT aggiunge così tanti byte in più al file che non sempre hanno abbastanza memoria per caricare il set di dati in Stata in primo luogo.

C'è un modo per impedire a SAS di riempire le variabili stringa in primo luogo? Quando esporto un file con una variabile di stringa di un carattere (ad esempio), desidero che tale variabile venga memorizzata come variabile di stringa di un carattere nel file di output.

+0

Sospetto che SAS stia aggiungendo un terminatore di stringa, anche se non ne ho idea. – Joe

+1

Guardando la documentazione Stata, supporta il terminatore di stringa '\ 0' (per l'operazione di tipo" Varchar "). Sospetto che SAS lo metta appena dopo * ogni * stringa, se dovessi indovinare.Suggerirei di inserire un ticket di supporto con il supporto tecnico SAS; possono probabilmente a) confermare questo e b) farti sapere se c'è una soluzione alternativa. Non ne vedo uno basato su un breve sguardo. – Joe

+1

E se si riceve risposta dal supporto tecnico SAS, si prega di aggiungere una risposta con qualsiasi informazione si ottenga, quindi è disponibile per altri utenti! – Joe

risposta

0

Se siete disposti ad accettare una risposta file flat, mi è venuta in mente un modo abbastanza semplice di generare uno che credo abbia le proprietà desiderati:

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; 

Questo dovrebbe funzionare così com'è , a condizione che la lunghezza totale assegnata di tutte le variabili nel set di dati sia inferiore a 32767 (il limite della funzione cat nell'ambiente di passaggio dei dati- il limite inferiore di 200 caratteri non si applica, poiché è solo quando si utilizza cat per creare un variabile a cui non è stata assegnata una lunghezza). Oltre a questo, potresti iniziare a incorrere in problemi di troncamento. Una soluzione alternativa quando ciò accade è solo il numero cat insieme un numero limitato di variabili alla volta: un processo manuale, ma molto meno laborioso della scrittura di istruzioni put basate sulle lunghezze di tutte le variabili e, a seconda dei dati, potrebbe non essere mai realmente salire.

In alternativa, si potrebbe andare verso il basso un percorso macro più complesso, ottenendo lunghezze variabili da entrambi la funzione vlength o dictionary.columns e utilizzando quelli più i nomi delle variabili per costruire la necessaria put statement (s).

+0

Mi piace l'idea di ottenere CAT per formattare la linea ma non funziona con variabili numeriche. Non puoi contare sulla conversione da numerica a carattere per produrre valori con la stessa larghezza. Ciò che renderebbe questo lavoro (penso) è una versione di funzione CAT che formatta tutti i vars utilizzando la funzione VVALUE. –

+0

@data_null_ - sfortunatamente nessuna funzione ipotetica 'catv' esiste, e' vvalue' e funzioni simili non possono essere utilizzate all'interno di una definizione di 'proc fcmp' in quanto sono valide solo all'interno di un passo di dati. Alcuni array e la logica delle macro sarebbero necessari per convertire i vär numerici in testo a larghezza fissa. – user667489

1

Ecco come è possibile farlo utilizzando le funzioni esistenti.

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; 

Per evitare l'uso di _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' e' vformatwx' sono i pezzi del puzzle che mi mancavano - è molto più difficile mettere tutto insieme ordinatamente senza di loro. Tuttavia, sarebbe ancora meglio evitare di usare '_file_' poiché limita ciascuna linea di output a 32767 caratteri. – user667489

+0

Vorrei anche suggerire di utilizzare 'substr' invece di' trim' per il passaggio finale di riordino, in quanto ciò eviterà di rimuovere qualsiasi spazio vuoto finale finale dall'ultima variabile nel set di dati di origine. – user667489

+0

Guardando molto bene ora - l'unica cosa che farei sarebbe impostare 'lrecl = 1000000' o simile per evitare che lunghe righe di output vengano troncate alla lunghezza predefinita. – user667489