【问题标题】:import variables with both character and numeric values from excel to SAS将具有字符和数值的变量从 excel 导入 SAS
【发布时间】:2018-05-22 11:05:42
【问题描述】:

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

var1 -------- var2

352,45 -----

当我将它们导入 SAS 时,var2 丢失了,如何为 var2 保留或估算“

我使用如下代码导入:

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

【问题讨论】:

  • 你是如何导入数据的?日志显示什么?
  • 我在帖子中添加了代码
  • 您是否尝试过使用XLSX 引擎而不是EXCEL 引擎?
  • 另见this question

标签: excel sas character numeric


【解决方案1】:

快速解答

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

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

会变成

0

解释

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

你必须这样做

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

扫描更多行 - Excel

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

Proc IMPORT DBMS=Excel 在 Windows 中使用 Microsoft 技术来读取 Excel 文件。在 SAS 版本 Windows 注册表来获取参数TypeGuessingRows,即在推断列是字符、数字或日期之前应该扫描多少行。当参数值为0时,在推断之前扫描所有行。

SAS Documentation“SAS/ACCESS® 9.4 Interface to PC Files: Reference, Fourth Edition”章节“Microsoft Excel 工作簿文件”详细介绍了需要根据系统更改的 Windows 注册表项和办公室安装。正如快速中提到的,我的系统有

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

8 行的默认值已更改为 0

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

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

Proc IMPORT DBMS=CSV 可以通过使用 GUESSINGROWS 语句

强制扫描所有行
Proc IMPORT --all my options-- out=import_raw;
  GUESSINGROWS=MAX; * statement;
run;

第 2 步 - 后处理

这里是一些示例代码,展示了如何将已知的“棘手”列转换为同名的数字列。 规则是将值<#### 转换为####

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;

您的实际转换规则可能会有所不同——例如,您可能需要添加一个$1var2_relation,该列采用值=&lt;&gt;。或者您可以在进行 input() 转换之前压缩该值,删除所有非数字字符。

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

【讨论】:

  • 谢谢,但 GUESSINGROWS 不适用于 excel 文件,而仅适用于 csv。有什么东西可以为 excel 做同样的工作吗?
  • var2 首先在 Excel 的哪一行显示
  • 只存在于Excel文件的第27行和第30行。
  • 您必须更改 Windows 注册表设置。查看更新的答案
  • 我认为如果您使用 XLSX 引擎而不是 EXCEL 引擎,那么您不需要更改它检查的行数。它应该检查整个列。
【解决方案2】:

正如其他人所指出的那样,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;

【讨论】:

  • 什么不起作用?? DBMS=XLSX 在 9.4 中确实有效。它不能解决您的字符/数字问题吗?
  • 这是我使用 XLSX 得到的日志:(Excel 不会发生这种情况) 3365 PROC IMPORT OUT= data1 3366 DATAFILE= "data.xlsx" 3367 DBMS=XLSX REPLACE;第3368章第3369章3370 运行;错误:在电子表格中找不到工作表注:SAS 系统因错误而停止处理此步骤。注意:PROCEDURE IMPORT 使用(总处理时间):实时 0.04 秒 cpu 时间 0.00 秒
  • 如果您只想要第一张纸,则不需要SHEET= 语句。您确定该文件是实际的 XLSX 文件吗?复制一份并将扩展名更改为 ZIP 并检查您是否可以在 ZIP 文件中看到 XML 文件。
  • 现在我可以看到数字和字符值,但是当我尝试将数据集与其他数据集组合时,我收到以下错误,错误:变量 day__14 已被定义为字符和数字。错误:变量 day_2 已被定义为字符和数字。我使用 put(day_2,6.) 将所有转换为字符,但我仍然得到同样的错误
【解决方案3】:

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

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

下面的代码是我从循环中获得的示例,但您应该能够弄清楚。请注意,当 infile 语句中的列后跟 $ 时,它会强制该列为字符!

 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;  

【讨论】:

  • 这只有在 Excel 数据先导出到 csv 文件时才有效。
  • 谢谢!在您链接的这个网页中,当office有2013版左右时,有更改windows注册表设置的信息,但没有2016版的信息。我的office版本是2016,你知道如何更改注册表设置吗?
  • 您可以在 RegEdit 中四处寻找或使用 RegEdit 查找功能找到 TypeGuessingRows 的条目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多