我正在尝试解析in()函数中的datastep变量。我有一个数据集,如下所示:
|Run|Sample Level|Samples Tested|
| 1 | 1 | 1-5 |
| 1 | 2 | 1-5 |
...etc
| 1 | 5 | 1-5 |
---------------------------------
| 2 | 1 | 1-4 |
| 2 | 2 | 1-4 |
测试样品随运行而变化。通常,数据集中唯一的样本级别是“样本测试”提供的范围内的那些。但是,有时情况并非如此,并且可能变得凌乱。例如,我研究的最后一个看起来像这样:
|Run|Sample Level|Samples Tested|
| 1 | 1 |2-9, 12-35, 37-40|
在这种情况下,我想删除所有包含未包含在“测试样品”中的样品水平的行,这是通过手动添加代码来完成的:
Data Want;
set Have;
if sample_level not in (2:9, 12:35, 37:40) then delete;
run;
但是我想做的是通过查看“测试样本”列自动完成此操作。将“-”转换为“:”很容易,但是我遇到的困难是让IN()
函数识别或解析变量。我想要看起来像这样的代码:if sample_level not in(Samples_Tested) then delete;
,其中samples_tested已转换为IN()
函数可以处理的东西。如果有人有他们认为可行的解决方案,我也不反对使用proc sql;
。我知道您可以做
Proc sql; Create table want as select * from HAVE where Sample_Level in (Select Samples_Tested from Have); Quit;
但是问题是测试的样品随运行而变化,并且可能有16种不同的运行。希望我已经足够清楚地说明了挑战。感谢您抽出宝贵的时间阅读本文,并提前感谢您的帮助!
答案 0 :(得分:2)
假设对于每个RUN值,SAMPLES_TESTED的值都是恒定的,则可以使用它来生成选择标准。例如,您可以使用_null_数据步骤将WHERE语句写入文件,然后将该代码%include到另一个数据步骤中。
filename code temp;
data _null_;
file code;
if eof then put ';';
set have end=eof;
by run;
if first.run;
if _n_=1 then put 'where ' @ ;
else put ' or ' @ ;
samples_tested=translate(samples_tested,':','-');
put '(' run= 'and sample_level in (' samples_tested '))';
run;
data want;
set have;
%include code;
run;
注意:IN
是运算符,而不是函数。
答案 1 :(得分:0)
很高兴看到SAS代码;-)
这将适用于一个范围:
select * from HAVE where level in (tested);
对于多个范围,我将在MySQL中使用SUBSTRING_INDEX或仅将SUBSTRING和INDEX结合使用以查找下一个条件。 从(已测试(1)中的水平或(已测试2)中的水平或(已测试3)中的水平)中选择*; 例如,在其中将tested1替换为substr(tested,1,index(tested,',')
我使用以下代码生成示例: 创建表有 (运行int, 级别int 经测试的varchar(20)); INSERT INTO拥有(运行,级别,测试) 值(1、1,“ 3-5”); INSERT INTO拥有(运行,级别,测试) 值(1、3,“ 3-5、12:35”); INSERT INTO拥有(运行,级别,测试) 值(1、20,“ 3-5、12-35”);