楼主: augustin4
3375 12

求助,关于sas批量打入excel数据 [推广有奖]

  • 0关注
  • 0粉丝

博士生

12%

还不是VIP/贵宾

-

威望
0
论坛币
416 个
通用积分
1.8536
学术水平
6 点
热心指数
6 点
信用等级
6 点
经验
7707 点
帖子
93
精华
0
在线时间
329 小时
注册时间
2014-1-14
最后登录
2022-12-20

200论坛币
学习了这个帖子https://bbs.pinggu.org/thread-1572362-1-1.html,但还有点不会
这是我的代码:
filename indata pipe "dir c:\*.csv/b";
data vname;                        
length fname $20.;
infile indata truncover;
input fname $20.;
call symput('nvars',_n_);
run;
%macro want;
%do i=1 %to &nvars ;
  data _null_;
   set vname;
   if _n_=&i;
   call symput('file',fname);
  run;
  data tmp;
    infile "c:\&file" firstobs=2 delimiter=',';
    input x y;
  run;
  proc datasets noprint;  
        append base=want data=tmp;
  quit;
%end;
%mend;
%want
quit;

我想实现:
1.不同的csv文件输入到以它名字命名的数据集中
2.输到一个数据集中,但添加一个分类变量:type,值等于数据集名字。

请各位指教。

最佳答案

sniperhgy 查看完整内容

嗯,这几点的意思分别是: 1. 用if _n_ = &i.;会导致set被执行多次,只有到了&i.的时候,值才会保留,而且即使已经去到了&i.,set也会去读取下面的行,这样比较浪费资源,如果用firstobs和obs选项,那么只会读取一次数据,这对于数据量比较大的时候,优势比较明显。 2.proc import: 2.1dbms是SAS外接其他数据的接口,而delimiter是分隔符,当dbms = dlm的时候,delimiter才会发生作用,也就是自定义分隔符,比如楼主遇到 ...
关键词:excel数据 EXCEL xcel exce cel sas
沙发
sniperhgy 发表于 2014-10-23 19:30:11 |只看作者 |坛友微信交流群
augustin4 发表于 2014-10-24 16:04
我还是有些问题不太明白:
关于第一段代码:
1.第13行这么做和
嗯,这几点的意思分别是:
1. 用if _n_ = &i.;会导致set被执行多次,只有到了&i.的时候,值才会保留,而且即使已经去到了&i.,set也会去读取下面的行,这样比较浪费资源,如果用firstobs和obs选项,那么只会读取一次数据,这对于数据量比较大的时候,优势比较明显。

2.proc import:
  2.1dbms是SAS外接其他数据的接口,而delimiter是分隔符,当dbms = dlm的时候,delimiter才会发生作用,也就是自定义分隔符,比如楼主遇到一个文本文件,里面都是用|分割的,那么delimiter = ‘|’,如果遇到用tab符分割的,delimiter = '09'x。至于dbms = csv,这句话,其实已经暗含了delimiter = ‘,’这句,就不需要楼主自己写了。

  2.2 guessingrows的作用就是判断变量类型和长度的,一般我都设置成32676,要是万一以后的数据出现不一样的情况,那就需要自己改成MAX(也可以写2147483647)了。所以我也推荐楼主这么设置,不是很费资源,所以不用担心运行效率的问题。

  2.3 datarow这个选项,和getnames有一定关系,如果getnames=YES,那么datarow不写的话值就为2,如果写了,那么就按照写的值读取;如果getnames=NO,datarow不写就是1,写了的话,按照写了的值

  2.4 replace这个也是个习惯,可以不加。

  2.5 导入excel不成功:那是因为excel引擎不支持guessingrows选项,也不需要,遇到excel文件,import会根据全部变量来设置变量的类型和长度,不用担心会被截取,所以只要将guessingrows去掉就好了。guessingrows用到普通的文本文件。

使用道具

藤椅
sniperhgy 发表于 2014-10-24 10:46:04 |只看作者 |坛友微信交流群
楼主你好,我又来了,对于问题一,其实用import会比较简单一点,因为是csv文件,格式是都好分割,不需要自己写data部,代码如下:
  1. filename indata pipe "dir d:\*.csv /b";

  2. data vname;
  3.   length fname $20.;
  4.   infile indata truncover;
  5.   input fname $20.;
  6.   call symput ('nvars',_n_);
  7. run;

  8. %macro want;
  9.   %do i = 1 %to &nvars.;
  10.     data _null_;
  11.       set vname(firstobs = &i. obs = &i.);
  12.       call symput ('file', strip(fname));
  13.     run;

  14.     proc import
  15.       out = %substr(&file., 1, %length(&file.) - 4)
  16.       datafile = "d:\&file."
  17.       dbms = csv replace;
  18.       guessingrows = 32676;
  19.       getname = YES;
  20.     run;
  21.   %end;
  22. %mend;

  23. %want
