Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SAS中是否有一种有效的转置大表的方法_Sas_Transpose - Fatal编程技术网

SAS中是否有一种有效的转置大表的方法

SAS中是否有一种有效的转置大表的方法,sas,transpose,Sas,Transpose,我在SAS中有一个数据集需要转置。它的形式是 id日期类型值 我需要把它转换成 类型1的id日期值类型2的id日期值 有什么有效的方法来实现这一点吗?我的数据是huuuge 比如, data one; input ID date type $ value; cards; 1 2001 A 2 1 2002 A 4 1 2001 B 3 2 2001 B 1 2 2002 A 5 2 2002 C 2 2 2003 C 5 3 2001 B 6 4 2002 B 8 4 2003 B 4

我在SAS中有一个数据集需要转置。它的形式是 id日期类型值 我需要把它转换成 类型1的id日期值类型2的id日期值

有什么有效的方法来实现这一点吗?我的数据是huuuge

比如,

data one; 
input ID date type $ value; 

cards; 
1 2001 A 2
1 2002 A 4
1 2001 B 3
2 2001 B 1
2 2002 A 5
2 2002 C 2
2 2003 C 5
3 2001 B 6
4 2002 B 8
4 2003 B 4
4 2001 A 2
;
我想把它转换成以下形式;(最后三列为valA、valB、valC)


PROC-TRANSPOSE将非常非常有效地完成这项工作,我敢说,它与任何其他数据库管理系统中最有效的方法相当或更好。您的数据也已经针对该方法进行了完美的组织。您只需要按ID日期排序,除非您已经有了该组合的索引(如果您有数十亿条记录,这是必要的)。除非您有足够的内存将其全部放在内存中,否则没有其他解决方案能与之媲美——对于这种大小的数据集来说,这是相当疯狂的(即使10亿条记录也至少需要7GB,如果您有数百万个ID,那么它显然不是一个1字节的ID;我猜是25-30GB或更多)

在我的系统上进行的简单测试,包括以下内容:

data one; 
do id = 1 to 1e6;
  do date = '01JAN2010'd to '01JAN2012'd;
    type = byte(ceil(ranuni(7)*26)+64);
    value = ceil(ranuni(7)*20);
    output;
  end;
end;
run;
proc sort data=one;
by id date;
run;
proc transpose data=one out=want;
by id date;
id type;
var value;
run;
该数据集压缩了约20GB(OPTIONS COMPRESS=YES)。最初写大约需要4分15秒,排序需要11分钟,转置需要45分钟,写一个大约100GB的压缩文件。我想这是你能做的最好的了;在这45分钟中,可能有20分钟以上的数据被写出来(数据集大5倍,写出来的时间将超过5倍,加上压缩开销);我当时也在做其他事情,所以CPU时间可能有些膨胀,因为它没有得到我的整个处理器(这是我的桌面,一个4核的i5)。我不认为这是特别不合理的处理时间

你可以考虑一下你的需求,也许转座不是你真正想要的——你真的想把你的桌子弄得那么多吗?你很有可能在不转换整个数据集的情况下实现你的实际目标(你的分析等)

if first.date then a=.;b=.;c=.;d=.; 
必须替换为:

if first.date then do;
    a=.;b=.;c=.;d=.;
end;

也代替

if last.date then do; output; a=.;b=.;c=.;d=.; end;
现在,这应该足够了:

if last.date then output;
我想在大数据上,datastep总是比PROC TRANSPOSE更高效。限制是您必须找出转置变量的不同值,并为这些值创建新变量。我认为这就是PROC TRANSPOSE的开销——它首先找出值。
(很抱歉,我编辑了您自己的答案,因此现在可能不清楚问题出在哪里。)

另一种数据步骤方法():

在我的系统上,使用Joe使用的1/10大小的数据集,排序需要2分钟,使用proc transpose需要9分40秒。道琼斯指数在7分4秒内完成了同样的事情。在这个特定的场景中,它并不令人印象深刻,但它比proc转置有一个很大的优势:您可以使用它在一个过程中转置多个变量。以下是我使用的代码:

data one; 
do id = 1 to 1e5;
  do date = '01JAN2010'd to '01JAN2012'd;
    type = byte(ceil(ranuni(7)*26)+64);
    value = ceil(ranuni(7)*20);
    output;
  end;
end;
run;

data two;
  do _n_ = 1 by 1 until(last.DATE);
    set one;
    array vals[26] val65-val90;
    by ID DATE;
    do i = 1 to 26;
      if type = byte(64 + i) then vals[i] = value;
    end;
  end;
  drop value i;
run;
动态重命名所有26个转置类型变量有点棘手,但这可以通过调用执行完成:

data _null_;
  call execute('proc datasets lib = work nolist;');
  call execute('modify two;');
  call execute('rename');
  do i = 1 to 26;
    call execute(compress('val' || i + 64) || ' = ' || compress('val' || byte(64+i)));
  end;
  call execute(';');
  call execute('run;');
  call execute('quit;');
run;

您是否知道
proc transpose
?如果有比为这项工作设计的
proc
更有效的方法,我会感到惊讶。我知道
proc transpose
但是还有其他方法吗?因为我的数据集有超过10亿个观测值(数百万个ID,几乎每个ID都有近千个日期,以及8种不同的类型)。是否有使用其他功能(如保留等)的快捷方式?谢谢。根据我对SAS效率的理解,几乎任何可以在
proc
中完成的事情都应该在
proc
中完成。使用数据步骤通常效率要低得多;如果您使用的是SPDE,那么您可以跳过排序,并且可能可以从中获得非常好的性能,远远好于我在这里得到的性能。
if last.date then output;
proc sort data = one;
  by ID date;
run;

data two;
  do _n_ = 1 by 1 until(last.date);
    set one;
    by ID DATE;
    if type = "A" then valA = value;
    else if type = "B" then valB = value;
    else if type = "C" then valC = value;
  end;
  drop value;
run;
data one; 
do id = 1 to 1e5;
  do date = '01JAN2010'd to '01JAN2012'd;
    type = byte(ceil(ranuni(7)*26)+64);
    value = ceil(ranuni(7)*20);
    output;
  end;
end;
run;

data two;
  do _n_ = 1 by 1 until(last.DATE);
    set one;
    array vals[26] val65-val90;
    by ID DATE;
    do i = 1 to 26;
      if type = byte(64 + i) then vals[i] = value;
    end;
  end;
  drop value i;
run;
data _null_;
  call execute('proc datasets lib = work nolist;');
  call execute('modify two;');
  call execute('rename');
  do i = 1 to 26;
    call execute(compress('val' || i + 64) || ' = ' || compress('val' || byte(64+i)));
  end;
  call execute(';');
  call execute('run;');
  call execute('quit;');
run;