如何使用简单的输入语句在 SAS 中读取长(或宽)数据集?

How can I read in long (or wide) data sets in SAS using a simple input statement?

提问人:glico 提问时间:4/10/2023 最后编辑:glico 更新时间:4/12/2023 访问量:55

问:

我想使用 do 循环转置数据而不使用 proc 转置。有问题的数据集是如下所示的 .csv 文件:

站点 ID 1 AQS 3(常见问题解答) 3 代码 2
最大1
最小销售值0.3
数量23
站点 ID 1 AQS 3(常见问题解答) 3 代码 2
最大3
最小销售值0.028
数量22
站点 ID 1 AQS 3(常见问题解答) 3 代码 2
最大10
最小销售值0.0005
数量20

换句话说,我有我感兴趣的变量 Max、MinSaleValue 和 Count,它们由指示 SiteID、AQS 和 Code 的标头分隔。

同样,当我有标题时,我对如何使宽数据变长感到困惑。

在这种情况下,我有一些看起来像这样的东西:

站点 ID AQS的 法典 最大1 最小值1 数量1 最大2 ...
1 1 2 3 0.5 23 5 ...
2 1 1 5 0.02003 21 7 ...

注意:尾随表示我对后续列有 200 个 max、min 和 count 值的重复。因此,在包含 siteID、AQS 和 Code 的标头之后,我有 (max1,min1,count1,max2,min2,count2,max3,min3,count3.....等等)。 我也想使用数组和 do 循环使这个宽数据很长,但我遇到了类似的问题,不知道如何读取数据。

对于长数据:

像这样读取数据:

data InputDS.LongData;
infile RawData('Long Data.csv') dlm='092C'x dsd truncover firstobs=7 *skip 7 lines to get rid of descriptive header;
*input _SiteID _AQS _Code;

返回一个看起来喜欢这样的表:

站点 ID 1 AQS 3(常见问题解答) 3 代码 2
.
.
.
站点 ID 1 AQS 3(常见问题解答) 3 代码 2
.
.
.
站点 ID 1 AQS 3(常见问题解答) 3 代码 2
.
.
.

. . . 等等,我有大约 200 个这样的观察结果。

换句话说,我保留了标头,但没有保留我想用数组和 do-loop 扩展的长瘦数据。我的最终结果将包含所有 200 个观测值的 SiteID、AQS、Code 和三个变量(最大值、最小值、计数)。

如果分隔这些的标题不存在(或者如果我只需要担心站点 ID),这似乎很简单。但是,我对如何处理标题有点茫然。

对于宽数据:

对于这个,我什至不确定如何输入所有变量,到目前为止我有这个:

data InputDS.WideData;
infile RawData('Wide Data.csv') dlm=',' dsd truncover firstobs=6 *skip descriptive header of data by reading in from 6th line onwards;
*input _all_;*

但不太确定从哪里开始。我想读取数据集中存在的每个变量,然后使用我的方法将所有最大值、最小值和计数获取到它们自己的数组中,并使用 do 循环来“延长”这些数据,但我已经卡住了如何读取这些数据。

数组 循环 输入 SAS 转置

评论

0赞 Richard 4/10/2023
最小最大计数值在 csv 中的哪个位置?它们是行标题的一部分吗?AQS3 和 Code2 列中的值对于节的所有行(节是属于标题的行)是否相同。如果您输入和累加具有 name=value 对的行,您将需要在阅读 csv 后进行 SORT 和 TRANSPOSE
0赞 Tom 4/10/2023
请更正您的示例,以便清楚输出值的来源。将一些值放入 AQS3 和 CODE2 单元格中。此外,请确保输入和输出上的变量名称匹配。例如,输入具有变量 AQS3 和 CODE2,但输出具有 AQS 和 CODE。输入有MAX1、MAX3和MAX10,输出有MAX1和MAX2。
0赞 Tom 4/10/2023
您能否显示示例 CSV 文件的实际文本,而不是您现在拥有的那些表格内容?
0赞 glico 4/10/2023
@Tom AQS2 和 CODE2 下没有输入。这些是“标头”所以我试图让行看起来像:(SiteID1,AQS3,CODE2,Max1,MinSaleValue0.3,Count23)第一行,第二行我想要(SideID1,AQS3,CODE2,Max3,MinSaleValue0.028,Count22)...以此类推,大约有 300 个。请记住,SiteID1 是 SiteID 的一个特定值,AQS3 是 AQS 的特定值,CODE2 是 CODE 的特定值。这些可能会有所不同,但对于我的数据集来说,它们都是相同的。我在 .csv 文件中有 SiteID、AQS 和代码,占据了三列,在它下面有(续)
0赞 glico 4/10/2023
(cont) Max、MinSaleValue 和 Count 的“瘦/长”数据。我想转置(使用 do 循环和数组)该部分,然后将其附加到它前面的 SideID/AQS3/CODE2 部分。我有大约 200 个这样的观察值(所以 200 个最大值、200 个最小销售值、200 个计数),在我的最终数据集中,我希望 200 行在它们自己的列中显示这些值中的每一个,以及相应的代码、aqs 和 siteID。

答:

0赞 Tom 4/11/2023 #1

因此,假设您有一个这样的 CSV 文件,其中变量名称和值被混合到一个单元格中。

options parmcards=csv1;
filename csv1 temp;
parmcards4;
SiteID 1,AQS 3,Code 2
Max 1,,
MinSaleValue 0.3,,
Count 23,,
;;;;

您可以通过首先将单元格值读入字符变量,然后解析名称和值来读取它。

data file1;
  infile csv1 dsd truncover ;
  if _n_=1 then do;
    input dummy :$50. @ ;
    SiteID=scan(dummy,2,' ');
    input dummy @;
    AQS=input(scan(dummy,2,' '),32.);
    input dummy @;
    Code=input(scan(dummy,2,' '),32.);
    retain SiteID AQS Code ;
    delete;
  end;
  input dummy ;
  value=input(scan(dummy,2,' '),32.);
  varname=scan(dummy,1,' ');
  drop dummy;
run;

这将产生如下数据集:

regular dataset

然后,可以使用 PROC TRANSPOSE 创建宽数据集。

proc transpose data=file1 out=wide1(drop=_name_) ;
  by siteid aqs code ;
  id varname;
  var value;
run;

transposed dataset

要获得非常广泛的数据集,您需要添加另一个变量,该变量可用作变量名称的后缀。也许它是CSV文件的文件名的一部分?或者只是简单地计算读取的文件数?获得该变量后,只需将其包含在 PROC TRANSPOSE 步骤的 ID 语句中即可。