复制代码
但有一点要注意,就是那些csv文件的名字,不能有空格,否则SAS会出错,还有就是不能以数字开头,一定是字母或者下划线,否则SAS会认为那是无效的数据集名字。

第二个问题和第一个问题的思路是一样的,都是先读入,然后append到一起,代码如下:
  1. filename indata pipe "dir d:\*.csv /b";

  2. data vname;
  3.   length fname $20.;
  4.   infile indata truncover;
  5.   input fname $20.;
  6.   call symput ('nvars',_n_);
  7. run;

  8. %macro want;
  9.   %do i = 1 %to &nvars.;
  10.     data _null_;
  11.       set vname(firstobs = &i. obs = &i.);
  12.       call symput ('file', strip(fname));
  13.     run;

  14.     proc import
  15.       out = %substr(&file., 1, %length(&file.) - 4)
  16.       datafile = "d:\&file."
  17.       dbms = csv replace;
  18.       guessingrows = 32676;
  19.       getname = YES;
  20.     run;

  21.     data %substr(&file., 1, %length(&file.) - 4);
  22.       set %substr(&file., 1, %length(&file.) - 4);
  23.       type = %substr(&file., 1, %length(&file.) - 4);
  24.     run;

  25.     proc datasets;
  26.       append
  27.         base = want
  28.         data = %substr(&file., 1, %length(&file.) - 4);
  29.     quit;
  30.   %end;
  31. %mend;

  32. %want
复制代码
但是要append到一起,限制就比较多,首先,要求那些csv文件的layout是一样的,也就是列名和顺序都一样,还有,变量的长度要确保一致,否则会出现trunc的情况,还有就是需要先制作一个空的数据集want,里面的layout要和外面的csv一致,还得有一个type列,楼主可以自己试试看,我这里已经试验成功了。
已有 1 人评分论坛币 收起 理由
admin_kefu + 90 根据规定进行奖励

总评分: 论坛币 + 90   查看全部评分

使用道具

板凳
augustin4 发表于 2014-10-24 16:04:10 |只看作者 |坛友微信交流群
sniperhgy 发表于 2014-10-24 10:46
楼主你好,我又来了,对于问题一,其实用import会比较简单一点,因为是csv文件,格式是都好分割,不 ...
我还是有些问题不太明白:
关于第一段代码:
1.第13行这么做和
if _n_=&i;
   call symput('file',fname); 有什么区别?
2.我对proc import不太了解:
2.1 dbm和delimiter有什么区别?它的缺省值是csv还是dlm?dlm的意思是不是由delimiter定义划分?
2.2 guessingrows是不是用来判断变量的类型? 它的值应该i怎么设?
2.3 datarow这里没有给出,是不是缺省值是2?
2.4 以csv文件名命名的数据集本来就是第一次输入,是不是不用加replace?
2.4 我想干脆输入excel数据, 首先,这样成功了:(后缀xlsx)
  1. proc import
  2.    datafile='c:\temp\test.xlsx'
  3.    out=test2
  4.    dbms=excel;
  5.    sheet='sheet1$';
  6.    getname=yes;
  7.    run;
复制代码
但我把原来的程序改成这样就报错了:(后缀改成xlsx, dbms改为excel, substr改成截取5位)
  1. filename indata pipe "dir c:\*.xlsx /b";
  2. data vname;
  3.   length fname $20.;
  4.   infile indata truncover;
  5.   input fname $20.;
  6.   call symput ('nvars',_n_);
  7. run;
  8. %macro want;
  9.   %do i = 1 %to &nvars;
  10.     data _null_;
  11.       set vname(firstobs = &i obs = &i);
  12.       call symput ('file', strip(fname));
  13.     run;
  14.     proc import
  15.       out = %substr(&file,1,%length(&file)-5)
  16.       datafile = "c:\&file"
  17.       dbms = excel replace;
  18.       guessingrows = 32676;
  19.       getnames = YES;
  20.     run;
  21.   %end;
  22. %mend;
  23. %want
复制代码

使用道具

报纸
augustin4 发表于 2014-10-24 16:13:34 |只看作者 |坛友微信交流群
sniperhgy 发表于 2014-10-24 10:46
楼主你好,我又来了,对于问题一,其实用import会比较简单一点,因为是csv文件,格式是都好分割,不 ...
关于第二段代码,出了点问题:
我拿我c盘里的两个csv文件进行测试:
kkkkkeee.csv
hoh.csv
kkkkkeee.csv:
x        y
2        34
2        3
3        12
7        3
43        5
6        1
3        2

hoh.csv:
x        y
2        4
21        43
4        4
6        1
45        3
2        5
21        1

