Sas 数据清理:处理额外的if语句与执行额外的赋值

Sas 数据清理:处理额外的if语句与执行额外的赋值,sas,Sas,编辑:我明白为什么这样做是错误的(我忘记了我过去是怎么做的),我接受了乔的答案。如果有人对SAS中关于比较更多if语句与执行额外任务的性能注意事项有任何意见,我仍然很感兴趣 以下哪种方法是首选的 通过将多个变体/键入组合成一个正确值来清理某些数据时, 我可以这样做: 备选方案A: 我看到的这些操作的问题是,每次遇到'A:Correct Value',都必须通过每个if语句来处理它。这不是什么大不了的事,但我觉得“a”组到“Z”组的所有测试都会运行,这是不对的 因此,我可以写它: 方案B 这会阻

编辑:我明白为什么这样做是错误的(我忘记了我过去是怎么做的),我接受了乔的答案。如果有人对SAS中关于比较更多if语句与执行额外任务的性能注意事项有任何意见,我仍然很感兴趣


以下哪种方法是首选的

通过将多个变体/键入组合成一个正确值来清理某些数据时, 我可以这样做:

备选方案A: 我看到的这些操作的问题是,每次遇到'A:Correct Value',都必须通过每个if语句来处理它。这不是什么大不了的事,但我觉得“a”组到“Z”组的所有测试都会运行,这是不对的

因此,我可以写它:

方案B 这会阻止它通过正确的组进行计算(并且还有一个额外的优点,即允许您在末尾添加类似
else value='notcleanned';

然而,这个版本最终执行了与
等效的操作,如果value='A:Correct value',那么value='A:Correct value'。这看起来像是一个浪费的操作,尽管它可能比检查if语句的浪费更少

到目前为止,我已经:

  • 选项A
    • 优点:
      • 短码
      • 仅重新分配不正确的值(无
        如果a=1,则a=1
    • 缺点:
      • 当一个值不需要清理时,它将必须继续执行每个if语句
      • 不能用else子句结束
  • 选项B
    • 优点:
      • 对于干净值和不干净值,评估将在正确的组停止
      • 可以使用
        else
        子句捕获所有未清除的值(如果您更新基础数据并希望使用新值执行其他操作,则会很有用)
      • “in”列表包含映射到单个干净值的所有值(如果以编程方式生成这些值,可能会有所帮助)
    • 缺点:
      • 如果a=1,则必须执行
        操作,然后a=1
        操作
      • 代码稍微长一些,因为必须写出两次正确的值

我的想法是,选择B是实现这一目标的更好方式。访问
else
语句,并且不必一直发送一个干净的“a:Correct Value”到Z的if语句,这似乎超过了避免使用
if a=1则a=1构造的任何值。但我对SAS的底层活动并不十分熟悉,因此重新分配操作可能比检查一些额外的if语句更耗时。

对于数据清理,这两个选项都不是特别好的选项。墙纸编码,即生成大量的
IF
语句,效率极低,难以读取/维护,写入速度较慢。它还将数据存储在程序中,这是不可取的;良好的编程习惯将数据与代码分开,这样,如果您的数据发生更改,您只需修改(其他)数据,而不是修改您的程序

单值数据清理(即检查)最好使用格式。如果愿意,您可以在程序中编写一种格式,但更好的方法是在数据集(或excel工作表、数据库表或其他任何地方)中维护该格式

一个简单的格式解决方案:

proc format;
value q01f
1-5  = [F1.0]
other= INVALID;
quit;

data test;
input x;
x_fixed = put(x,q01f.);
if put(x,Q01f.)='INVALID' then ; *take action here;
put x= x_fixed=;
datalines;
1
2
3
6
8
5
4
1
;;;;
run;
其中,值1至5为“合法”,其他值编码为“无效”。你可以用它来代替你的IF语句列表,如果它是合法的,你可以得到“合法”值。当然,你可以把想要的东西,而不是“无效的”;如果您希望99是“无效”响应,则将99放在那里


这不仅非常快(比多个IF语句或布尔语句快),而且易于维护。将这些合法值和格式名称放入excel文件中。您不仅可以获得易于维护的合法值列表(可以由非程序员维护),还可以免费获得数据字典。

我想还有第三种选择。您可以添加一个额外的if语句,该语句捕获正确的值,并且不处理这些值。如果这是第一个if语句,并且您的大多数数据都是干净的,那么这可能会节省很多时间。我想我没有想清楚。通常我在这里要做的是有一个“重新编码”数据集,其中一列包含每个唯一值,另一列包含每个唯一值的正确干净值……然后我会按值排序并合并。我不确定您的格式解决方案在这里是如何工作的。我正在尝试将坏值(即字符串)重新分配给清理后的值…因此,我希望6=5(或1或任何正确的值)而不是6=invalid。您必须更详细地说明您的具体问题,但您当然可以建立这样的格式。如果是直接重新编码,您当然可以在一种格式中完全这样做。查看如何使用具有
proc格式的
cntlin
数据集;初始值为
start
,重新编码的值为
标签
。这很好。不需要对大型数据集进行两次排序(一次排序为不干净的值,第二次排序为有用的值)。最后一个问题:您从什么时候开始对大格式产生性能问题?如果我有10000个凌乱的值,可以清除多达1000个正确的值(在100000个观测数据集中),SAS是否会与具有10k选项的格式斗争?(并不是说我会有1000条if语句……只是在这里思考未来)取决于记忆;我认为在标准的2GB内存桌面上,几十万个就可以了,但数百万个可能开始成为一个问题。如果你在一个有大量RAM的服务器上,你是相当安全的。
if value in (
    'A: Correct Value'
    'A: Wrong Value 1'
    'A: Typo 1'
    'a: Typo 2'
    'A: Wrong Value 2'
  ) then value = 'A: Correct Value';
else if value in (
    'B: Correct Value'
    'B: Wrong Value 1'
    'B: Wrong Value 2'
    'B: Typo 1'
  ) then value = 'B: Correct Value';
else if value in (
    'C: Correct Value'
    'C: Wrong Value 1'
    'C: Wrong Value 2'
    'C: Wrong Value 3'
    'C: Typo 1'
  ) then value = 'C: Correct Value';
proc format;
value q01f
1-5  = [F1.0]
other= INVALID;
quit;

data test;
input x;
x_fixed = put(x,q01f.);
if put(x,Q01f.)='INVALID' then ; *take action here;
put x= x_fixed=;
datalines;
1
2
3
6
8
5
4
1
;;;;
run;