楼主: addictedtome
5544 24

[原创博文] SAS求解一个问题,关于寻找连续出现的变量 [推广有奖]

  • 0关注
  • 4粉丝

已卖:22份资源

副教授

43%

还不是VIP/贵宾

-

威望
0
论坛币
183 个
通用积分
10.6659
学术水平
21 点
热心指数
30 点
信用等级
14 点
经验
22165 点
帖子
638
精华
0
在线时间
1000 小时
注册时间
2008-8-31
最后登录
2025-7-6

楼主
addictedtome 发表于 2010-4-18 17:29:33 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
希望找出被基金连续持有超过4个季度(含4个季度)的公司。

比如说基金001,持有100只股票,希望找出被连续持有超过4个季度(含4个季度)的公司。这个程序大概怎么写?我想了很久想不出来,望有高手求解!谢谢
二维码

扫码加我 拉你入群

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

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

关键词:程序

回帖推荐

yatming 发表于10楼  查看完整内容

7楼的substr有个小错误,第三个参数应该是截长。其次,关于where的语句所要表达的意思,我来解释一下吧,其实是having语句,该表若每天都有记录即持有则视为连续,因此sum(n)就是持有的天数,dif则是时长,因此天数等于时长就代表了连续,反之两者之间的差则是代表了未持有的天数,若差不为零就不构成了连续。 不过关于楼主的定义我有一些别的看法。 从楼主给到的数据来看,貌似并不是每天都有记录,而date的值都为季度末的最 ...

crackman 发表于7楼  查看完整内容

