楼主: LinYouthen
6297 12

[问答] SAS如何读取凌乱数据,将字符串转日期,并且在字符串中截取字段? [推广有奖]

  • 1关注
  • 0粉丝

已卖:8份资源

副教授

27%

还不是VIP/贵宾

-

威望
0
论坛币
1678 个
通用积分
0
学术水平
0 点
热心指数
2 点
信用等级
1 点
经验
53994 点
帖子
58
精华
0
在线时间
1517 小时
注册时间
2010-8-29
最后登录
2024-8-27

楼主
LinYouthen 发表于 2013-8-27 23:33:57 |AI写论文
20论坛币
我有一百万行向类似下面的文本数据:
x1:小明,x2:1988-03-17  12:00:47,x3:男,x4:公务员,x5:喜欢打篮球,x6:1:14,25:10,67:01,6:23,x7:25岁
x1:小红,x2:1982-01-17  11:04:24,x3:女,x4:程序员,x5:喜欢乒乓球球,x6:16:14,25:10,67:01,6:23,x7:26岁
x1:小朱**x2:1990-01-17  05:07:11****x3:男,x4:运动员,x5:喜欢游泳/*/-x6:10:10,05:18,77:06,6:23,x7:23岁
x1:小梁**&x2:1978-09-17  05:07:11***x3:男,x4:会计员,x5:喜欢跑步,x6:11:14,07:18,47:09,6:23,x7:35岁

…………
有几个问题:
1.读取以上数据,本来想以逗号为分隔符,可是看到红色的乱码,发现不能这样读取数据,否则小朱的X1和X2会连在一起。现在希望读取每个Xi和X(i+1)之间的字符串或者数字(包括乱码但是不要逗号)。
2.读完数据以后,我希望将X2转换成为日期格式,比如小明X2这一列转换成1988/03/17 12:00:47。
3.读取完以后,发现蓝色部分X6字段需要再分割,而且只读每个取冒号和逗号之间的部分,比如小明分成X6a这一列是14,X6b是10,X6c是01,X6d是23。
4.最后做逻辑回归发现一百万数据,y=0的有930万,而y=1反应变量只有70万,比例是13:1,请问需要在y=0中进行抽样,使得1和0没有那么大差距,最佳比例又是多少?
先谢谢大家了!

最佳答案

scarfacetony 查看完整内容

看是这个意思不~
关键词:字符串 逻辑回归 文本数据 读取数据 程序员 字符串 如何
无忧无虑无烦恼

沙发
scarfacetony 发表于 2013-8-27 23:33:58
LinYouthen 发表于 2013-8-28 18:21
非常感谢您,请问一下:

如果按照您第一次给我的方法,如何计算每个人,比如小明,不同id的num总数以及 ...
  1. data a(drop=i x6);
  2.         infile cards dlm=',*/' missover;
  3.         input
  4.         @'x1:' x1 :$10.
  5.         @'x2:' x2 :anydtdtm20.
  6.         @'x3:' x3 :$2.
  7.         @'x4:' x4 :$20.
  8.         @'x5:' x5 :$20.
  9.         @'x6:' x6 $30.
  10.     #1        @'x7:' x7 :$6.;
  11.         format x2 datetime19.;
  12.                 i=1;
  13.         do while (i=1 or id >0);
  14.                 id=input(scan(x6,i,':,'),8.);
  15.                 counts=input(scan(x6,i+1,':,'),8.);
  16.                                 i+2;
  17.                                 output;
  18.                 id=input(scan(x6,i,':,'),8.);                               
  19.         end;
  20. cards;
  21. x1:小明,x2:1988-03-17  12:00:47,x3:男,x4:公务员,x5:喜欢打篮球,x6:1:14,25:10,67:01,6:23,x7:25岁
  22. x1:小红,x2:1982-01-17  11:04:24,x3:女,x4:程序员,x5:喜欢乒乓球球,x6:16:14,25:10,67:01,6:23,x7:26岁
  23. x1:小朱**x2:1990-01-17  05:07:11****x3:男,x4:运动员,x5:喜欢游泳/*/-x6:10:10,05:18,77:06,6:23,x7:23岁
  24. x1:小梁**&x2:1978-09-17  05:07:11***x3:男,x4:会计员,x5:喜欢跑步,x6:11:14,07:18,47:09,6:23,x7:35岁
  25. ;

  26. run;

  27. proc sql;
  28.         create table b as
  29.         select id, sum(counts) as sumnum, mean(counts) as avenum
  30.         from a group by id;
  31. quit;
复制代码
看是这个意思不~
看了这个视频,我于是有了进股市的信心!
https://bbs.pinggu.org/thread-2787427-1-1.html

藤椅
yongyitian 发表于 2013-8-28 09:58:54
try this.
  1. data a;
  2. length x1-x7 $30.;
  3. infile datalines dsd dlm='x';
  4. input @4 x1 $ +2 x2 $ +2 x3 $ +2 x4 $ +2 x5 $ +2 x6 $ +2 x7 $ +2;  
  5. datalines;
  6. x1:XiaoMing,x2:1988-03-17  12:00:47,x3:M,x4:Officer,x5:LikeBasketBall,x6:1:14,25:10,67:01,6:23,x7:25SUi
  7. x1:XiaoHong,x2:1982-01-17  11:04:24,x3:F,x4:Programmer,x5:LikeTableTennis,x6:16:14,25:10,67:01,6:23,x7:26Sui
  8. x1:XiaoZhu**x2:1990-01-17  05:07:11****x3:M,x4:Athlete,x5:LikeSwim/*/-x6:10:10,05:18,77:06,6:23,x7:23Sui
  9. x1:XiaoLiang**&x2:1978-09-17  05:07:11***x3:M,x4:Accountant,x5:LikeJogging,x6:11:14,07:18,47:09,6:23,x7:35Sui
  10. ; run;

  11. data b; ;
  12.     set a;
  13.      x1 = scan(x1, 1, ',');  
  14.       x2 = scan(x2, 1, ',*');
  15.        x3 = scan(x3, 1, ',*');
  16.         x4 = scan(x4, 1, ',*');
  17.          x5 = scan(x5, 1, ',*');
  18.      x6a = scan(scan(x6, 1, ','), 2, ':');
  19.       x6b = scan(scan(x6, 2, ','), 2, ':');
  20.        x6c = scan(scan(x6, 3, ','), 2, ':');
  21.         x6d = scan(scan(x6, 4, ','), 2, ':');
  22.     x7 = scan(x7, 1, ',*');
  23.    datetime=dhms(input(scan(x2, 1, '  '), yymmdd10.), 0,0, input(scan(x2, 2, '  '), time.));
  24.    format date yymmdd10. time time. datetime datetime20.;
  25.    drop date time;
  26. run;