都是随便输的。
代码几乎没有改动:
  1. data want;
  2. input x y type;
  3. run;
  4. filename indata pipe "dir c:\*.csv /b";
  5. data vname;
  6.   length fname $20.;
  7.   infile indata truncover;
  8.   input fname $20.;
  9.   call symput ('nvars',_n_);
  10. run;
  11. %macro want;
  12.   %do i = 1 %to &nvars.;
  13.     data _null_;
  14.       set vname(firstobs = &i. obs = &i.);
  15.       call symput ('file', strip(fname));
  16.     run;
  17.         proc import
  18.       out = %substr(&file, 1, %length(&file) - 4)
  19.       datafile = "c:\&file"
  20.       dbms = csv replace;
  21.       guessingrows = 32676;
  22.       getname = YES;
  23.     run;
  24.          data %substr(&file, 1, %length(&file) - 4);
  25.       set %substr(&file, 1, %length(&file) - 4);
  26.       type = %substr(&file, 1, %length(&file) - 4);
  27.     run;
  28.    proc datasets noprint;
  29.       append
  30.         base = want
  31.         data = %substr(&file, 1, %length(&file) - 4);
  32.     quit;
  33.   %end;
  34. %mend;
  35. %want
复制代码
在给type赋值的data步之前没有任何问题,但之后
两个数据集中不但多了type变量,还多了一个叫kkkkkeee的变量,且两个变量都没有赋值。

最后日志是这样的:
NOTE: 由调用宏“WANT”生成行。
2      32676;       getname = YES;     run;
                    -------
                    1

WARNING 1-322: 假定符号 GETNAMES 被错拼为 getname。

ERROR: 文件正在使用中,c:\hoh.csv。
ERROR: 导入失败。详细信息,请参阅“SAS 日志”。
NOTE: 由于出错,SAS 系统停止处理该步。
NOTE: “PROCEDURE IMPORT”所用时间(总处理时间):
      实际时间          0.15 秒
      CPU 时间          0.15 秒



ERROR: 文件“WORK.HOH.DATA”不存在。

NOTE: 由于出错,SAS 系统停止处理该步。
WARNING: 数据集 WORK.HOH 可能不完整。该步停止时,共有 0 个观测和 2 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.03 秒
      CPU 时间          0.03 秒



NOTE: 正在追加 WORK.HOH 至 WORK.WANT。
WARNING: 变量 hoh 在 BASE 文件中未找到。变量将不能添加到 BASE 文件。
WARNING: 变量 x 在 DATA 文件中没有找到。
WARNING: 变量 y 在 DATA 文件中没有找到。
ERROR: 由于上面所列的异常,没有完成追加。 请用 FORCE 选项追加这些文件。
NOTE: 添加了 0 个观测。
NOTE: 数据集 WORK.WANT 有 0 个观测和 3 个变量。
NOTE: 由于上述错误,没有处理语句。
NOTE: 由于出错,SAS 系统停止处理该步。
NOTE: “PROCEDURE DATASETS”所用时间(总处理时间):
      实际时间          0.03 秒
      CPU 时间          0.03 秒




NOTE: 从数据集 WORK.VNAME. 读取了 1 个观测
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.00 秒
      CPU 时间          0.00 秒


NOTE: 由调用宏“WANT”生成行。
6      32676;       getname = YES;     run;
                    -------
                    1

WARNING 1-322: 假定符号 GETNAMES 被错拼为 getname。

ERROR: 文件正在使用中,c:\kkkkkeee.csv。
ERROR: 导入失败。详细信息,请参阅“SAS 日志”。
NOTE: 由于出错,SAS 系统停止处理该步。
NOTE: “PROCEDURE IMPORT”所用时间(总处理时间):
      实际时间          0.17 秒
      CPU 时间          0.17 秒



ERROR: 文件“WORK.KKKKKEEE.DATA”不存在。

NOTE: 由于出错,SAS 系统停止处理该步。
WARNING: 数据集 WORK.KKKKKEEE 可能不完整。该步停止时,共有 0 个观测和 2 个变量。
NOTE: “DATA 语句”所用时间(总处理时间):
      实际时间          0.01 秒
      CPU 时间          0.01 秒



NOTE: 正在追加 WORK.KKKKKEEE 至 WORK.WANT。
WARNING: 变量 kkkkkeee 在 BASE 文件中未找到。变量将不能添加到 BASE 文件。
WARNING: 变量 x 在 DATA 文件中没有找到。
WARNING: 变量 y 在 DATA 文件中没有找到。
ERROR: 由于上面所列的异常,没有完成追加。 请用 FORCE 选项追加这些文件。
NOTE: 添加了 0 个观测。
NOTE: 数据集 WORK.WANT 有 0 个观测和 3 个变量。
NOTE: 由于上述错误,没有处理语句。
NOTE: 由于出错,SAS 系统停止处理该步。
NOTE: “PROCEDURE DATASETS”所用时间(总处理时间):
      实际时间          0.03 秒
      CPU 时间          0.03 秒

