我遇到的问题是,当我导入我的CSV文件时,我最终获得了大尺寸的临时文件(比输入文件本身大得多)。当对其中一些文件使用压缩时,我的空间减少了99%,但我想知道是否有更好的方法可以直接减小尺寸。我准备了一个简化的例子。我导入的CSV如下所示:
FILENAME CSVFILE("c:\example.csv");
DATA CSVINPUT (COMPRESS=yes REUSE=yes);
INFILE CSVFILE DSD DLM ="," lrecl=15000;
INFORMAT multiplier 3.0;
INFORMAT A $char1000. ;
INFORMAT B $char2000. ;
INFORMAT C $char2000. ;
INFORMAT D $char1000. ;
INFORMAT E $char5000. ;
INFORMAT F $char4000. ;
INPUT multiplier
A $
B $
C $
D $
E $
F $ ;
RUN;
CSV包含不同宽度的数据,列A
可能包含5个字符,或者可能包含1000个字符。与其他列类似。此外,这些列中的一些可能具有嵌入的空格。我不确定它是否对问题有帮助,但乘数决定了这些列的大小。以下是CSV数据文件格式的示例:
4,aaaa,bbbbbbbb, cc ,dddd,eeeeeeeeeeeeeeeeeeee,ffffffffffff
1,a,bb, ,d,eeeee,ffff
2,aa,bbbb,cc ,eeeeeeeeee,ffffffff
有没有什么方法可以更有效地导入这些数据,而不会截断任何值(或空格,例如C列)?这似乎是一个常见/简单的问题,但我还没有找到一个可行的解决方案,所以任何正确方向的帮助都会受到赞赏!
答案 0 :(得分:5)
SAS是一个固定宽度的数据库系统;像大多数SQL实现一样,它没有varchar
的概念。这意味着对于任何给定的SAS数据集,列具有固定的宽度(分配给它的存储字节数)。如果您希望有时在列(变量)中包含1或2个字符,有时需要1500个字符,则必须为列分配1500并处理废物。它使SAS在访问数据方面更快(因为它是可预测的扇区数量)但如果您的数据结构如上所述会浪费相当多的空间。
OPTIONS COMPRESS=CHAR
是处理此问题的正确方法,因为它会压缩数据并删除浪费的空间。除了以某种方式重构您的数据以避免列有大量浪费的空间之外,这是您唯一真正的选择。
答案 1 :(得分:1)
当您在文件中阅读时,您可以动态确定每个变量的最大长度,然后将定义变量的数据集重新写入最大长度。
但正如Joe所说,使用COMPRESS=CHAR
将基本上将磁盘消耗降低到存储非空数据所需的最小值。相比之下,使用动态方法加上压缩可能只会将其减少一小部分。
data char_lengths ; set csvinput end=eof ; array n{*} $5000. A-F ; array l{*} l1-l6 ; retain l . ; do i = 1 to dim(n) ; l{i} = max(l{i},length(n{i})) ; end ; if eof then do ; do i = 1 to dim(n) ; call symputx(cats('LEN',i),l{i}) ; call symputx(cats('VAR',i),vname(n{i})) ; end ; output ; end ; run ; %MACRO VARLEN ; %DO I = 1 %TO 6 ; &&VAR&I.._new $&&LEN&I... %END ; %MEND ; %MACRO VARASSIGN ; %DO I = 1 %TO 6 ; &&VAR&I.._new = &&VAR&I ; drop &&VAR&I ; %END ; %MEND ; data shrink (compress=char) ; length %VARLEN ; set csvinput ; %VARASSIGN ; run ;