我很难过。
我想将一个非常大的数据集减少到更少的观察值,但是包含原始数据集的所有级别(最多)一次。这样做是为了测试目的,因此我们最好的办法是提出最少数量的最终数据集。
因此,如果我们以数据集SASHELP.CLASS为例。我想找出第一个障碍物(或任何非特异性障碍物,但我觉得它可能更容易使用第一个/最后一个障碍物)覆盖原始数据集的每个单独级别,不所有可能的(现有的或理论上的)所需变量的组合。
输出看起来像这样:(SASHELP.CLASS:AGE,SEX的所有级别):
所以我们最终应该:
芭芭拉,卡罗尔和亨利将不会输出,因为F-M和13-14都被覆盖
输出结束
在这种情况下,我们按顺序遍历数据,并且我们发现满足要求的最小数量的obs(6),但是如果级别变得更长(或相互关联),并且数据被分类(假设我们可以预先-sort),我们最终会得到一些接近最小值的东西,但不是所需变量中最长的最小值。
我认为这需要某种递归算法才能最有效地获得少量的遮挡数值,但不知道从哪里开始。任何帮助将不胜感激!
答案 0 :(得分:1)
这不是一种非常有效的方法,但它可以提供理想的结果
/* sort by first key */
proc sort data=sashelp.class out=minset;
by age;
run;
/* set wantflag to 1 if first.key else wantflag is 0 */
data minset;
set minset;
by age;
if first.age then wantflag = 1;
else wantflag = 0;
run;
/* repeat proc sort and next data step for each consecutive key */
/* sort by second key and by descending wantflag */
proc sort data=minset out=minset;
by sex descending wantflag ;
run;
/* set wantflag to 1 if first.key, do NOT set to 0 if not key */
data minset;
set minset;
by sex;
if first.sex then wantflag = 1;
run;
/* finally keep smallest possible dataset */
data minset (drop=wantflag );
set minset;
if wantflag eq 1 then output;
run;
答案 1 :(得分:0)
我假设你想要一个相当容易实现的算法并产生一个好的(但不一定是最好的)结果。
我的方法是从最稀有的水平开始。
步骤1.根据级别频率对所有类别进行排序。
在您的示例中,我们可能会得到:
AGE
14 117
13 119
11 140
12 154
15 165
16 170
SEX
M 503
F 524
步骤2.从最稀有的剩余水平开始。在我们的案例中,AGE = 14。
然后在(剩下的)每个类别中保留最稀有的剩余等级。 如果你得到一个匹配,那么使用它作为样本。如果没有,那么将搜索增加到更频繁的级别,直到获得命中。勾选你找到的水平。
在SQL中,您可以使用ORDER BY
执行此操作:
SELECT <primary key>,
case when category2 = <lowest remaining freq level for category2> then 1
when category2 = <second lowest remaining freq level for category2> then 2
...
end case AS category2,
case when category3 = <lowest remaining freq level for category3> then 1
when category3 = <second lowest remaining freq level for category3> then 2
...
end case AS category3
FROM table1
WHERE category1 = <lowest remaining freq level for category1>
ORDER BY category2, category3
重复步骤2,直到表示所有级别。
答案 2 :(得分:0)
对数据集进行排序并使用数据步骤中的by
语句仅输出第一个组。
请注意,这是从我之前的帖子更新的。正如其他人指出的那样,这是不正确的。
proc sort data=SASHELP.CLASS out=class_temp;
by AGE descending sex;
run;
data class_temp;
set class_temp;
by AGE;
if first.age then output;
run;
proc sort data=SASHELP.CLASS out=class_temp2;
by sex descending AGE;
run;
data class_temp2;
set class_temp2;
by sex;
if first.sex then output;
run;
proc sort data=class_temp2;
by age;
run;
data combos;
merge class_temp class_temp2;
by age sex;
run;
答案 3 :(得分:0)
您可以使用哈希对象编写一些大致相同的内容。这样做的缺点是它并不完美 - 我列出的例子给出了一个超出你想要的额外项目,因为与细胞相互作用的顺序很重要;并且数据集的初始顺序会影响输出的多样性,因此在下面的示例中,您有很多女性记录,只有两个男性记录,而不是反映初始数据集的多样性,仅仅因为(在我的sashelp.class中,至少在大多数年龄的男性之前都有女性。
data want;
if _n_ = 1 then do;
declare hash recs();
recs.defineKey('keytype');
recs.defineKey('keylist');
recs.defineData('keydata');
recs.defineDone();
format keylist $10. keytype $8. keydata $8.;
call missing(of keylist keytype keydata);
end;
set sashelp.class;
agechar=put(age,3.);
rc_age = recs.check(key: 'age', key:agechar);
rc_sex = recs.check(key:'sex',key:sex);
rc = rc_age+rc_sex;
if rc=0 then delete;
else do;
if rc_age ne 0 then recs.add(key:'age',key:agechar,data:'sex');
if rc_sex ne 0 then recs.add(key:'sex',key:sex,data:'sex');
output;
end;
run;
它分别检查每个密钥的哈希值,如果找到一个带有尚未找到的密钥的记录,它会用这些密钥填充数据集和哈希值。它不会返回并稍后检查是否有更好的解决方案,尽管您可以在传入的数据集上使用不同的(随机)排序顺序运行几次并保留最小的数据集。