【发布时间】:2015-10-20 15:56:25
【问题描述】:
假设我的数据集有很多缺失/无效值,如果它包含太多无效值,我想删除(或删除)整个变量(或列)。
以下面的例子为例,变量'gender'有相当多的“#N/A”。如果其中一定比例的数据点是“#N/A”,我想删除该变量,比如超过 50%,超过 30%。
此外,我想将百分比设为可配置值,即,如果该变量下超过 x% 的观察结果为“#N/A”,我愿意删除整个变量。而且我还希望能够定义什么是无效值,可以是“#N/A”,可以是“无效值”,可以是“”,可以是我预先定义的任何其他值。
data dat;
input id score gender $;
cards;
1 10 1
1 10 1
1 9 #N/A
1 9 #N/A
1 9 #N/A
1 8 #N/A
2 9 #N/A
2 8 #N/A
2 9 #N/A
2 9 2
2 10 2
;
run;
请使解决方案尽可能通用。例如,如果真实数据集包含数千个变量,我需要能够遍历所有这些变量,而不是一一引用它们的变量名。此外,数据集可能不仅包含“#N/A”作为错误值,还包含“.”、“Invalid Obs”、“N.A.”等其他内容。也可以同时存在。
PS:其实我想了一个办法让这个问题变得更简单。我们可能可以将所有数据点作为数值读入,这样所有“#N/A”、“N.A.”、“”的东西都会变成“.”,这使得丢弃标准更容易。希望能帮到你为我解决这个问题……
更新:下面是我正在处理的代码。卡在最后一个街区。
data dat;
input id $ score $ gender $;
cards;
1 10 1
1 10 1
1 9 #N/A
1 9 #N/A
1 9 #N/A
1 8 #N/A
2 9 #N/A
2 8 #N/A
2 9 #N/A
2 9 2
2 10 2
;
run;
proc contents data=dat out=test0(keep=name type) noprint;
/*A DATA step is used to subset the test0 data set to keep only the character */
/*variables and exclude the one ID character variable. A new list of numeric*/
/*variable names is created from the character variable name with a "_n" */
/*appended to the end of each name. */
data test0;
set test0;
if type=2;
newname=trim(left(name))||"_n";
/*The macro system option SYMBOLGEN is set to be able to see what the macro*/
/*variables resolved to in the SAS log. */
options symbolgen;
/*PROC SQL is used to create three macro variables with the INTO clause. One */
/*macro variable named c_list will contain a list of each character variable */
/*separated by a blank space. The next macro variable named n_list will */
/*contain a list of each new numeric variable separated by a blank space. The */
/*last macro variable named renam_list will contain a list of each new numeric */
/*variable and each character variable separated by an equal sign to be used on*/
/*the RENAME statement. */
proc sql noprint;
select trim(left(name)), trim(left(newname)),
trim(left(newname))||'='||trim(left(name))
into :c_list separated by ' ', :n_list separated by ' ',
:renam_list separated by ' '
from test0;
quit;
/*The DATA step is used to convert the numeric values to character. An ARRAY */
/*statement is used for the list of character variables and another ARRAY for */
/*the list of numeric variables. A DO loop is used to process each variable */
/*to convert the value from character to numeric with the INPUT function. The */
/*DROP statement is used to prevent the character variables from being written */
/*to the output data set, and the RENAME statement is used to rename the new */
/*numeric variable names back to the original character variable names. */
data test2;
set dat;
array ch(*) $ &c_list;
array nu(*) &n_list;
do i = 1 to dim(ch);
nu(i)=input(ch(i),8.);
end;
drop i &c_list;
rename &renam_list;
run;
data test3;
set test2;
array myVars(*) &c_list;
countTotal=1;
do i = 1 to dim(myVars);
myCounter = count(.,myVars(i));
/* if sum(countMissing)/sum(countTotal) lt 0.5 then drop VNAME(myVars(i)); */
end;
run;
问题是,我陷入困境的地方是我无法删除我想要删除的变量。原因是我不想在 drop 函数中使用变量名。相反,我希望它在一个循环中完成,我可以使用循环器“i”引用变量名。我尝试使用数组“myVars(i)”,但它似乎不适用于 drop 函数。
【问题讨论】:
-
Stack Overflow 不是代码生成服务。您应该尝试解决这个问题,并提出有关您的解决方案的问题 - 而不仅仅是要求解决一个重大问题。
-
我同意乔的观点——你似乎已经对自己想要做什么有了一个相当清晰的想法,所以先自己动手吧。如果您在某个特定步骤上遇到困难,请务必发布您的代码并寻求帮助。
-
现在我提供了更多详细信息和我正在处理的代码,请删除你的拇指,因为我不再要求代码生成服务,@Joe
-
感谢您改进您的问题。
-
改进很多。谢谢。
标签: sas