SAS中文论坛

 找回密码
 立即注册

扫一扫,访问微社区

查看: 2335|回复: 15
打印 上一主题 下一主题

一个对我来说的难题。望各位给个援手

[复制链接]

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
楼主
 楼主| 发表于 2008-11-23 11:33:24 | 只看该作者

一个对我来说的难题。望各位给个援手

我有一个数据“house”,包括大约40000个家庭的数据。然后,我想把这个数据切成40000个小数据,从hourse_1 house_2 .... house_40000。

我写了一段非常简单的宏,显然可以做这个。
%macro Cut;      
  %do U=1 %to 40000 ;
  data house&U;
    set house ;
            if house_ID = &U then output house_&U ;
  run;
  %end;
%mend Cut;
%Cut;

但是,这里存在一个大问题。 这个house数据非常大,大约好几个G。我所写的宏的循环,非常慢。大约每3分钟才能够读出一个小文件(我电脑也不快 <!-- s:( --><img src="{SMILIES_PATH}/icon_sad.gif" alt=":(" title="Sad" /><!-- s:( -->  )。很急,所以想请教各位,有没有更有效率的编程方法或者思路。

我知道,直接用如下的方法,很快。一次读完house数据,就直接同时生成40000个我所需要的小文件。但是,这样一行一行写40000行,在编程方面就太没效率了。
data house_1 house_2 house_3 house_4 house_5   ......  (此处省略)   ;
    set house ;
            if house_ID = 1 then output house_1 ;
            if house_ID = 2 then output house_2 ;
            if house_ID = 3 then output house_3 ;
            if house_ID = 4 then output house_4 ;
            if house_ID = 5 then output house_5 ;
            if house_ID = 6 then output house_6 ;
            ...... (此处省略)
run;

希望各位大虾,给个可能的电脑跑起来比较快而且编程不会太冗长的解决之道。 多谢各位了。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
沙发
 楼主| 发表于 2008-11-23 14:50:23 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

[code:2vp912gh]%macro cut(num);
%local i;
data
  %do i=1 %to &amp;num;
     house_&amp;i
  %end;;
  set a;
  %do i=1 %to &amp;num;
  if house_id=&amp;i then output house_&amp;i;
  %end;
run;
%mend;
%cut(×××××);[/code:2vp912gh]
测测这个程序看怎么样,手头上没这么大的数据,无法测试。
前面一个很慢应该是由于频繁打开这么大的文件,耗时肯定是很长的。
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
板凳
 楼主| 发表于 2008-11-23 15:41:23 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

To tianwild

多谢你的帮助。正如你指出的,我的程序在于每次都要重新读入一个几G大的House,所以非常慢。每输出一次小文件,比如House_1,就要耗时几分钟。[40000 * 3 分钟 = 2000 小时。]

你的程序显然在每一循环中,不要读入House原文件,好得多。现在我正在试你提供的程序。我先试了Num = 100,即只输出 House_ID = 1 到 100 的小文件,耗时大约6分钟。 假如,这种循环不会由于Num的增加,几何级数增加的话,估计耗时 6* 40000/100 = 2400 分钟 = 40 小时。 好太多了,呵呵。

我会在试一下大约Num = 10000, 等有结果,我再留言。多谢多谢。  <!-- s:o --><img src="{SMILIES_PATH}/icon_surprised.gif" alt=":o" title="Surprised" /><!-- s:o -->
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
地板
 楼主| 发表于 2008-11-23 15:50:22 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

<!-- s:shock: --><img src="{SMILIES_PATH}/icon_eek.gif" alt=":shock:" title="Shocked" /><!-- s:shock: --> 应该还有更好的办法,看看其他高手...
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
5#
 楼主| 发表于 2008-11-23 17:09:58 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

类似的题目在论坛里讨论过很多次,我就把byes的答案重复一下吧:
data _null_;
set House;
by House_id;
if first.House_id then call execute('data '||House_id||';set house;if House_id='||House_id||';run');
run;
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
6#
 楼主| 发表于 2008-11-23 19:03:14 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

to Tianwild

目前,在temp文件夹中,House_1 to House_1000 (temp files) 大约耗时3小时了。也就是说,比原先估计的要多花3倍以上的时间,恐怕总共要超过120小时。诚如你所说的&quot;应该还有更好的办法&quot;,我也希望能有更快的方法。多谢了。   <!-- s:) --><img src="{SMILIES_PATH}/icon_smile.gif" alt=":)" title="Smile" /><!-- s:) -->