使用道具

地板
sniperhgy 发表于 2014-10-24 17:49:36 |只看作者 |坛友微信交流群
augustin4 发表于 2014-10-24 16:13
关于第二段代码,出了点问题:
我拿我c盘里的两个csv文件进行测试:
kkkkkeee.csv
不好意思啊,代码里面有两处错误的地方
  1. filename indata pipe "dir d:\*.csv /b";

  2. data vname;
  3.   length fname $20.;
  4.   infile indata truncover;
  5.   input fname $20.;
  6.   call symput ('nvars',_n_);
  7. run;

  8. %macro want;
  9.   %do i = 1 %to &nvars.;
  10.     data _null_;
  11.       set vname(firstobs = &i. obs = &i.);
  12.       call symput ('file', strip(fname));
  13.     run;

  14.     proc import
  15.       out = %substr(&file., 1, %length(&file.) - 4)
  16.       datafile = "d:\&file."
  17.       dbms = csv replace;
  18.       guessingrows = 32676;
  19.       getnames = YES;
  20.     run;

  21.     data %substr(&file., 1, %length(&file.) - 4);
  22.       set %substr(&file., 1, %length(&file.) - 4);
  23.       type = "%substr(&file., 1, %length(&file.) - 4)";
  24.     run;

  25.     proc datasets;
  26.       append
  27.         base = want
  28.         data = %substr(&file., 1, %length(&file.) - 4);
  29.     quit;
  30.   %end;
  31. %mend;

  32. %want
复制代码
这个代码在我这里可以正常运行。

使用道具

7
augustin4 发表于 2014-10-25 00:07:26 |只看作者 |坛友微信交流群
sniperhgy 发表于 2014-10-24 17:49
不好意思啊,代码里面有两处错误的地方这个代码在我这里可以正常运行。
是差不多能运行了,但还是有一点小问题:
我的两个变量名长短不一样,于是我用proc datasets 中的force选项追加了,但长度被选为短的名字
hoh了。我于是在data步中定义了type的长度为$20.
  1. filename indata pipe "dir c:\*.csv /b";
  2. data vname;
  3.   length fname $20.;
  4.   infile indata truncover;
  5.   input fname $20.;
  6.   call symput ('nvars',_n_);
  7. run;
  8. %macro want;
  9.   %do i = 1 %to &nvars.;
  10.     data _null_;
  11.       set vname(firstobs = &i. obs = &i.);
  12.       call symput ('file', strip(fname));
  13.     run;
  14.     proc import
  15.       out = %substr(&file., 1, %length(&file.) - 4)
  16.       datafile = "c:\&file."
  17.       dbms = csv replace;
  18.       guessingrows = 32676;
  19.       getnames = YES;
  20.     run;
  21.     data %substr(&file., 1, %length(&file.) - 4);
  22.   length type $20.;
  23.       set %substr(&file., 1, %length(&file.) - 4);
  24.       type = "%substr(&file., 1, %length(&file.) - 4)";
  25.      
  26.      run;
  27.     proc datasets noprint;
  28.       append
  29.         base = want
  30.         data = %substr(&file., 1, %length(&file.) - 4) force;
  31.     quit;
  32.   %end;
  33. %mend;
  34. %want
复制代码
这样就可以了,只不过之前把length写在了type赋值之后,就失败了。

使用道具

8
augustin4 发表于 2014-10-25 00:09:52 |只看作者 |坛友微信交流群
sniperhgy 发表于 2014-10-24 17:49
不好意思啊,代码里面有两处错误的地方这个代码在我这里可以正常运行。
还有,麻烦回答我一下藤椅楼的问题。悬赏已加。

使用道具

9
augustin4 发表于 2014-10-28 14:01:22 |只看作者 |坛友微信交流群
sniperhgy 发表于 2014-10-25 13:26
嗯,这几点的意思分别是:
1. 用if _n_ = &i.;会导致set被执行多次,只有到了&i.的时候,值才会保留,而 ...
多谢指点!解决了我不少老问题!感觉我以前学的sas就像菜单操作一样!

使用道具

10
sniperhgy 发表于 2014-10-28 14:21:08 |只看作者 |坛友微信交流群
augustin4 发表于 2014-10-28 14:01
多谢指点!解决了我不少老问题!感觉我以前学的sas就像菜单操作一样!
不客气,有收获就好,恭喜楼主了,也欢迎一起讨论问题

使用道具

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

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-25 14:40