第一步变换DATE data crackman; set fund000001; date=mdy(input(substr(date,6,7),f2.),input(substr(date,9,10),f2.),input(substr(date,1,4),f4.); run; proc sort data=crackman out=crackman; by stock date; run; proc sql noprint; create table result as select *,max(date)-min(date) as dif from crackman group by stock; quit; data result; set result; if dif>=365 then n=1; else n=0; proc sql; ...

本帖被以下文库推荐

沙发
crackman 发表于 2010-4-18 19:43:52
我也不知道怎么帮助你
我不知道你的数据库结构是什么样子的
你先列一个例子出来吧
不然不好写的

藤椅
addictedtome 发表于 2010-4-19 07:44:28

板凳
addictedtome 发表于 2010-4-19 08:00:38
我自己把这个分了个类:
proc print data=fund;
run;

proc sort data=fund out=fund1;
by fund_code;

proc print data=fund1;
run;

data fund000001;
set fund1;
if fund_code= '000001';

proc print data=fund000001;

proc sort data=fund000001;
by date;


proc means data=fund000001;
by date;
run;

proc print data=fund000001;
by date;
title fund000001;
run;

现在我需要的是,如果某只股票被fund连续持有超过4个季度,就返回一个值1,否则是0。

不知道我解释的是否清楚.......

麻烦了。。

报纸
addictedtome 发表于 2010-4-19 08:02:52
因为这个数据是试用的,所以只有1年,完整版本的有大概4-5年。

地板
crackman 发表于 2010-4-19 08:13:27
你说了这么多
我还是没理解
你按照图片的格式
解释每一个变量的定义其实就完了

7
crackman 发表于 2010-4-19 08:26:32
第一步变换DATE
data crackman;
set  fund000001;
date=mdy(input(substr(date,6,7),f2.),input(substr(date,9,10),f2.),input(substr(date,1,4),f4.);
run;
proc sort data=crackman out=crackman;
by stock date;
run;
proc sql noprint;
create table result as select *,max(date)-min(date) as dif from crackman group by stock;
quit;
data result;
set result;
if dif>=365 then n=1;
else n=0;
proc sql;
create table result1 as select * from result where sum(n)=dif;
quit;
run;
这个里面用一个标记变量,当标记变量值与日期插值想等时候初步判断为连续
但是这个里面的连续是不是你所说的连续?
已有 2 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
bakoll + 3 + 3 精彩帖子
jingju11 + 1 + 1 + 1 so good

总评分: 经验 + 3  论坛币 + 3  学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

8
addictedtome 发表于 2010-4-19 16:50:27
谢谢啊,我看了程序,太厉害了,结果应该就是我需要的,不过程序还是有些问题

max(date)-min(date);

运行到这里的时候出错,显示减法需要使用数字:
ERROR: Expression using subtraction (-) requires numeric types.

最后为什么要加 where sum(n)=dif 呢?而且这里也出错了,显示ERROR: Summary functions are restricted to the SELECT and HAVING clauses only.

9
crackman 发表于 2010-4-19 17:38:39
你用input转换一下就可以了

10
yatming 发表于 2010-4-20 00:08:08
7楼的substr有个小错误,第三个参数应该是截长。其次,关于where的语句所要表达的意思,我来解释一下吧,其实是having语句,该表若每天都有记录即持有则视为连续,因此sum(n)就是持有的天数,dif则是时长,因此天数等于时长就代表了连续,反之两者之间的差则是代表了未持有的天数,若差不为零就不构成了连续。

不过关于楼主的定义我有一些别的看法。

从楼主给到的数据来看,貌似并不是每天都有记录,而date的值都为季度末的最后一天,如果是这样,那date其实就可以作为季度。因此猜想:
1 此数据是在季度末最后一天的状态。有记录则代表此季度fund持有该stock,无记录则代表此季度fund不持有。
2 连续持有4个季度应该是指对于某个fund,只要有连续四个季度及以上持有某stock的记录,则就视为满足条件。季度的连续性应该包括跨年吧。
举例:对于某个fund,持有某个stock的时间点
若为:2005-03-31,2005-06-30,2005-12-31,则该stock不满足条件
若为:2005-06-30,2005-09-30,2005-12-31,2006-01-31,则该stock满足条件
若为:2004-06-30,2005-06-30,2005-09-30,2005-12-31,2006-01-31,虽然第一时间点与第二时间点相差1年,但后四个时间点仍然构成连续四个季度,因此则该stock满足条件

在这样的前提下:

第一步:
  1. proc sql;
  2.         create table fund01 as
  3.         select
  4.                 distinct *,
  5.                 input(date,yymmdd10.) as td,
  6.                 min(td) as min_dte
  7.         from fund
  8.         group by fund_code,stock
  9.         order by fund_code,stock,td
  10.         ;
  11. quit;
复制代码
第二步:
  1. data fund02(keep=fund_code stock hsy);
  2.         set fund01;
  3.         by fund_code stock td;
  4.         length hsy $ 30;
  5.         retain hsy;
  6.         if first.stock then call missing(hsy);
  7.         /*计算季度差,建议采用'30/360',对于本数据集更准确。
  8.         由于此例,date的特殊性,yrdif函数计算结果的小数位只有0,.25,.5,.75四种可能。*/
  9.         t=yrdif(min_dte,td,'30/360')*4;
  10.         if t=1 then hsy=compress(hsy)||'1';
  11.         else if t>1 then hsy=compress(hsy)||repeat('0',t-2)||'1';
  12.         else hsy='1';
  13.         if last.stock;
  14. run;
复制代码
第三步:
  1. proc sql;
  2.         create table result as
  3.         select
  4.                 a.*,
  5.                 case when b.fund_code and b.stock then 1 else 0 end flg
  6.         from fund as a
  7.         left join fund02(where=(hsy contains '1111')) as b
  8.         on a.fund_code=b.fund_code
  9.         and a.stock=b.stock
  10.         ;
  11. quit;
复制代码
哪位高手有更好的方法,希望指点。
已有 2 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
bakoll + 3 + 3 精彩帖子
addictedtome + 1 + 1 + 1 非常感谢

总评分: 经验 + 3  论坛币 + 3  学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

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

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