楼主: reduce_fat
866 13

[程序分享] 悬赏金币解决 SAS 数据处理整合问题, 谢谢! [推广有奖]

荣誉版主

海外论坛首席管理员

已卖:18504份资源

泰斗

28%

还不是VIP/贵宾

-

TA的文库  其他...

海外原创经济论文和写作技巧

威望
11
论坛币
3591257 个
通用积分
34054.8393
学术水平
6834 点
热心指数
7193 点
信用等级
6665 点
经验
1830 点
帖子
12424
精华
78
在线时间
1974 小时
注册时间
2011-6-13
最后登录
2025-10-23

一级伯乐勋章 初级热心勋章 初级学术勋章 中级热心勋章 中级学术勋章 高级学术勋章 初级信用勋章 特级学术勋章 高级热心勋章 中级信用勋章 特级热心勋章 高级信用勋章 特级信用勋章

楼主
reduce_fat 发表于 2025-2-7 09:40:55 |AI写论文
66论坛币
楼主最近遇到一个数据处理和整合问题,具体请看附件里的 数据表和说明。 Sample Data.pdf (27.46 KB)   
简单来说呢,就是附件里的左边表格是原始样本数据。 右边的表格是要实现的结果表格。

我们把原始数据叫做 dataset_1 那么想要的数据叫做 final_output。

首先是把这些人的ID 选出符合条件的。条件是每个ID的第一个start date 必须是在 2020年1月1日以后发生的就是疫情开始后的才算数。如果有的ID 的第一个 start date 是2019年10月发生的,那么不论他是否有2020年以后发生的start date,他所有的数据都该被剔除。

还有就是service count 就是服务统计。 想要实现的结果表格就是统计符合条件的人的服务的。 比如ID 009 的第一个start date 是4/9/2020 那么他就符合条件。 如果他后来又有三个服务日期分别发生在 9/2/2020, 11/5/2020, 和5/11/2021 那么就应该这样统筹到结果表格里。

比如Month 1 意味着 Day 1-30 也就是 4/9/2020 - 5/8/2020 期内发生的任何服务都算在Month 1的里面。

那么9/2/2020 是发生在 9/9/2020 - 10/8/2020 之间,那么这该算作 Month 6里面因为是在 Day 151-180 期内发生的。

但是 11/5/2020 是发生在 11/9/2020 - 12/8/2020 之间, 这个算做 Month 8 里面。我想要的表格里不关心Month 8 所以这个服务虽然是符合条件的,但是不必统计到结果表格里。

还有5/11/2021 是发生在 一年以后也就是 Month 12+ 那么这个只要是超过Day 365 的都算作一起,归纳到 Month 12+ 里即可。

金币不够,可以再加。 请把代码发到评论里。 谢谢支持。

关键词:数据处理 dataset service output month
相关内容:SAS数据处理
复制粘贴积分链接 https://bbs.pinggu.org/ext8_airdrop.php?airdropfrom^^uid=2669999

沙发
whymath 发表于 2025-2-7 09:40:56
  1. data dataset_1;
  2.   input id : $3. start_date : mmddyy10. service_count;
  3.   format start_date e8601da.;
  4.   cards;
  5. 001 7/4/2018 1
  6. 001 4/9/2019 2
  7. 002 4/1/2021 1
  8. 002 5/3/2022 3
  9. 003 1/2/2019 1
  10. 004 11/5/2023 2
  11. 005 6/4/2020 4
  12. 005 4/2/2021 1
  13. 005 4/19/2021 4
  14. 006 5/2/2021 3
  15. 006 5/31/2022 1
  16. 007 1/5/2021 1
  17. 007 9/16/2022 2
  18. 007 10/25/2023 3
  19. 008 4/8/2020 2
  20. ;
  21. run;

  22. data final_output;
  23.   set dataset_1 end=_eof_;
  24.   by id start_date;

  25.   *仅分析首个 start_date 晚于 2020-01-01 的观测;
  26.   retain first_start_date;
  27.   if first.id then first_start_date=start_date;
  28.   if first_start_date>'01JAN2020'd;

  29.   *将每条观测划分到首个 start_date 以来的不同月份;
  30.   ady=start_date-first_start_date+1;
  31.   if ady>=365 then category='Month 12+';
  32.   else category='Month '||cats(ceil(ady/30));
  33.   categoryn=ifn(ady>=365,13,ceil(ady/30));

  34.   *按月份对 ID 去重计数,按月份对 service_count 求和;
  35.   array _count_[13]_temporary_(13*0);   *13 stands for "Month 12+";
  36.   array _sum_[13]_temporary_(13*0);
  37.   if first.ID or categoryn^=lag(categoryn) then _count_[categoryn]+1;
  38.   _sum_[categoryn]+service_count;

  39.   *按格式输出结果;
  40.   length item $ 42;
  41.   array _result_[13] result1-result13;
  42.   if _eof_ then do;
  43.     item=cats('# of IDs');
  44.     do _n_=1 to dim(_result_);
  45.       _result_[_n_]=_count_[_n_];
  46.     end;
  47.     output;

  48.     item='Count of Services';
  49.     do _n_=1 to dim(_result_);
  50.       _result_[_n_]=_sum_[_n_];
  51.     end;
  52.     output;

  53.     item='Average Services Per ID';
  54.     do _n_=1 to dim(_result_);
  55.       if _count_[_n_] then _result_[_n_]=_sum_[_n_]/_count_[_n_];
  56.       else _result_[_n_]=.N;
  57.     end;
  58.     output;
  59.   end;
  60.   keep item result1 result3 result6 result9 result13;
  61. run;
