导入数字列中包含无效字符的数据

时间:2013-07-23 16:11:39

标签: excel csv sas

数据结构:我有一个可以作为Excel或CSV文件读取的数据集。它具有以下变量类型:日期,时间,数字变量,以及应该是错误地将字符附加到数字的数字变量 - 例如-0.011 *和0.023954029324)(最后的括号在单元格中) - 由于编写文件的程序出错。每条记录之间也有空行,删除所有这些内容是不现实的,因为我有数百个要管理的文件。

DATA ISSUE:我们已经确定某些值在字符前是正确的(例如,只要删除了星号,-0.011就是正确的),而其他值,例如0.023954029324),则完全不正确,应该是失踪。请不要对此问题发表评论,因为它不受我的控制,此时我所能做的就是管理数据,直到错误得到修复并且字符值停止写入文件。

SAS问题:

1)如果我将PROC IMPORT与Excel文件一起使用,SAS会使用前八行(CSV文件为20行)来确定变量是数字还是字符。如果括号的星号未出现在前20行中,则SAS表示该变量为数字,然后使任何后续单元格缺少字符值。对于星号,这是不可行的,因为我想维护值的数字部分并在以后的数据步骤中删除星号。使用PROC IMPORT导入Excel文件不允许使用GUESSINGROWS选项(因为它使用CSV文件,见下文)。编辑:此外,MIXED = YES选项不起作用(请参阅下面的评论 - 仍然需要更改SAS使用的行数,对我来说,这意味着此选项会...什么?)。

2)如果我将PROC IMPORT与CSV文件一起使用,我可以指定GUESSINGROWS = 32767并且我非常兴奋,因为它确定了星号是字符并保持星号的变量。但是,非常奇怪的是,不再将带括号的变量确定为字符(就像在导入Excel文件时一样,只要括号位于前20行中),而是删除字符并另外将值舍入为最接近的整数(0.1435980234变为0,1.82149023843变为2等)。这太圆了 - 我需要保持小数位。而且,最重要的是,括号现在已经消失,因此我无法使相应的单元格丢失。我不知道是否有办法使SAS不圆和/或保持括号。对我来说,这是不一致的行为 - 为什么星号而不是括号在这种情况下被认为是一个字符?此外,当我读取带有PROC IMPORT的Excel文件(如(1)中所述)时,可以处理括号(如果它们出现在前20行中) - 另一个不一致。

3)如果我使用INFILE,那么 - 我得到一个错误w /我尝试读入的每个变量 - 这个过程对于数据变化的方式过于敏感和不稳定(我必须编写一个解决方法)对于空白数据行。)

终极目标(请注意,如果这很重要,此代码将在宏中自动运行):

1)将日期变量读取为日期

2)将时间变量读取为时间

3)能够识别该变量的任何单元格中存在的变量(即使在20行之后)作为字符变量,并保持单元格中的值(即不舍入/删除字符)。这可以通过先验告诉SAS让一组变量成为字符(我会在删除字符/使单元格丢失后将它们更改为数字),或者通过SAS识别变量w /字符本身。

1 个答案:

答案 0 :(得分:1)

  1. SAS实际上默认使用前8行。这是在注册表设置TYPEGUESSROWS中定义的 - 通常存储在HKLM \ Software \ Microsoft \ Office \ 14.0 \ Access Connectivity Engine \ Engines \ Excel \ TypeGuessRows \(或插入您的办公室版本 - 那里)。将该值更改为FFFF(十六进制)/ 65536(十进制)或其他一些大数字,或者为零以搜索最大行数(超过16000位 - 很难找到确切的数字)。

  2. 对于CSV文件,您可以编写数据步骤导入来控制每个变量的格式。最简单的方法是运行PROC IMPORT,然后检查您的日志;日志将包含用于在数据步骤中读取文件的完整代码。然后根据需要修改信息。你说你对Infile方法有太多的麻烦,所以也许这对你不起作用,但通常你可以解决任何不一致的问题 - 如果你的文件不一致,听起来你会做大量的手工工作无论如何。这为您提供了正确读取日期/时间变量的选项。

  3. 您还可以将PROC IMPORT / CSV用于日志,将日志写入文件,然后读取并自行生成新的导入代码 - 甚至关闭生成文件的proc内容,做出已知修改。

  4. 不确定您对日期/时间的询问,因为您在问题的第一部分没有提及问题。

    您有一个额外的选项是在读入之前清除字符(来自CSV)。这很简单,如果它真的只是数字和逗号(以及小数和负号):

    data mydata;
    infile myfile /*options*/;
    input @@;
    length infileline $32767; *or your longest reasonable line;
    infileline = compress(_infile_,'.-','kd');
    run;
    
    data _null_;
    set mydata;
    file myfile /*options*/ /*or a new file if you prefer */;
    put @1 infileline $32767.; *or your longest reasonable line;
    run;
    

    然后使用proc import读取该新文件。我将它拆分为两个数据包,以便您可以看到它,但您可以将它们组合成一个以便于运行 - 在SAS文档中查找“就地更新文件”。您还可以使用特定于OS的工具完成此清理工作;例如,在Unix上,一个简短的awk脚本可以轻松删除行为不端的字符。