复制代码
已有 2 人评分学术水平 热心指数 信用等级 收起 理由
LinYouthen + 1 + 1 + 1 观点有启发
scarfacetony + 1 + 1 + 1 有心了,写这么长……

总评分: 学术水平 + 2  热心指数 + 2  信用等级 + 2   查看全部评分

板凳
scarfacetony 发表于 2013-8-28 10:53:13
这里有些分隔符是中文格式下输入的,要先做个替换,替换成英文格式下的符号。就是   ,换成,  :换成:
  1. data a(drop=i x6);
  2.         infile cards dlm=',*/' missover;
  3.         input
  4.         @'x1:' x1 :$10.
  5.         @'x2:' x2 :anydtdtm20.
  6.         @'x3:' x3 :$2.
  7.         @'x4:' x4 :$20.
  8.         @'x5:' x5 :$20.
  9.         @'x6:' x6 $30.
  10.     #1        @'x7:' x7 :$6.;
  11.         format x2 datetime19.;
  12.         do i=1 to 7 by 2;
  13.                 id=scan(x6,i,':,');
  14.                 num=scan(x6,i+1,':,');
  15.                 output;
  16.         end;
  17. cards;
  18. x1:小明,x2:1988-03-17  12:00:47,x3:男,x4:公务员,x5:喜欢打篮球,x6:1:14,25:10,67:01,6:23,x7:25岁
  19. x1:小红,x2:1982-01-17  11:04:24,x3:女,x4:程序员,x5:喜欢乒乓球球,x6:16:14,25:10,67:01,6:23,x7:26岁
  20. x1:小朱**x2:1990-01-17  05:07:11****x3:男,x4:运动员,x5:喜欢游泳/*/-x6:10:10,05:18,77:06,6:23,x7:23岁
  21. x1:小梁**&x2:1978-09-17  05:07:11***x3:男,x4:会计员,x5:喜欢跑步,x6:11:14,07:18,47:09,6:23,x7:35岁
  22. ;

  23. run;
复制代码
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
yongyitian + 1 + 1 + 1 观点有启发

总评分: 学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

看了这个视频,我于是有了进股市的信心!
https://bbs.pinggu.org/thread-2787427-1-1.html

报纸
LinYouthen 发表于 2013-8-28 15:11:27
scarfacetony 发表于 2013-8-28 10:53
这里有些分隔符是中文格式下输入的,要先做个替换,替换成英文格式下的符号。就是   ,换成,  :换成:
感谢两位大侠的帮助,两位程序让我受益匪浅,可是我有些不懂的还是需要请教两位:

@yongyitian,我的实际数据是存在很多个X的,不是全部中文或者数字,因此用X作为分隔符,会出现很多问题,另一方面,请问一下scan(x3, 1, ',*'),引号中存在两个字符是什么意思呢?,第三方面其实我的实际数据不仅包括x6a-x6d四个分割的,有些有6个,有些有9个等等,如果按照您的方法,有些繁琐。

@scarfacetony,您好,您的方法很好用,可是菜鸟我不懂的是dlm=',*/' missover这句话什么意思,  #1        @'x7:' x7 :$6.;,这句话前面的  #1又是什么意思,最后我希望每个名字出现的跟原来一样,而不是出现若干个小明,小红,请问该怎么做,谢谢你们了

