在 proc-iml 中创建新数据集时如何不更改先前存在的字符变量的长度?
How to not change the length of preexisting character variables when creating a new dataset in proc-iml?
我有一个在 proc-iml 中操作的数据集,然后创建一个新数据集读取其中的一些操作值。当我读取字符值时,它们的长度从 7 变为 9。
这并没有真正造成问题,只是有点烦人,当我稍后合并这个新数据集时,我收到了两个数据集中变量长度不同的警告。
有没有办法保持原变量的长度?
示例代码
data data1;
infile datalines delimiter=',';
input classif :. time :.;
datalines;
05, 2021_11
051, 2021_11
;
run;
proc iml;
use work.data1;
read all var {classif time } into _temp_1;
classif = _temp_1[,1];
time = _temp_1[,2];
close;
create work.data2 var{classif time};
append;
quit;
观察data1的时间长度是7,而data2的时间长度是9。
来自Understanding the SAS/IML Language
Defining a Matrix
A matrix is the fundamental structure in the SAS/IML language. A matrix is a two-dimensional array of numeric or character values. Matrices are useful for working with data and have the following properties:
- Matrices can be either numeric or character. Elements of a numeric matrix are double-precision values. Elements of a character matrix are character strings of equal length.
INTO
将字符值放入矩阵_temp_1
中,矩阵必须包含所有原始值,因此元素宽度是最宽数据集变量的属性长度。
_temp_1
矩阵元素的属性通过赋值语句传播。
正如@Richard 所解释的,当您将两个长度不同的字符变量读入公共矩阵的列时,就会发生这种情况。我可以想到至少三种解决方法。根据您的应用,其中一种方法可能比其他方法更方便。
proc iml;
/* Option 1: Read variables into vectors, not a matrix */
use work.data1;
read all var {classif time };
close;
print (nleng(time))[L="nleng(time)"];
/* Option 2: Allocate time to have LENGTH=7 and copy the data in */
use work.data1;
read all var {classif time } into _temp_1;
close;
time = j(nrow(_temp_1), 1, BlankStr(7)); /* allocate char vector */
time[,] = _temp_1[,2]; /* copy the data */
print (nleng(time))[L="nleng(time)"];
/* Option 3: Read into a table instead of a matrix. */
tbl = TableCreateFromDataset("work", "data1") ;
classif = TableGetVarData(tbl, {"Classif"});
time = TableGetVarData(tbl, {"time"});
print (nleng(time))[L="nleng(time)"];
如果您希望 DATA1 中的变量与 DATA2 中的变量定义相同,您可以在 PROC IML 代码之后添加一个数据步骤。
data data2;
set data1(obs=0) data2;
run;
之所以有效,是因为 SAS 在第一次看到变量时定义了变量。在这种情况下,变量由 DATA1 中的定义方式定义,即使 OBS=0 数据集选项将阻止实际从 DATA1 读取任何观察结果。
我有一个在 proc-iml 中操作的数据集,然后创建一个新数据集读取其中的一些操作值。当我读取字符值时,它们的长度从 7 变为 9。
这并没有真正造成问题,只是有点烦人,当我稍后合并这个新数据集时,我收到了两个数据集中变量长度不同的警告。
有没有办法保持原变量的长度?
示例代码
data data1;
infile datalines delimiter=',';
input classif :. time :.;
datalines;
05, 2021_11
051, 2021_11
;
run;
proc iml;
use work.data1;
read all var {classif time } into _temp_1;
classif = _temp_1[,1];
time = _temp_1[,2];
close;
create work.data2 var{classif time};
append;
quit;
观察data1的时间长度是7,而data2的时间长度是9。
来自Understanding the SAS/IML Language
Defining a Matrix
A matrix is the fundamental structure in the SAS/IML language. A matrix is a two-dimensional array of numeric or character values. Matrices are useful for working with data and have the following properties:
- Matrices can be either numeric or character. Elements of a numeric matrix are double-precision values. Elements of a character matrix are character strings of equal length.
INTO
将字符值放入矩阵_temp_1
中,矩阵必须包含所有原始值,因此元素宽度是最宽数据集变量的属性长度。
_temp_1
矩阵元素的属性通过赋值语句传播。
正如@Richard 所解释的,当您将两个长度不同的字符变量读入公共矩阵的列时,就会发生这种情况。我可以想到至少三种解决方法。根据您的应用,其中一种方法可能比其他方法更方便。
proc iml;
/* Option 1: Read variables into vectors, not a matrix */
use work.data1;
read all var {classif time };
close;
print (nleng(time))[L="nleng(time)"];
/* Option 2: Allocate time to have LENGTH=7 and copy the data in */
use work.data1;
read all var {classif time } into _temp_1;
close;
time = j(nrow(_temp_1), 1, BlankStr(7)); /* allocate char vector */
time[,] = _temp_1[,2]; /* copy the data */
print (nleng(time))[L="nleng(time)"];
/* Option 3: Read into a table instead of a matrix. */
tbl = TableCreateFromDataset("work", "data1") ;
classif = TableGetVarData(tbl, {"Classif"});
time = TableGetVarData(tbl, {"time"});
print (nleng(time))[L="nleng(time)"];
如果您希望 DATA1 中的变量与 DATA2 中的变量定义相同,您可以在 PROC IML 代码之后添加一个数据步骤。
data data2;
set data1(obs=0) data2;
run;
之所以有效,是因为 SAS 在第一次看到变量时定义了变量。在这种情况下,变量由 DATA1 中的定义方式定义,即使 OBS=0 数据集选项将阻止实际从 DATA1 读取任何观察结果。