全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
2013-9-10 23:12:36
zhou.wen 发表于 2013-9-10 23:10
APP function 据说只有5%的sasor才精通
APP function 是什么啊?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-10 23:24:57
addr peek poke
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 00:00:52
B.N.F 发表于 2013-9-10 23:10
这个代码为什么通不过呢?

data b;
%macro main;
data b;
array a(1000) $ ;
do i=1 to 1000;
a(i)=put(i,pib8.);
end;
e=addrlong(a(1));
call symputx("e",e);
_error_=dosubl( "
data a;
do i=1 to 12;
ans=peeklong(put(input('&e',pib8.)+8*(i-1),pib8.),8);
output;
end;
run;
quit;
");
run;
%mend;

%main;
嵌到一个宏里?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 00:34:37
dosubl is really a useful function!!!
DOSUBL is an experimental function in SAS 9.3 that takes a character value and executes the value as SAS code. DOSUBL does not return until the SAS code completes execution. DOSUB is similar to DOSUBL, yet it takes a fileref for a file that contains SAS code. DOSUB reads the file into memory and executes the contents as SAS code.
Both DOSUBL and DOSUB return zero if the code was able to execute and nonzero if the code did not execute. For example, if DOSUB could not read the input file or allocate enough memory to hold the file contents, it returns a nonzero value.
Here is an example of using DOSUBL from a DATA step to create a data set with PROC SQL:
4
data _null_;
rc = dosubl('proc sql;
create table work.regions as
select distinct region from sashelp.shoes;');
run;
When DOSUBL is called, it does not return until the SAS code completes. The SAS code passed to DOSUBL uses PROC SQL to create a data set named WORK.REGIONS that contains all the unique values for REGION in SASHELP.SHOES. If you wanted to operate on the distinct values within the same step, you can use the DATA step OPEN and FETCH functions to open and read WORK.REGIONS. The SET statement cannot be used because SET opens the data set before the step begins execution and the data set would not have been created yet.
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 05:05:15
zhou.wen 发表于 2013-9-11 00:00
%macro main;
data b;
array a(1000) $ ;
不知道为什么第一次执行会报错,
重复执行才没有报错。。。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 10:24:20
B.N.F 发表于 2013-9-11 05:05
不知道为什么第一次执行会报错,
重复执行才没有报错。。。
我一开始执行的时候没有出错,不过结果不对
你能说下你实现数据共享的思路是什么么?
感觉你对sas的宏用的不是很熟,但是对dosubl这种新函数又比较了解,还有app fuction这种基本没人用的东西反而比较了解,所以比较好奇你的背景,难道是有高人指点么
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 11:39:28
sxlion 发表于 2013-9-10 22:20
"我想把array进行数据共享,这样多个宏和多个data步,就不用重复的set了。"

这个问题 n年前讨论过,目 ...
9.3之后出了dosubl,可以实现这个目标
http://support.sas.com/resources ... ings12/227-2012.pdf
http://support.sas.com/resources ... ings13/032-2013.pdf
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 13:36:02
之前写的宏的处理机制我自己都不太理解
下面的做法更适合
data b;
array a(1000) $ ;
do i=1 to 1000;
a(i)=put(i,pib8.);
end;
e=addrlong(a(1));
call symputx("e",e);
_error_=dosubl( "
data a;
do i=1 to 12;
ans=peeklong(put(input(symget('e'),pib8.)+8*2*(i-1),pib8.),8);
output;
end;
run;
quit;
");
run;
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 14:03:29
补充一下,上面的代码也应该是比较好理解的,但是外部嵌套宏之后,宏的编译不是应该在data之前
因此,你第一次运行%main;的时候宏变量e没有赋值,所以出错,但是第二次运行%main;后宏变量e已经赋了值,所以第二次运行结果正确
这里还有个小问题,宏变量e赋的是data b中变量a(1)的内存地址,我一开始理解data步结束后内存地址会释放,也就是说下次运行data b步的时候a(1)的地址应该有变化才对
但是从结果来看,第二次运行%main;宏变量e正确的取到了a(1)的内存地址,也就是说第二次运行data b的时候,虽然数据集是重新生成的,但是给变量a(1)分配的内存地址跟第一次运行相比并没有改变。于是我猜测可能是sas内部有缓存机制
下面做一些实验:
option nonotes nosource;
%put Firt Time Run:data a address is;
data a;
b=1;c=2;
add=addrlong(b);
put add hex16.;
run;
%put Firt Time Run:data a1 address is;
data a1;
x=1;y=1;z=2;
add=addrlong(x);
put add hex16.;
run;
%put Second Time Run:data a address is;
data a;
b=1;c=2;
add=addrlong(b);
put add hex16.;
run;
结果为:
Firt Time Run:data a address is
0881AA0C00000000
Firt Time Run:data a1 address is
3881AA0C00000000
Second Time Run:data a address is
0881AA0C00000000
可以猜测提交过的代码在,在sas中有缓存,所以相同的变量的内存地址没有发生变化,这样也就解释了为什么第二次运行%main;可以成功。
上面的大部分内容为个人理解,希望各路大神拍砖。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 22:21:54
zhou.wen 发表于 2013-9-11 13:36
之前写的宏的处理机制我自己都不太理解
下面的做法更适合
data b;
1    data b;
2    array a(1000) $ ;
3    do i=1 to 1000;
4    a(i)=put(i,pib8.);
5    end;
6    e=addrlong(a(1));
7    call symputx("e",e);
8    _error_=dosubl( "
9    data a;
10   do i=1 to 12;
11   ans=peeklong(put(input(symget('e'),pib8.)+8*2*(i-1),pib8.),8);
12   output;
13   end;
14   run;
15   quit;
16   ");
17   run;

ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8
000000000C8A694E  000000002A22FA98  sase7:tkvercn1+0x1590E

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
ERROR: 出现了异常。
请与技术支持人员联系,并向他们提供下列回溯信息:

SAS 任务名称为 [DATASTEP]
ERROR:  Read Access Violation DATASTEP
Exception occurred at (0D811518)
Task Traceback
Address   Frame     (DBGHELP API Version 4.0 rev 5)
000000000D811518  000000002A22FA60  uwusysap:tkvercn1+0x4D8

NOTE: 参数“1”(用于函数“PEEKLONG”)无效,位置: 行 0 列 25。
i=13 ans=. _ERROR_=1 _N_=1
NOTE: 在以下位置无法执行算术运算。运算结果已设为缺失值。
      每个位置的指定方式: (次数)(行:列)。
      12,位置: 0:25。
NOTE: 数据集 WORK.A 有 12 个观测和 2 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.12 秒
      CPU 时间          0.09 秒


NOTE: 数据集 WORK.B 有 1 个观测和 1002 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.21 秒
      CPU 时间          0.15 秒


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 22:24:17
不加quit就没事,为什么?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-11 22:49:57
B.N.F 发表于 2013-9-11 22:21
1    data b;
2    array a(1000) $ ;
3    do i=1 to 1000;
我运行没有问题
1     data b;
2        array a(1000) $ ;
3        do i=1 to 1000;
4        a(i)=put(i,pib8.);
5        end;
6        e=addrlong(a(1));
7        call symputx("e",e);
8        _error_=dosubl( "
9        data a;
10      do i=1 to 12;
11      ans=peeklong(put(input(symget('e'),pib8.)+8*2*(i-1),pib8.),8);
12      output;
13      end;
14      run;
15      quit;
16      ");
17      run;

NOTE: 数据集 WORK.A 有 12 个观测和 2 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.04 秒
      CPU 时间          0.00 秒


NOTE: 数据集 WORK.B 有 1 个观测和 1002 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.54 秒
      CPU 时间          0.17 秒
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 00:37:59
zhou.wen 发表于 2013-9-11 22:49
我运行没有问题
1     data b;
2        array a(1000) $ ;
341  data b;
342  array a(1000) $ ;
343  do i=1 to 1000;
344  a(i)=put(i,pib8.);
345  end;
346  e=addrlong(a(1));
347  call symputx("e",e);
348  _error_=dosubl( "
349  data a;
350  do i=1 to 12;
351  ans=peeklong(put(input(symget('e'),pib8.)+8*(i-1),pib8.),8);
352  put ans=;
353  output;
354  end;
355  run;
356  quit;
357  ");
358  run;

ans=673
ans=674
ans=675
ans=676
ans=677
ans=678
ans=679
ans=680
ans=681
ans=682
ans=683
ans=684
NOTE: 数据集 WORK.A 有 12 个观测和 2 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.03 秒
      CPU 时间          0.03 秒


NOTE: 数据集 WORK.B 有 1 个观测和 1002 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.04 秒
      CPU 时间          0.04 秒
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 10:37:00
B.N.F 发表于 2013-9-12 00:37
341  data b;
342  array a(1000) $ ;
343  do i=1 to 1000;
我觉得问题在于call symputx("e",e)或者symget('e')的时候,把地址e截断了,因为addrlong出来的值有些是不可显示的符号,symputx()的时候可能将有些不可显示的值截取了,另外addrlong返回的20位的文本,而symget返回的是200位的文本,这里也可能发生截断。用宏直接传递地址可能不妥,不过我也没有解决方案,希望论坛里的大牛出来解答一下

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 11:55:25
B.N.F 发表于 2013-9-12 00:37
341  data b;
342  array a(1000) $ ;
343  do i=1 to 1000;
从下面的语句可以看到,出错并不是symput,symget的问题
而是通过dosubl函数不能实现内存数据共享,dosubl的具体机制我不清楚这里就不妄加评论了
内存共享数据还是比较困难的,还是让有能力的人去实现吧
data a;
a = 123456;
e=addrlong(a);
call symput('e',e);
x=peekclong(e,8);
y=input(x,rb8.);
rc=dosubl("
data b;
b=symget('e');
x1=peekclong(b,8);
y1=input(x1,rb8.);
run;
");
b=symget('e');
x1=peekclong(b,8);
y1=input(x1,rb8.);
run;
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 18:43:54
zhou.wen 发表于 2013-9-12 11:55
从下面的语句可以看到,出错并不是symput,symget的问题
而是通过dosubl函数不能实现内存数据共享,dosu ...
dosubl可以直接编译,不用symget是不是比较好?
另外peeklong和peekclong有什么区别呢?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 19:50:31
两位大侠拳来脚往,煞是精彩。我根本就不知道什么叫内存数据共享,但是如果楼主以前写过C,想在SAS里象C里面那样灵活地引用内存的话,基本是白费心机。为什么不把你要共享的东西放到SASFILE或者FORMAT里,享受生活呢?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 20:14:46
邓贵大 发表于 2013-9-12 19:50
两位大侠拳来脚往,煞是精彩。我根本就不知道什么叫内存数据共享,但是如果楼主以前写过C,想在SAS里象C里面 ...
那样会不会先被读取到PDV,然后再被读取?效率会低下?
如果内存里共享的话,是不是就一直在PDV里呢?
而且我要处理array,放在dataset里,只有一行,会不会慢?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 20:57:17
B.N.F 发表于 2013-9-12 20:14
那样会不会先被读取到PDV,然后再被读取?效率会低下?
如果内存里共享的话,是不是就一直在PDV里呢? ...
我建议你把数据变成一列,然后用hash组件,那样也可以实现data步共享数据
http://support.sas.com/documenta ... tn1vh9x4waiioz4.htm
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 21:16:34
zhou.wen 发表于 2013-9-12 20:57
我建议你把数据变成一列,然后用hash组件,那样也可以实现data步共享数据
http://support.sas.com/docum ...
hash的速度没有temp array 快,而且列的话,没法引用处理
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 23:07:07
B.N.F 发表于 2013-9-12 21:16
hash的速度没有temp array 快,而且列的话,没法引用处理
引用还是可以通过key引用的,hash也是address-direct定位的
不过如果你那么追求效率的话可能用C或C++比较适合,毕竟sas的定位还是统计软件,指针什么的不大适合
如果楼主要是研究出来了,一定要告知我,过来膜拜学习
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 23:38:06
zhou.wen 发表于 2013-9-12 23:07
引用还是可以通过key引用的,hash也是address-direct定位的
不过如果你那么追求效率的话可能用C或C++比较 ...
那本来需要lag来处理的,能用其他方法代替吗?
除了变成temp array?
谢谢!!!
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-12 23:44:00
B.N.F 发表于 2013-9-12 23:38
那本来需要lag来处理的,能用其他方法代替吗?
除了变成temp array?
谢谢!!!
你把代码贴上来啊,不然怎么帮你
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-13 15:17:21
zhou.wen 发表于 2013-9-12 23:44
你把代码贴上来啊,不然怎么帮你
data a;
do i= 1 to  1000000;
t=i;
output;
end;
run;
%macro a;
%do i=1 %to 50000;
data _null_;
set a;
retain e 0;
do j=&i. to 50000;
if _n_ gt &i. then do;
d=lag&i.(a)+lag10(lag&i.(a))/lag512(a)*exp(lag(a));
e=(e+d)/&i.
output;
end;
end;
run;
%end;
%mend;
%a;

大概就上面的意思。
因为需要重复调用a的数据,所以我想array计算起来方便,而且如果能共享的话,就免去了每次set的读入pdv的效率损失。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-13 15:40:41
B.N.F 发表于 2013-9-13 15:17
data a;
do i= 1 to  1000000;
t=i;
试下把数据集a放到内存里
sasfile a load;
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-13 16:42:56
zhou.wen 发表于 2013-9-13 15:40
试下把数据集a放到内存里
sasfile a load;
那样不也是需要每次先从内存的一个地方,放到内存的另一个地方pdv吗?
而且我早就把a放在内存里了。
另外还有就是lag问题很麻烦,如果是循环引用,大量的,不可能从lag1-lag10000生成表
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-14 16:49:42
B.N.F 发表于 2013-9-13 16:42
那样不也是需要每次先从内存的一个地方,放到内存的另一个地方pdv吗?
而且我早就把a放在内存里了。
另 ...
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-15 22:47:11
DELETE
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-16 04:08:50
邓贵大 发表于 2013-9-15 22:47
It cost 3 minutes to lag 1000 times. Expect 3 hours or so for 50,000 lags.
The LAG functions can be ...
谢谢邓贵大大哥热心回复!!!!
另外,如果用set point,会不会比lag好些?
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-9-17 04:12:34
DELETE
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群