1

对于我们的分析,我们需要从 csv (xls) 读取原始数据并将其转换为 SAS 数据集,然后再进行分析。

现在,问题是这些原始数据通常有两个问题: 1. 列的顺序有时会发生变化。因此,如果在早期我们有按变量顺序排列的列 A,然后是 B,然后是 C,等等。它可能会变为 B,然后是 C,然后是 A。 2. 有诸如“#”或“”之类的外来元素。 ”,或“一些字母”等。现在,我们必须先清理原始数据,然后再读入 SAS。这需要相当长的时间。有什么方法可以在读取数据之前清理 SAS 系统本身的数据。如果我们可以用 SAS 代码对数据进行校正,那将节省相当多的时间。

这是示例:

第 1 阶段:我以这种格式获取 Data1.csv 中的数据。在数字列 B 中,我有“#”和“.”。还有C列,也是数字,我有“g”。如果我使用 PROC IMPORT 或 Infile 语句导入 Data1.csv,则 B & C 列中的这些外来元素将保留。这里的问题是如何做到这一点?我可以使用 If STATEMENT。但问题是外来元素太多(例如,不是“#”、“.”、“g”,我可能会得到其他外来元素,如“$”、“h”等)如果有什么办法可以每次在 SAS 中导入原始数据时,我都无需使用 IF STATEMENT 指定它来检测和删除外来元素的代码。

   A    B   C
Name1   1   5
Name2   2   6
Name3   3   4
Name4   #   g
Name5   5   3
Name6   .   6

第 2 期:在此期间,我得到了 DATA2.csv,如下所示。当我使用 INFILE 语句时,我指定应使用特定名称读取第一个 A,然后使用特定名称读取 B,然后是 C。在第二个周期中,当我获得数据时,B 被赋予第一个。因此,当 SAS 读取数据时,我使用的是 B 而不是 A。所以,我必须每次都检查变量与前一阶段数据的顺序并在使用 infile 语句读取数据之前对其进行更正。由于变量的数量太大,以这种方式验证列排序非常耗时(有时令人沮丧)。是否有 SAS 代码,SAS 会自动读取 A,然后是 B,然后是 C,即使它不是这个顺序?

B   A   C
1   Name1   5
2   Name2   6
3   Name3   4
#   Name4   g
5   Name5   3
.   Name6   6

尽管我主要在分析目的中使用 SAS。但我可以使用 R 来清理数据,然后在 SAS 中读取数据以进行进一步分析。所以 R 代码也很有帮助。

谢谢。

4

2 回答 2

3

在 R 中,当您指定列是特定类时,您会提高文件读取速度。使用提供的示例(3 列,中间一列是“字符”,您可以使用以下代码:

 dat <- read.csv( filename, colClasses=c("numeric", "character", "numeric"), comment.char="")

“#”和“.” 在数字列中遇到时将变为 NA 值。上面的代码删除了注释字符的默认规范,即“#”。如果你想要“#”和“.” 要强制转换为 NA_character_ 的字符列中的条目,您可以使用以下代码:

dat <- read.csv( filename, 
                 colClasses=c("numeric", "character", "numeric"),
                 comment.char="",
                 na.strings=c("NA", ".", "#") )

默认情况下,该header=TRUE设置由 read.csv() 假定,但如果您使用 read.table(),则需要header=TRUE使用您显示的两个文件结构进行断言。这里有进一步的文档和读取 Excel 数据的工作示例:但是,我的建议是按照您计划和使用 CSV 传输的方式进行操作。通过这种方式,您将更快地看到 Excel 对日期和缺失值所做的棘手事情。建议您将数据格式更改为与 POSIX 标准一致的自定义“yyyy-mm-dd”,在这种情况下,您还可以指定“日期”分类列并跳过将字符分类列转换为默认的 Excel 格式(所有这些都是错误的)转换为日期。

于 2012-08-25T19:48:46.060 回答
2

是的,您可以使用 SAS 进行您想象的任何类型的“数据清理”。SAS DATA 步语言充满了执行此类操作的功能,但没有灵丹妙药;您需要自己编写代码。

csv文件只是一个纯文本文件(与文件非常不同)xls。通常,文件中的第一行csv包含列名,数据从第二行开始。如果使用PROC IMPORT,SAS 将使用第一行来构造变量名,并尝试通过扫描文件的前几行来确定数据类型。例如:

proc import datafile='c:\temp\somefile.csv'
     out=SASdata
     dbms=csv replace;
run;

或者,您可以使用数据步骤读取文件。这需要您提前知道文件布局。例如:

data SASdata;
   infile 'c:\temp\somefile.csv' dsd firstobs=2 lrecl=32767 truncover;
   informat A $50.; /* A character variable with max length 50 */
   informat B yymmdd10.; /* A date presented like 2012-08-25 */
   informat C dollar12.; /* A number containing dollar sign, commas, or decimals */

   input A B C;  /* The order of the variables in the file */

   if B = . then B = today(); /* A possible data cleaning statement */
run;

请注意,INPUT 语句控制变量在文件中存在的顺序。关键是您使用的代码必须与您处理的每个文件的布局相匹配。

这些只是一般性评论。如果您遇到问题,请回复更具体的问题。

针对已更新问题的更新:原始数据文件中的变量必须以与每个文件中存在的顺序相同的顺序列在 INPUT 语句中。此外,您需要直接定义列类型,并建立它们需要遵循的任何规则。无法自动执行此操作;每个文件大都分开处理。

在这种情况下,假设您的变量是 A、B 和 C,其中 A 是字符,B 和 C 是数字。该程序可能会处理这两个文件并将它们添加到历史数据集(假设为 ALLDATA):

data temp;
   infile 'c:\temp\data1.csv' dsd firstobs=2 lrecl=32767 truncover;
   /* Define dataset variables */
   informat A $50.;
   informat B 12.;
   informat C 12.;
   /* Add a KEEP statement to keep only the variables you want */
   keep A B C;

   input A B C;
run;
proc append base=ALLDATA data=temp;
run;
data temp;
   infile 'c:\temp\data2.csv' dsd firstobs=2 lrecl=32767 truncover;
   informat A $50.;
   informat B 12.;
   informat C 12.;

   input B A C;
run;
proc append base=ALLDATA data=temp;
run;

请注意,每个数据步骤的“数据定义”部分是相同的;唯一的区别是INPUT语句中列出的变量的顺序。请注意,因为变量 A 和 B 被定义为数字,所以当读取这些无效字符(# 和 g)时,这些值将存储为缺失值。

在您的情况下,我将创建一个模板 SAS 程序,以按照您期望的顺序定义您想要的所有变量。然后使用该模板按照该文件中变量的顺序导入每个文件。设置模板程序可能需要一些时间,但要运行它,您只需要修改 INPUT 语句。

于 2012-08-25T18:18:19.317 回答