Sas 输入变量中的数字行
我有一个数组t,它指定我要从file.txt读取的行数。因此,我的代码应该如下所示:Sas 输入变量中的数字行,sas,Sas,我有一个数组t,它指定我要从file.txt读取的行数。因此,我的代码应该如下所示: data a; do i = 1 to dim(t); infile "C:\sas\file.txt" firstobs = t(i) obs = t(i); input x1-x10; output; end; run; 2 4 6 . . . . . . . 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4
data a;
do i = 1 to dim(t);
infile "C:\sas\file.txt" firstobs = t(i) obs = t(i);
input x1-x10;
output;
end;
run;
2 4 6 . . . . . . .
2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6
当然,此解决方案(firstobs)仅在列数为常量时有效。如何使用数组(也从同一文件读取,即从第一行读取)执行此操作
例如,如果file.txt如下所示:
data a;
do i = 1 to dim(t);
infile "C:\sas\file.txt" firstobs = t(i) obs = t(i);
input x1-x10;
output;
end;
run;
2 4 6 . . . . . . .
2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6
然后我希望输出为:
2 2 2 2 2 2 2 2 2 2
4 4 4 4 4 4 4 4 4 4
6 6 6 6 6 6 6 6 6 6
如果您的文件是结构化的(即相同的分隔符/一行连续的输入数据),那么下面的方法应该有效。我相信您可以调整以提高效率,但我在其中添加了一些注释来解释每个部分的功能。我还建议阅读文档,了解
\u infle\u
自动变量和其他操作输入数据缓冲区的方法的说明。此外,如果您的输入数据文件本身需要拆分为单独的行,那么您需要对此进行调整
filename in_data 'C:\sas\file.txt';
data out_data (keep=x1-x10);
infile in_data;
input fn;
/*get the number of vars based on delimiter*/
count = count(strip(_infile_), ' ') + 1;
/*iterate through vars*/
do i =1 to count;
/*set new value to current var*/
rec = scan(strip(_infile_), i, ' ');
/*set array values to new value*/
array obs(10) x1-x10;
do j=1 to dim(obs);
obs(j) = rec;
end;
/*output to dataset*/
output out_data;
end;
run;
输入
输出
希望这能有所帮助。听起来第一行包含要保留的行列表。从一个单独的文件中读取可能会更容易,但您可以使用单个文件。您没有提到如何知道数据的列数或第一行中的最大行号数。现在让我们假设您可以在宏变量中设置这些数字 让我们将示例数据放入一个文件:
options parmcards=tempdata ;
filename tempdata temp;
parmcards;
2 4 6 . . . . . . .
2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6
;
现在,让我们将其读入数据集
%let ncol=9 ;
%let maxrows=1000;
data want ;
infile tempdata truncover ;
array rows (&maxrows) _temporary_;
if _n_=1 then do i=1 by 1 until (rows(i)=.);
input rows(i) @;
drop i;
end;
else do;
input x1-x&ncol;
if whichn(_n_,of rows(*)) then output;
end;
run;
如果文件的其他行具有无效数据,以致于INPUT语句会导致错误,则可以跳过尝试从这些行读取数据,只需在ELSE块中进行一次小的修改
else do;
input @;
if whichn(_n_,of rows(*)) then do;
input x1-x&ncol;
output;
end;
end;
如果您发现经常不想读取文件末尾的大量记录,可以将这一行添加到数据步骤的末尾,以便在读取完所需的最后一行后停止
if _n_ > max(of rows(*)) then stop;
这里有一个类似于Tom的答案,但它不会尝试读取非路径数据。对于跳过的行中的数据格式与路径数据格式不同的情况,这可能更适合。它使用Tom的Parmcard和结构,因此您可以更容易地看到差异
options parmcards=tempdata ;
filename tempdata temp;
parmcards;
2 4 6 . . . . . . .
2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6
;
%let ncol=9 ;
%let maxrows=1000;
data want ;
infile tempdata truncover end=eof;
array rows (&maxrows) _temporary_;
do i=1 by 1 until (rows(i)=.); *read in first line, just like Toms answer;
input rows(i) @;
drop i;
end;
input ; * stop inputting on the first line;
* Here you may need to use CALL SORTN to sort row array if it is not already sorted;
_currow = 2; * current row indicator;
do _i = 1 to dim(rows); * iterate through row array;
if rows[_i]=. then leave; * leave if row array is empty;
do while (_currow lt rows[_i] and not eof); * skip rows not in row array;
input;
_currow = _currow + 1;
end;
input x1-x&ncol; * now you know you are on a desired row, so input it;
output; * and output it;
_currow = _currow + 1;
end;
run;
如上所述,如果数组尚未排序(即,如果缺失不在末尾,且数字顺序不正确),您可能必须使用CALL SORTN。好的,我已经解决了。假设我知道列数(10)和行数(10),我可以使用以下代码得到我想要的:
data a;
w=1;
infile "C:\sas\file.txt" n=10;
input #w x1-x10;
array x(*) x1-x10;
array t(10) _temporary_;
do i=1 to 10;
if(x(i)^=.) then t(i)=x(i);
else leave;
end;
do j=1 to i-1;
w=t(j);
input #w x1-x10;
output;
end;
stop;
run;
剩下的就是在不知道行数和列数的情况下执行相同的操作。通过这种方式,我只读取我感兴趣的行,而不是读取所有行并只输出我需要的行。如果您只是将整个矩阵读取到数据集中,然后使用行号选择所需的数据,那么程序维护可能会容易得多。您的文件可能需要有数十万次的观察才能节省时间,从而值得编程来避免读取完整的文件 下面是使用SET语句的POINT=选项选择行的一种方法
options parmcards=tempdata ;
filename tempdata temp;
parmcards;
2 4 6
2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6
;
data rows;
infile tempdata obs=1 ;
input row @@;
row=row-1;
run;
proc import datafile="%sysfunc(pathname(tempdata))" dbms=dlm out=full replace;
getnames=no;
delimiter=' ';
datarow=2;
run;
data want ;
set rows ;
pointer=row ;
set full point=pointer ;
run;
proc print; run;
您的意思是文件的第一行包含行号,而您只想读取第一条记录中的行号所引用的文件中的记录吗?如果这不是你想要的,那么试着用一些相应的输出数据显示一些示例输入数据,并扩展你对所需内容的解释。我不认为OPs实际数据只包含行号。似乎OP希望读取第2、4、6行,而不仅仅是在该行中放置2。只需将实际输入语句移动到IF语句之后就更容易了<代码>输入@;如果whichn(_n_,行数(*));输入x1-x&ncol;产出代码>我认为上面的速度会稍微快一点,因为我不必每次都查询
whichn
。好的,但这里您读取所有行,只输出第一行中的行。我不想那样做。我想避免读取其他行。无法避免读取顺序文件的所有行。您可以避免尝试将行中的文本转换为变量,但仍然需要读取文件。如果“只读取我感兴趣的行”,则不会保存任何内容。需要时间的是将文件中的行读取到内存中。操作系统将以块的形式读取行。像本例这样小的文件可以放在一个磁盘I/O操作中。是的,如果我在sas集中有它,我就可以这样做。我很想做‘point=’所做的事情,但是当从.txt文件中读取时,不可能从文本文件中读取point=。您可能可以从具有固定长度记录的文件中删除它,但现在没有人真正使用这些记录了。