大型数据集行的随机排列
Random Permutation of Rows of a Large Dataset
我需要为超过 300 万行的数据集创建随机排列。
我尝试使用 PROC PLAN,基于此示例:http://support.sas.com/kb/23/977.html 根据这篇文章,有 n =(行数)!允许随机选择排列。不幸的是,对于这个大小的集合,它有 4.3*10^19668676 个排列。显然我 运行 在这里遇到了一点内存问题。
我还找到了一个使用 PROC IML 的示例,但看起来我的公司没有必要的 licence/software 包来使用它。
任何人都可以提供一个打乱这个数据集的好方法吗?
听起来您想获取行并将它们按随机顺序排列。如果是这样,最常见的方法是为每一行创建一个随机值,然后按随机值排序:
DATA augmented ;
SET original ;
sortval = RAND('UNIFORM') ;
RUN ;
PROC SORT DATA=augmented OUT=permuted(DROP=sortval) ;
BY sortval ;
RUN ;
如果您希望以后能够精确地再现随机序列,您可以使用 CALL STREAMINIT(seedval) 调用例程。
您也可以使用 PROC SQL [未测试代码]:
PROC SQL ;
CREATE TABLE permuted(DROP=sortval) AS
SELECT a.*, RAND('UNIFORM') AS sortval
FROM original a
ORDER BY sortval
;
QUIT ;
这将创建数据的随机洗牌并将随机数种子保存为数据中的列和元数据。您可以省略一个或两个,但我喜欢让 SAS 生成种子并让我保存它以便我可以重现 sample/shuffle。使用 VIEW,以便将观察结果直接输送到 PROC SORT。
data shuffle / view=shuffle;
obs = _n_;
set sashelp.cars;
if _n_ eq 1 then call streaminit(0);
r = rand('uniform');
retain seed;
if _n_ eq 1 then seed=symgetn('sysrandom');
run;
proc sort data=shuffle out=shuffle01;
by r;
run;
%put NOTE: &=sysrandom;
proc datasets nolist;
modify shuffle01(label="SEED=&sysrandom");
run;
quit;
proc contents;
run;
proc print;
run;
和路德维希61说的一样,我会做下面的事情
DATA augmented ;
SET original ;
call streaminit(12072015)*optional, if you want to set a seed;
sortval1 = RAND('UNIFORM') ;
sortval2 = RAND('UNIFORM') ;
sortval3 = RAND('UNIFORM') ;
RUN ;
PROC SORT DATA=augmented OUT=permuted(DROP=sortval1 sortval2 sortval3) ;
BY sortval1 sortval2 sortval3;
RUN ;
由于仅使用一个随机数会 运行 发生碰撞,因此您可以添加更多随机数,直到您知道不会得到任何重复值为止,然后按这些随机数排序.鉴于 Rand('Uniform') 函数的周期为 2^19937-1,您应该可以使用 3——在这种情况下,您唯一的敌人是 SAS 的 t运行cation 在 53 位之后。
我需要为超过 300 万行的数据集创建随机排列。
我尝试使用 PROC PLAN,基于此示例:http://support.sas.com/kb/23/977.html 根据这篇文章,有 n =(行数)!允许随机选择排列。不幸的是,对于这个大小的集合,它有 4.3*10^19668676 个排列。显然我 运行 在这里遇到了一点内存问题。
我还找到了一个使用 PROC IML 的示例,但看起来我的公司没有必要的 licence/software 包来使用它。
任何人都可以提供一个打乱这个数据集的好方法吗?
听起来您想获取行并将它们按随机顺序排列。如果是这样,最常见的方法是为每一行创建一个随机值,然后按随机值排序:
DATA augmented ;
SET original ;
sortval = RAND('UNIFORM') ;
RUN ;
PROC SORT DATA=augmented OUT=permuted(DROP=sortval) ;
BY sortval ;
RUN ;
如果您希望以后能够精确地再现随机序列,您可以使用 CALL STREAMINIT(seedval) 调用例程。
您也可以使用 PROC SQL [未测试代码]:
PROC SQL ;
CREATE TABLE permuted(DROP=sortval) AS
SELECT a.*, RAND('UNIFORM') AS sortval
FROM original a
ORDER BY sortval
;
QUIT ;
这将创建数据的随机洗牌并将随机数种子保存为数据中的列和元数据。您可以省略一个或两个,但我喜欢让 SAS 生成种子并让我保存它以便我可以重现 sample/shuffle。使用 VIEW,以便将观察结果直接输送到 PROC SORT。
data shuffle / view=shuffle;
obs = _n_;
set sashelp.cars;
if _n_ eq 1 then call streaminit(0);
r = rand('uniform');
retain seed;
if _n_ eq 1 then seed=symgetn('sysrandom');
run;
proc sort data=shuffle out=shuffle01;
by r;
run;
%put NOTE: &=sysrandom;
proc datasets nolist;
modify shuffle01(label="SEED=&sysrandom");
run;
quit;
proc contents;
run;
proc print;
run;
和路德维希61说的一样,我会做下面的事情
DATA augmented ;
SET original ;
call streaminit(12072015)*optional, if you want to set a seed;
sortval1 = RAND('UNIFORM') ;
sortval2 = RAND('UNIFORM') ;
sortval3 = RAND('UNIFORM') ;
RUN ;
PROC SORT DATA=augmented OUT=permuted(DROP=sortval1 sortval2 sortval3) ;
BY sortval1 sortval2 sortval3;
RUN ;
由于仅使用一个随机数会 运行 发生碰撞,因此您可以添加更多随机数,直到您知道不会得到任何重复值为止,然后按这些随机数排序.鉴于 Rand('Uniform') 函数的周期为 2^19937-1,您应该可以使用 3——在这种情况下,您唯一的敌人是 SAS 的 t运行cation 在 53 位之后。