t********m 发帖数: 939 | 1 这里的牛人多,再来请教一下。data set 如下:
data test;
input id $1 v1 3 v2 $5-6 v3 8 v4 $10-11;
cards;
a 1 x2 .
a . 3
a . . x4
b 1 x2 .
b . 3
b . . x4
;
run;
我想得到如下的data set:
id v1 v2 v3 v4
a 1 x2 3 x4
b 1 x2 3 x4
试了几种办法都不行,求教大牛们,谢谢! |
j******o 发帖数: 127 | 2 试试这个
data obtain(rename=(v1a=v1 v2a=v2 v3a=v3 v4a=v4));
length v2a v4a $8;
set test;
by id;
retain v1a v2a v3a v4a;
if first.id then do;
v1a=.; v3a=.;
v2a='';v4a='';
end;
if v1^=. then v1a=v1;
if v3^=. then v3a=v3;
if v2^='' then v2a=v2;
if v4^='' then v4a=v4;
if last.id;
keep id v1a v2a v3a v4a;
run; |
y********0 发帖数: 638 | 3 %let NM=is not missing;
data one(keep=id v1 v2 where=(v1 &NM))
two(keep=v3 where=(v3 &NM))
three(keep=v4 where=(v4 &NM));
set test;
;
data all;
set one;
set two;
set three;
run;
【在 t********m 的大作中提到】 : 这里的牛人多,再来请教一下。data set 如下: : data test; : input id $1 v1 3 v2 $5-6 v3 8 v4 $10-11; : cards; : a 1 x2 . : a . 3 : a . . x4 : b 1 x2 . : b . 3 : b . . x4
|
g****8 发帖数: 2828 | 4 楼上的方法好,不过,可以不用两步,用个merge的小trick就行
%let NM=is not missing;
data test2;
merge test(keep=id v1 v2 where=(v1 &NM))
test(keep=v3 where=(v3 &NM))
test(keep=v4 where=(v4 &NM));
;
run; |
t********m 发帖数: 939 | 5 这个行,谢谢!
不过真实情况是,我的变量有差不多上千个,如果按照这个来写,将会非常的tedious
,不知道能不能有什么改进的办法。我觉得这个程序应该是最保险最不会出错的。多谢
了!
【在 j******o 的大作中提到】 : 试试这个 : data obtain(rename=(v1a=v1 v2a=v2 v3a=v3 v4a=v4)); : length v2a v4a $8; : set test; : by id; : retain v1a v2a v3a v4a; : if first.id then do; : v1a=.; v3a=.; : v2a='';v4a=''; : end;
|
y********0 发帖数: 638 | 6 谢谢,我就是瞅着应该能改进..所以还是放上来,想着总会有人指出来.
其实楼主如果怕出错,可以三个都用keep=id,然后merge by,会不会更保险?
【在 g****8 的大作中提到】 : 楼上的方法好,不过,可以不用两步,用个merge的小trick就行 : %let NM=is not missing; : data test2; : merge test(keep=id v1 v2 where=(v1 &NM)) : test(keep=v3 where=(v3 &NM)) : test(keep=v4 where=(v4 &NM)); : ; : run;
|
k*******a 发帖数: 772 | 7 这个可以看作是个 LOCF的问题
可以用 array 来做,如果变量多的话
tedious
【在 t********m 的大作中提到】 : 这个行,谢谢! : 不过真实情况是,我的变量有差不多上千个,如果按照这个来写,将会非常的tedious : ,不知道能不能有什么改进的办法。我觉得这个程序应该是最保险最不会出错的。多谢 : 了!
|
t********m 发帖数: 939 | 8 这个方法真好,简单明了。我也想过分出几个data set,每一个data set里面id没有重
复的,但现实是我的变量有差不多上千个,按照变量值missing来分出几个data set可
能不太可行,因为对于同一个id,有些变量可能都missing,而有些变量可能不止存在
于一个record,比如说如果我的data set是这样的:
a 1 x2 . x4
a 1 x2 .
a . . x4
b 1 x2 .
b . .
b . x2 . x4
那这个程序就不work了。怎样改进这个程序,让它work呢?请继续指教!
【在 y********0 的大作中提到】 : %let NM=is not missing; : data one(keep=id v1 v2 where=(v1 &NM)) : two(keep=v3 where=(v3 &NM)) : three(keep=v4 where=(v4 &NM)); : set test; : ; : data all; : set one; : set two; : set three;
|
t********m 发帖数: 939 | 9 谢谢!如果这个程序对我的真实的case能work就好了。
【在 g****8 的大作中提到】 : 楼上的方法好,不过,可以不用两步,用个merge的小trick就行 : %let NM=is not missing; : data test2; : merge test(keep=id v1 v2 where=(v1 &NM)) : test(keep=v3 where=(v3 &NM)) : test(keep=v4 where=(v4 &NM)); : ; : run;
|
P****D 发帖数: 11146 | |
|
|
t********m 发帖数: 939 | 11 保留任何一个都可以,因为在我的case里同一id同一变量在不同的record里面的值应该
是相同的。如果说我要保留同一个id里第一个record的,该怎么操作呢?
多谢指教!
【在 P****D 的大作中提到】 : 在这种情况下,你要保留哪个?
|
t********m 发帖数: 939 | 12 谢谢。我想过了,但对我的case这个程序必须得修改才能用,原因见上楼。
【在 y********0 的大作中提到】 : 谢谢,我就是瞅着应该能改进..所以还是放上来,想着总会有人指出来. : 其实楼主如果怕出错,可以三个都用keep=id,然后merge by,会不会更保险?
|
t********m 发帖数: 939 | 13 多谢建议。我去做做locf的research。
【在 k*******a 的大作中提到】 : 这个可以看作是个 LOCF的问题 : 可以用 array 来做,如果变量多的话 : : tedious
|
y********0 发帖数: 638 | 14 如果变量在同一个id下都一样,用个merge by,然后只取if first.id就可以了.
不过有1000个变量的话,我觉得就得一个一个变量来,用宏好像好点.
我试了一下下面的:
%let NM=is not missing;
%macro v_func;
%do i=1 %to 1000;
v_&i(keep=id v&i where=(v&i &NM))
%end;
%mend;
data %v_func;
set test;
run;
data all;
merge v_1-v_1000;
by id;
if first.id;
run;
其实ginl18的更简单些,也可以改成宏程序. 不过我sas也是新手,用的也不是很熟.
大家一起讨论..
【在 t********m 的大作中提到】 : 谢谢。我想过了,但对我的case这个程序必须得修改才能用,原因见上楼。
|
n**m 发帖数: 156 | 15 use multiple line input:
data test;
input #1 id $1 v1 3 v2 $5-6
#2 v3 8
#3 v4 $10-11;
cards;
a 1 x2 .
a . 3
a . . x4
b 1 x2 .
b . 3
b . . x4
;
run; |
s******r 发帖数: 1524 | 16 proc sql;
create table test2 as
select id, max(v1) as v1, max(v2) as v2, max(v3) as v3, max(v4) as v4
from test
group by id;quit;run;
It works for your sample. Not sure meet your requirement.
【在 t********m 的大作中提到】 : 这里的牛人多,再来请教一下。data set 如下: : data test; : input id $1 v1 3 v2 $5-6 v3 8 v4 $10-11; : cards; : a 1 x2 . : a . 3 : a . . x4 : b 1 x2 . : b . 3 : b . . x4
|
t********m 发帖数: 939 | 17 多谢你的回复,这个程序很好,不过不太适合我的case,因为我的差不多1000个变量的
变量名并不是成系列的,所以那个do循环和V&i都不合适。不过还是非常感谢你热心的
回复,我觉得你能写出这样的sas程序,还说自己是初学者有点谦虚啦~
【在 y********0 的大作中提到】 : 如果变量在同一个id下都一样,用个merge by,然后只取if first.id就可以了. : 不过有1000个变量的话,我觉得就得一个一个变量来,用宏好像好点. : 我试了一下下面的: : %let NM=is not missing; : %macro v_func; : %do i=1 %to 1000; : v_&i(keep=id v&i where=(v&i &NM)) : %end; : %mend; : data %v_func;
|
t********m 发帖数: 939 | 18 Thanks for your reply. This works for my sample data, but not works for my
real case. Thanks anyway.
【在 n**m 的大作中提到】 : use multiple line input: : data test; : input #1 id $1 v1 3 v2 $5-6 : #2 v3 8 : #3 v4 $10-11; : cards; : a 1 x2 . : a . 3 : a . . x4 : b 1 x2 .
|
t********m 发帖数: 939 | 19 Thanks a lot for your reply. I think it will also work for my real case, but
I need to enter all those hundreds of variable names manually.
【在 s******r 的大作中提到】 : proc sql; : create table test2 as : select id, max(v1) as v1, max(v2) as v2, max(v3) as v3, max(v4) as v4 : from test : group by id;quit;run; : It works for your sample. Not sure meet your requirement.
|
g****8 发帖数: 2828 | 20 你可以用个macro把所有的变量名读出来,然后写macro.
but
【在 t********m 的大作中提到】 : Thanks a lot for your reply. I think it will also work for my real case, but : I need to enter all those hundreds of variable names manually.
|
|
|
s******r 发帖数: 1524 | 21 大包子 pls.
%macro test;
proc sql;
create table var_ls as select distinct name from dictionary.columns
where libname='WORK' and memname='TEST' and upcase(name) ne 'ID';quit;run;
data _null_;set var_ls;
call symput(cats('var',_n_),name);
call symput('cnt',_n_);
run;
proc sql;
create table test2 as
select id
%do i = 1 %to &cnt;
,max(&&var&i) as &&var&i
%end;
from test
group by id;quit;run;
%mend;
%test;
but
【在 t********m 的大作中提到】 : Thanks a lot for your reply. I think it will also work for my real case, but : I need to enter all those hundreds of variable names manually.
|
y********0 发帖数: 638 | 22 en.是用个宏把名字串起来就可以了.不知道大家还有没有更简单的.
proc datasets nolist;
contents data=test out=v_list(keep=name);
run;
proc sql noprint;
select name into:v_name separated by '.'
from v_list;
quit;
%let NM=is not missing;
%macro v_func;
data
%do i=1 %to 4;
v_&i(keep=id %scan(&v_name,(&i)+1,.) where=(%scan(&v_name,(&i)+1,.) &NM))
%end;
;
set test;
run;
%mend;
%v_func
data all;
merge v_1-v_4;
by id;
if first.id;
run;
【在 t********m 的大作中提到】 : 多谢你的回复,这个程序很好,不过不太适合我的case,因为我的差不多1000个变量的 : 变量名并不是成系列的,所以那个do循环和V&i都不合适。不过还是非常感谢你热心的 : 回复,我觉得你能写出这样的sas程序,还说自己是初学者有点谦虚啦~
|
c**d 发帖数: 104 | 23 maybe you can do this way (I did not write the whole codes):
/* 1: work on numeric */
/* output data include 3 columns:id, label, max value */
proc means data = test;
class id;
var _numeric_;
output out= max = _max;
run;
/* transpose by id and use label as variable name*/
proc transpose;
run;
/* 2: work on char variables */
/* you can also get id, varname, unique value and freq */
proc freq data = test;
table id*_char_;
ods output freqtable;
run;
/* do a data step to remove the row id*id in the freqtable */
/* you use proc transpose the freqtable */
/* 3: then you can merge them together */
/* 4: if you want to keep the original position of each variable */
proc contents data = orig_data short position;
run;
data new;
attrib /*paste the variable list from the log window */
set merged_data;
run;
【在 s******r 的大作中提到】 : 大包子 pls. : %macro test; : proc sql; : create table var_ls as select distinct name from dictionary.columns : where libname='WORK' and memname='TEST' and upcase(name) ne 'ID';quit;run; : data _null_;set var_ls; : call symput(cats('var',_n_),name); : call symput('cnt',_n_); : run; : proc sql;
|
o****o 发帖数: 8077 | 24 凑个热闹,给个比较冗长但是通用的解法
data test;
input id $1 v1 3 v2 $5-6 v3 8 v4 $10-11;
cards;
a 1 x2 .
a . 3
a . . x4
b 1 x2 .
b . 3
b . . x4
;
run;
proc sql noprint;
select
case
when(type='char') then cat('length ', compress(name), ' $ ',
length, ';')
else cat('length ', compress(name), ' ', length, ';')
end
into :varlist separated by ' '
from sashelp.vcolumn
where libname='WORK' and memname='TEST'
;
quit;
%put "&varlist";
proc transpose data=test out=out1;
by id;
var _numeric_;
run;
proc transpose data=test out=out2;
by id;
var _character_;
run;
data out1;
set out1;
val1=coalesce(of col:);
run;
data out2;
set out2;
where compress(_name_)^='id';
val2=coalescec(of col:);
run;
proc transpose data=out1 out=testback1(drop=_name_) name=_name_;
by id;
id _name_;
var val1;
run;
proc transpose data=out2 out=testback2(drop=_name_) name=_name_;
by id;
id _name_;
var val2;
run;
data testback;
&varlist;
merge testback1 testback2;
run;
【在 t********m 的大作中提到】 : 这里的牛人多,再来请教一下。data set 如下: : data test; : input id $1 v1 3 v2 $5-6 v3 8 v4 $10-11; : cards; : a 1 x2 . : a . 3 : a . . x4 : b 1 x2 . : b . 3 : b . . x4
|
g****8 发帖数: 2828 | 25 还可以用sql来写,不过有个前提,就是你最后的dataset里面所有的variable没有
missing,不过,好像不可能。再就是如果数据上了mm级别,可能冗余太多,这个处理
速度慢。
如果你有1000多个变量的话,也要用macro来读变量名。
大概的意思就是
proc sql;
create table test_2 as
select distinct *
from (select distinct t1.id,
t1.v1,
t2.v2,
t3.v3,
t4.v4
from test t1, test t2, test t3, test t4)
where id ne '' and v1 ne '' and v2 ne '' and v3 ne '' and v4 ne ''
;
quit;
所有的重复的地方换成macro variable。
有missing的情况,让谁来改改吧。 |