在具有长不同长度字段的SAS中导入CSV会浪费磁盘空间

时间:2014-04-23 14:47:58

标签: csv sas

我遇到的问题是,当我导入我的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列)?这似乎是一个常见/简单的问题,但我还没有找到一个可行的解决方案,所以任何正确方向的帮助都会受到赞赏!

2 个答案:

答案 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 ;