从excel到SAS导入包含字符和数值的变量

时间:2018-05-22 11:05:43

标签: excel sas character numeric

我在excel中有一个数据集,变量包含字符和数字格式的值。

  

var1 -------- var2

     

352,45 -----< 34,5

当我将它们导入SAS时,var2会丢失,我怎样才能保留或估算"< 34,5"对于var2?

我使用以下代码导入:

PROC IMPORT OUT= data
DATAFILE= "data1.xlsx" 
DBMS=EXCEL REPLACE;
RANGE="Sheet1$"; 
GETNAMES=YES;
MIXED=YES;
SCANTEXT=YES;
USEDATE=YES;
SCANTIME=YES;
RUN;

3 个答案:

答案 0 :(得分:2)

快速回答

使用RegEdit更改Windows注册表项。在我的系统上,Windows 10,x64,Office 2016,条目

...
var r1 = httpClient.GetAsync(url1);
var r2 = httpClient.GetAsync(url2);

var response1 = await r1;
var response2 = await r2;
...

会改为

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\14.0\Access Connectivity Engine\Engines\Excel\TypeGuessRow

解释

0 推断列Proc IMPORT DBMS=EXCEL是数字内容,因为它没有扫描足够多的Excel行来发现有一些非数字内容。因此,当达到非数字内容时,该过程会以缺失值替换它。

你必须

  1. 强制IMPORT扫描足够的行以查找列中的非数字(如果存在)。
    • 导致IMPORT将这些列(变量)定义为字符类型
  2. 在DATA步骤中对导入的数据集进行后处理
    • 执行将期望的数字变量转换为实际数字变量的转换。
  3. 扫描更多行 - Excel

    没有var2选项可用于更改扫描的Excel行数。

    Windows中的

    Proc IMPORT使用Microsoft技术读取Excel文件。在SAS版本< 9.2第2阶段,技术是Jet,新版本使用ACE。这些技术中的每一种都使用 Windows 注册表来获取参数Proc IMPORT DBMS=Excel,该参数是在推断列是字符,数字或日期之前应扫描的行数。当参数值为 0 时,在推断之前会扫描所有行。

    SAS Documentation“SAS /ACCESS®9.4与PC文件的接口:参考,第四版”章节“Microsoft Excel工作簿文件”详细说明了需要更改的 Windows 注册表项在系统和Office安装上。正如快速中提到的,我的系统有

    TypeGuessingRows

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\14.0\Access Connectivity Engine\Engines\Excel\TypeGuessRow 行的默认值已更改为8

    奖励:扫描更多行 - 分隔文件

    这些文本文件的字段由逗号,制表符或其他字符分隔。

    可以使用GUESSINGROWS 语句

    强制

    0扫描所有行

    Proc IMPORT DBMS=CSV

    第2步 - 后处理

    以下是一些示例代码,显示了如何将已知的“棘手”列转换为相同的命名数字列。 规则是值Proc IMPORT --all my options-- out=import_raw; GUESSINGROWS=MAX; * statement; run; 将转换为<####

    ####

    您实际的转化规则可能会有所不同 - 例如,您可能需要添加data import; set import_raw (rename=var2=var2_raw); if var2_raw =: '<' then var2 = input(substr(var2_raw,2), best12.); else var2 = input(var2_raw,best12.); drop var2_raw; run; $1,其中包含值var2_relation=或{{ 1}}。或者,您可以在执行input()转换之前压缩值,删除所有非数字字符。

    如果您在编写对所有变量执行相同转换的解决方案时遇到问题,那将是另一个问题。

答案 1 :(得分:0)

正如其他人所指出的那样,可能Excel引擎扫描的距离不足以找到字符值。

XLSX引擎,我相信9.3并且通常在9.4中的导入和导出功能完全正常,可以更好地扫描变量类型。这很容易使用,只需将DBMS=EXCEL交换为DBMS=XLSX即可。如果你有(例如)GETNAMES=NO,它将不完全相同,但对于大多数用途它是相同的。

PROC IMPORT OUT= data
DATAFILE= "data1.xlsx" 
DBMS=XLSX REPLACE;
SHEET="Sheet1"; 
GETNAMES=YES;
RUN;

答案 2 :(得分:-1)

您是否考虑过使用infile而不是proc import? 此外,如果数字和字符都在同一个colomn中,则需要将其强制为字符。

http://www2.sas.com/proceedings/forum2008/166-2008.pdf

下面的代码是我从循环中获得的一个示例,但您应该能够弄明白。请注意,当在colile语句中跟随colomn后,它会强制colomn成为字符!

 filename file&i "&fdir";   /*THIS ASSIGN FILE NAME RELATED WITH THE DIRECTORY IN PREVIOUS FILE*/
      data &name; /*USE THE FULL PATH OF THE FILE NEEDED AS PER 1ST TABLE*/
LENGTH  BAN $10.;
    LENGTH  SUBSCRIBER_NO   $10.;
    LENGTH  TRANSACTION_DATE    $18.;
    LENGTH  OPT1    $18.;
        INFILE file&i delimiter = ',' MISSOVER DSD LRECL=32767 FIRSTOBS=2 flowover;
        input SUBSCRIBER_NO $   BAN $   OPT1 $  TRANSACTION_DATE $  TRANSACTION_TYPE $  ITEM_ID $   MSID $  NIN1 $  ACTIVATION_TYPE $   STORE_CODE $    OPT8 $  OPT10 $     OPT9 $  WES $   BILL_CYCLE $    LANGUAGE_CODE $     REGION $    COMPANY_CODE $  PRICE_PLAN $    COMMIT_START_DATE $     SYS_CREATION_DATE $     RENEWAL_DATE $  ESN_TYPE $  ACCOUNT_TYPE $  EFFECTIVE_DATE $    INIT_ACTIVATION_DATE $  TENURE $    DATA $  PRICE_PLAN_DATA $   OPT3 $  PRICE_PLAN_DESC $   MSF $   PRICE_PLAN_SERIES $     ACTIVATION_DATE $   OPT5 $  TERM_STATUS $   OPT4 $  FIRST_NAME $    LAST_BUSINESS_NAME $    ADDRESS_ATTENTION $     USER_NAME $     ADDRESS_NAME_1 $    ADDRESS_NAME_2 $    ADDRESS_NAME_3 $    CITY $  province $  POSTAL_CODE $   home_no $   work_no $   MKT_ACCOUNT_TYPE $  ESN_EFFECTIVE_DATE $    CABLE_FOOTPRINT $   COMMON_IND $    CS_VIP_CLASS $  OPT2 $  OPT6 $  OPT7 $  KEYCODE $   CAMPAIGN_CODE $     CAMPAIGN_CYCLE $    CAMPAIGN_DATE $     CAMPAIGN_DESCRIPTION $  CAMPAIGN_TYPE $     EMAIL $     MOP $   SERIAL_NUMBER $     ACTIVATION_SUB_TYPE $   SALES_REP $ ;
      run;

      data import;
        set %if ne 1 %then import;
            &name;
      run;
      %let i = %eval(&i+1);
      filename  file&i clear;