复制代码

藤椅
reduce_fat 发表于 2025-2-10 11:46:12
whymath 发表于 2025-2-9 22:15
谢谢答复,这个 lag 的应用 还有 _temporary_ 我不怎么明白。 请详细解释一下。
  array _count_[13]_temporary_(13*0);   *13 stands for "Month 12+";
  array _sum_[13]_temporary_(13*0);
  if first.ID or categoryn^=lag(categoryn) then _count_[categoryn]+1;
  _sum_[categoryn]+service_count;

板凳
reduce_fat 发表于 2025-2-10 11:57:38
whymath 发表于 2025-2-9 22:15
刚才可能我打错字了,出现的错误,现在纠正过来了,但是还是不怎么懂:  categoryn=ifn(ady>=365,13,ceil(ady/30)); 这一个的逻辑,和我上个评论里的问题。 现在我跑出的结果只有result1 也就是每个ID的第一个符合标准的服务期后30天内的 人数,服务次数,还有每个ID的平均服务次数。 为什么 result3, 6, 9, 12+ (13) 都是 0 人数, 0 服务次数,还有 N 的 平均服务次数。 我跑出结果后没有得到任何warning 和 error 的提示。 不到5分钟就出来结果了。

谢谢再次解答。

报纸
whymath 发表于 2025-2-10 22:17:08
reduce_fat 发表于 2025-2-10 11:46
谢谢答复,这个 lag 的应用 还有 _temporary_ 我不怎么明白。 请详细解释一下。
  array _count_[13]_t ...
不客气。

此处用 lag 函数是想要判断当前观测 categoryn 的值是否与上一条观测不同,如不同时,才累加 ID 的数量,这样就做到了每个 ID 在每个 categoryn(月份) 仅累加一次数量。
_temporary_ 关键字将当前数组标记为临时数组,数组元素不会保存为输出数据集的变量,一来让输出更干净,二来也比普通数组处理速度更快。

地板
whymath 发表于 2025-2-10 22:27:45
reduce_fat 发表于 2025-2-10 11:57
刚才可能我打错字了,出现的错误,现在纠正过来了,但是还是不怎么懂:  categoryn=ifn(ady>=365,13,ceil ...
变量 ady 是每个 ID 当前观测的日期到该 ID 下第一条观测的日期的天数。

一楼的附件规定:
当 ady ≥ 365 时,当前观测分类为 Month 12+;
当 ady 处于 1~30 时,当前观测分类为 Month 1;
当 ady 处于 61~90 时,当前观测分类为 Month 3;
当 ady 处于 151~180 时,当前观测分类为 Month 6;
当 ady 处于 241~270 时,当前观测分类为 Month 9;

不难归纳:
当 ady ≥ 365 时,分类为 Month 12+;
否则,分类为 ceil(ady/30),此处的 ceil 表示向上取整;

可声明如下赋值语句:
  1. if ady>=365 then categoryn=13;
  2. else categoryn=ceil(ady/30);
复制代码
等价于
  1. categoryn=ifn(ady>=365,13,ceil(ady/30));
复制代码

7
whymath 发表于 2025-2-10 22:38:53
结果中,显示为 N 的,实际为 SAS 的特殊缺失值 .N,我以此表示分母为 0,无法执行除法。

若对结果存疑,可略过变量 categoryn 之后的计算,然后直接运行程序:
  1. data final_output;
  2.   set dataset_1 end=_eof_;
  3.   by id start_date;

  4.   *仅分析首个 start_date 晚于 2020-01-01 的观测;
  5.   retain first_start_date;
  6.   if first.id then first_start_date=start_date;
  7.   if first_start_date>'01JAN2020'd;

  8.   *将每条观测划分到首个 start_date 以来的不同月份;
  9.   ady=start_date-first_start_date+1;
  10.   if ady>=365 then category='Month 12+';
  11.   else category='Month '||cats(ceil(ady/30));
  12.   categoryn=ifn(ady>=365,13,ceil(ady/30));
  13. run;
复制代码

以便检查月份(变量category 和 categroyn)的划分是否正确。

8
reduce_fat 发表于 2025-2-11 09:34:45
whymath 发表于 2025-2-10 22:38
结果中,显示为 N 的,实际为 SAS 的特殊缺失值 .N,我以此表示分母为 0,无法执行除法。

若对结果存疑 ...
非常感谢讲解。

9
reduce_fat 发表于 2025-2-11 11:34:58
whymath 发表于 2025-2-10 22:17
不客气。

此处用 lag 函数是想要判断当前观测 categoryn 的值是否与上一条观测不同,如不同时,才累加 ...
还有个新问题想请教一下。 https://bbs.pinggu.org/forum.php ... 14034908&extra=

10
whymath 发表于 2025-2-11 20:57:07
reduce_fat 发表于 2025-2-11 11:34
还有个新问题想请教一下。 https://bbs.pinggu.org/forum.php?mod=viewthread&tid=14034908&extra=
谢邀,但题目没看懂

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

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-29 06:17