【问题标题】:Data Cleaning: processing extra if statements vs performing extra assignments数据清理:处理额外的 if 语句与执行额外的分配
【发布时间】:2013-09-18 17:13:37
【问题描述】:

编辑:我明白为什么这是错误的做法(而且我忘记了我过去是如何做到的)并接受了乔的回答。如果有人在比较更多 if 语句与执行额外分配方面有任何 cmets 可以在 SAS 中添加性能考虑因素,我仍然会感兴趣。


首选哪种方法?

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

选项 A:

if value in (
    'A: Wrong Value 1'
    'A: Typo 1'
    'a: Typo 2'
    'A: Wrong Value 2'
  ) then value = 'A: Correct Value';
else if value in (
    'B: Wrong Value 1'
    'B: Wrong Value 2'
    'B: Typo 1'
  ) then value = 'B: Correct Value';
else if value in (
    'C: Wrong Value 1'
    'C: Wrong Value 2'
    'C: Wrong Value 3'
    'C: Typo 1'
  ) then value = 'C: Correct Value';
**etc.  Assume there are a bunch of similar statements;
**with any number of items on the "in" list;

我在这些操作中看到的问题是,每次遇到“A:正确值”时,都必须通过每个 if 语句来处理它。这不是什么大不了的事,但我觉得“A”组的某些东西仍然会通过所有测试一直运行到“Z”组。

所以,我可以这样写:

选项 B

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';

这会阻止它评估超过正确的组(并具有允许您在最后添加类似 else value = 'Not Cleaned'; 的额外优势)。

但是,此版本最终会执行与 if value = 'A: Correct Value' then value = 'A: Correct Value'; 等效的操作。这似乎是一种浪费的操作,尽管它可能比继续检查 if 语句更不浪费。

到目前为止我有:

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

我对此的想法是选项 B 是完成此任务的更好方法。可以访问else 语句并且不必一直发送干净的“A:正确值”到Z 的if 语句似乎比避免if a = 1 then a = 1 构造的任何价值更重要。但我对 SAS 所做的底层活动并不是非常熟悉,因此重新分配操作可能比检查一些额外的 if 语句更耗时。

【问题讨论】:

  • 我想还有第三种选择。您可以添加一个额外的 if 语句来捕获正确的值并且对它们不做任何事情。如果这是第一个 if 语句,并且您的大部分数据都是干净的,那么这可能会节省很多时间。

标签: sas


【解决方案1】:

这些选项都不是特别好的数据清理选项。壁纸编码,即生成大量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 语句列表 - 如果它在此之上是合法的,那么您将获得“合法”值。当然你可以放一些想要的东西而不是'INVALID';如果您希望 99 成为“无效”响应,则将 99 放在那里。

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

【讨论】:

  • 我想我没有想清楚。通常我会在这里做的是有一个“重新编码”数据集,其中一列包含每个唯一值,第二列包含每个唯一值的正确干净值......然后我会按值排序并合并。我不确定您的格式解决方案如何在这里工作。我正在尝试将错误值(它们是字符串)重新分配给清理后的值......所以我想要 6=5(或 1 或任何正确的值)而不是 6=invalid。
  • 您必须更详细地说明您的具体问题,但您当然可以建立这样的格式。如果它是直接重新编码,那么您当然可以以某种格式做到这一点。查找如何使用cntlin 数据集与proc format;你的初始值是start,你重新编码的值是label
  • 这很整洁。不需要对大型数据集进行两次排序(一次到不干净的值,第二次回到有用的值)。最后一个问题:您从什么时候开始对大幅面的性能产生担忧?如果我有 10,000 个杂乱的值可以清理到 1000 个正确值(在 100,000 个观察数据集中),那么 SAS 是否会为具有 10k 个选项的格式而苦苦挣扎? (并不是说我会有 1000 个 if 语句……只是在这里考虑未来)
  • 取决于内存;我认为几十万是可以的,但在标准的 2GB RAM 桌面上,数百万可能会开始成为问题。如果您在具有大量 RAM 的服务器上,那么您是相当安全的。
猜你喜欢
  • 2021-07-19
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多