to 缘来是你

多谢你的帮助。等我的电脑有空了,就试你推荐Byes大侠的程序。
尽管,老帖有类似讨论。但是,这里的难点与侧重点有所不同。比如,不同于老帖的讨论,我已经知道House_ID总共有40000个distinct的值,这点无需在这里的编程中考虑了。我真正的麻烦来自于,House这个原数据文件很大有近10个G,所以程序需要很有效率运行,最好一步搞定不能反复读取原数据文件,否则非常耗时。 也恳请各路高手帮忙提供思路或解法,多谢了。

<!-- s:? --><img src="{SMILIES_PATH}/icon_confused.gif" alt=":?" title="Confused" /><!-- s:? -->
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
7#
 楼主| 发表于 2008-11-23 22:35:29 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

%macro cut(num);
%local i;
data
  %do i=1 %to &amp;num;
     house_&amp;i
  %end;;
  set a (where=(house_id=&amp;i ));
run;
%mend;
%cut(×××××);
试一试这个看下
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
8#
 楼主| 发表于 2008-11-23 22:38:01 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

我也遇到比较近似的问题,在近2G的文件里面提取子集,用data步无法提取,后来用sql才提取出来。但sql的效率一直是很低的。
[code:17ijaw8d]%macro cut(num);
proc sql noprint;
%do i=1 %to &amp;num;
create table house_&amp;i as
select house_id,x,y,z
from a
where house_id=&amp;i;
%end;
quit;
%mend;
%cut(XXXX);
[/code:17ijaw8d]
你测测下看效率如何
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
9#
 楼主| 发表于 2008-11-24 14:31:21 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

I would try to avoid
#1, opening 40,000 datasets at the same time;
#2, 40,000 passes of all rows of the original dataset.

Post #8 is ok if there is an index on house_id.

If you could sort the whole dataset by house_id in a reasonable amount of time, then
[code:9hwbi856]
options nonotes nosource;
data _null_;
        do count=1 by 1 until(last&#46;house_id);
                set houses_sorted(keep=house_id);
                by house_id;
        end;
        lastobs+count;
        call execute('data house_' || compress(house_id) || ';');
        call execute('set houses_sorted(firstobs=' || compress(lastobs-count+1) || ' obs=' || compress(lastobs) || ');');
run;
run;
[/code:9hwbi856]
Otherwise, you may break the big dataset into pieces (for example, cut it into 10 pieces by the remainder of house_id/10), and sort each piece before apply the code above for each sorted piece of data.

Anyway, it's a very bold action to generate 40,000 datasets and seems too many for my little brain.
回复 支持 反对

使用道具 举报

49

主题

76

帖子

1462

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1462
10#
 楼主| 发表于 2008-11-24 14:39:15 | 只看该作者

Re: 一个对我来说的难题。望各位给个援手

to applesloves

试了一下,似乎你的程序的where中的&amp;U并没有产生循环。多谢你的帮助。

to 嘉祥

我要花点时间看看的程序。 <!-- s:) --><img src="{SMILIES_PATH}/icon_smile.gif" alt=":)" title="Smile" /><!-- s:) -->   我也会听你的建议,把大数据先分成几个小的文件来对付。多谢了。

to tianwild

这个PROC sql程序需要反复读取原数据文件,并不快。还是你上一个程序好,很可能我就用它了。非常感谢你的热心帮助。 <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SAS中文论坛  

GMT+8, 2026-2-5 08:46 , Processed in 0.117546 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表