无忧无虑无烦恼

地板
scarfacetony 发表于 2013-8-28 15:29:16
LinYouthen 发表于 2013-8-28 15:11
感谢两位大侠的帮助,两位程序让我受益匪浅,可是我有些不懂的还是需要请教两位:

@yongyitian,我的实 ...
dlm=   是指分隔符  上面语句中只要出现其中任一分隔符则进行分隔。
MISSOVER在这个语句中是可以省略的。
SAS在读取字段时,如果发现在该行仍有未读入的变量,会转入下一行继续读取变量 。MISSOVER可以阻止这个行为,每一行都从第一个变量时开始读取。

#1是 是强行读取该行,因为在X6读取时,我是直接读取30个字符,不看分隔符,这时很可能已经把X7这个字符串读到X6里面去了,   此时如果不用#1读X7,会在X6读的数据后找X7,就找不到……

如果一个小明只要一行的话,就不需要循环。
  1. data a(drop=i x6);
  2.         infile cards dlm=',*/';
  3.         input
  4.         @'x1:' x1 :$10.
  5.         @'x2:' x2 :anydtdtm20.
  6.         @'x3:' x3 :$2.
  7.         @'x4:' x4 :$20.
  8.         @'x5:' x5 :$20.
  9.         @'x6:' x6 $30.
  10.     #1        @'x7:' x7 :$6.;
  11.         format x2 datetime19.;
  12.                 id1=scan(x6,1,':,');
  13.                 num1=scan(x6,2,':,');
  14.                 id2=scan(x6,3,':,');
  15.                 num2=scan(x6,4,':,');
  16.                 id3=scan(x6,5,':,');
  17.                 num3=scan(x6,6,':,');
  18.                 id4=scan(x6,7,':,');
  19.                 num4=scan(x6,8,':,');
  20. cards;
  21. x1:小明,x2:1988-03-17  12:00:47,x3:男,x4:公务员,x5:喜欢打篮球,x6:1:14,25:10,67:01,6:23,x7:25岁
  22. x1:小红,x2:1982-01-17  11:04:24,x3:女,x4:程序员,x5:喜欢乒乓球球,x6:16:14,25:10,67:01,6:23,x7:26岁
  23. x1:小朱**x2:1990-01-17  05:07:11****x3:男,x4:运动员,x5:喜欢游泳/*/-x6:10:10,05:18,77:06,6:23,x7:23岁
  24. x1:小梁**&x2:1978-09-17  05:07:11***x3:男,x4:会计员,x5:喜欢跑步,x6:11:14,07:18,47:09,6:23,x7:35岁
  25. ;

  26. run;
复制代码
看了这个视频,我于是有了进股市的信心!
https://bbs.pinggu.org/thread-2787427-1-1.html

7
LinYouthen 发表于 2013-8-28 17:23:44
scarfacetony 发表于 2013-8-28 15:29
dlm=   是指分隔符  上面语句中只要出现其中任一分隔符则进行分隔。
MISSOVER在这个语句中是可以省略的 ...
非常感谢您的帮助,最后请教一下:
请问第四个问题怎么解决?

怎么批量修改变量名,比如我有1000个字段名,分别是*1,*2,*3,*4,*5,*6,*7....,我怎么样全部把*去掉或者改成其他名字;

请问怎么打印变量的第一行?
谢谢你
无忧无虑无烦恼

8
scarfacetony 发表于 2013-8-28 17:55:08
LinYouthen 发表于 2013-8-28 17:23
非常感谢您的帮助,最后请教一下:
请问第四个问题怎么解决?
你说的第四个是统计问题,我不是统计学出身,还是等高人讲解。

批量改名的问题,我只知道在data步中,用rename进行处理,如果变量较多,你可以借助EXCEL写个函数,再把语句复制出来,不知道高人有没有其它方法。

打印功能,呃,木有使用过

爱莫能助了~
看了这个视频,我于是有了进股市的信心!
https://bbs.pinggu.org/thread-2787427-1-1.html

9
LinYouthen 发表于 2013-8-28 18:21:46
scarfacetony 发表于 2013-8-28 17:55
你说的第四个是统计问题,我不是统计学出身,还是等高人讲解。

批量改名的问题,我只知道在data步中, ...
非常感谢您,请问一下:

如果按照您第一次给我的方法,如何计算每个人,比如小明,不同id的num总数以及平均值等等相关的统计量。

因为我的数据不单单是X1a,X2b,X3c,X4d四个而已,因此需要做循环,我最终目的是做不同id的num的统计,请你指教,谢谢。


无忧无虑无烦恼

10
yongyitian 发表于 2013-8-29 09:39:37
LinYouthen 发表于 2013-8-28 15:11
感谢两位大侠的帮助,两位程序让我受益匪浅,可是我有些不懂的还是需要请教两位:

@yongyitian,我的实 ...
  1. /* Q1: ',*' = ',' or '*' */

  2. /* if you have more then 4 parts in x6, you can use array to define more variables */
  3. data b; ;
  4. set a;
  5. x1 = scan(x1, 1, ',');
  6. x2 = scan(x2, 1, ',*');
  7. x3 = scan(x3, 1, ',*');
  8. x4 = scan(x4, 1, ',*');
  9. x5 = scan(x5, 1, ',*');
  10. x7 = scan(x7, 1, ',*');
  11. date = input(scan(x2, 1, ' '), yymmdd10.);
  12. time = input(scan(x2, 2, ' '), time.);
  13. datetime=dhms(input(scan(x2, 1, ' '), yymmdd10.), 0,0, input(scan(x2, 2, ' '), time.));
  14. format date yymmdd10. time time. datetime datetime20.;
  15. * x6a = scan(scan(x6, 1, ','), 2, ':');
  16. * x6b = scan(scan(x6, 2, ','), 2, ':');
  17. * x6c = scan(scan(x6, 3, ','), 2, ':');
  18. * x6d = scan(scan(x6, 4, ','), 2, ':');
  19. /* vvvvv new vvvvv */
  20. array xx {5} x6_1-x6_5;
  21. array id {5} id1-id5;
  22. do i = 1 to dim(xx);
  23. xx[i] = scan(scan(x6, i, ','), 2, ':');
  24. id[i] = scan(scan(x6, i, ','), 1, ':');
  25. end;
  26. drop date time i x6;
  27. run;
复制代码

已有 1 人评分学术水平 热心指数 信用等级 收起 理由
LinYouthen + 1 + 1 + 1 观点有启发

总评分: 学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

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

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-10 05:12