在 SAS 中输入分隔的 is8601 日期时间
Input delimited is8601 datetimes in SAS
是否可以用一个输入语句输入以下内容而不产生任何错误的缺失值?我相信我已经为下面每个日期时间变量的前 19 个字符得到了正确的格式,但我似乎无法找到一种方法让 SAS 忽略无关字符并在尝试输入之前跳到下一个分隔符下一个变量。
data _null_;
infile datalines dlm=',' dsd missover;
input a is8601dt19. b is8601dt19. c .;
format a b is8601dt.;
put a= b= c=;
datalines;
2013-01-19T09:40:39.812+0000,2013-01-19T09:40:39.812+0000,text
,2013-01-19T09:40:39.812+0000,text
,,text
;
run;
我暂时的解决方法是先输入.
,然后使用substr
和input
函数,但我怀疑可能还有更多direct/efficient 方式。
我没有看到一个明确的方法来做到这一点。问题是这些实际上不是 ISO8601 值,至少根据 SAS 是这样。
SAS 识别两个版本的 ISO:基本 (B8601DZ.
) 和扩展 (E8601DZ.
)。 Basic没有colons/dashes/etc,Extended有所有可能的
- 基本:
20130119T094039812+0000
- 扩展:
2013-01-19T09:40:39.812+00:00
(有关详细信息,请参阅 the doc page on ISO date/times)
你的是两者的结合,SAS 似乎不喜欢那样。
再加上您正在从带分隔符的文件中读取这个事实,我没有看到一个好的单遍解决方案。我觉得你的方法很好。您可能可以跳过子字符串,否则您将被卡住。
您上面的输入无效,因为您不能在这样的列表输入法中使用信息格式;如果你在前面加上 :
那么将使用信息格式,但不幸的是你实际上不能使用它来将传入文本限制为信息格式(不知道为什么 - 它可以在其他情况下)。即:
input a :e8601dz19. b :e8601dz19. c :.;
这是合法的,但对你没有帮助,因为它试图将 28 长位插入其中(我不确定它是否右对齐,但绝对不是像它那样左对齐将在格式化输入中)。您正在使用格式化输入,但打算使用修改后的列表输入,因此出现了问题。
如果您没有所有缺失的数据,您可以这样做,例如:
data _null_;
infile datalines dlm=',' dsd missover;
informat a b e8601dt19.;
input
@1 a e8601dt19.
@"," b e8601dt19.
@"," c .;
format a b is8601dt.;
put a= b= c=;
datalines;
2013-01-19T09:40:39.812+0000,2013-01-19T09:40:39.812+0000,text
,2013-01-19T09:40:39.812+0000,text
, ,text
;
run;
这适用于第一行,基本上是将前 19 个读入 a,然后跳到下一个逗号并读入 b。但是请注意,每隔一行它都会失败,因为它为 a 吃掉了太多字符。你所做的任何使它适应工作的事情(这可能是可以完成的)都将远远超过你所做的只是子字符串化。
我会这样做:
data _null_;
infile datalines dlm=',' dsd missover;
informat a b e8601dt19.;
length a_c b_c ;
input
a_c $ b_c $ c $;
a = input(a_c,??e8601dt19. -l);
b = input(b_c,??e8601dt19. -l);
format a b is8601dt.;
put a= b= c=;
datalines;
2013-01-19T09:40:39.812+0000,2013-01-19T09:40:39.812+0000,text
,2013-01-19T09:40:39.812+0000,text
, ,text
;
run;
无需子字符串,只需使用 w
缩短为 19。如果您希望使用 TZ 信息,也可以通过编程方式添加 :
。
是否可以用一个输入语句输入以下内容而不产生任何错误的缺失值?我相信我已经为下面每个日期时间变量的前 19 个字符得到了正确的格式,但我似乎无法找到一种方法让 SAS 忽略无关字符并在尝试输入之前跳到下一个分隔符下一个变量。
data _null_;
infile datalines dlm=',' dsd missover;
input a is8601dt19. b is8601dt19. c .;
format a b is8601dt.;
put a= b= c=;
datalines;
2013-01-19T09:40:39.812+0000,2013-01-19T09:40:39.812+0000,text
,2013-01-19T09:40:39.812+0000,text
,,text
;
run;
我暂时的解决方法是先输入.
,然后使用substr
和input
函数,但我怀疑可能还有更多direct/efficient 方式。
我没有看到一个明确的方法来做到这一点。问题是这些实际上不是 ISO8601 值,至少根据 SAS 是这样。
SAS 识别两个版本的 ISO:基本 (B8601DZ.
) 和扩展 (E8601DZ.
)。 Basic没有colons/dashes/etc,Extended有所有可能的
- 基本:
20130119T094039812+0000
- 扩展:
2013-01-19T09:40:39.812+00:00
(有关详细信息,请参阅 the doc page on ISO date/times)
你的是两者的结合,SAS 似乎不喜欢那样。
再加上您正在从带分隔符的文件中读取这个事实,我没有看到一个好的单遍解决方案。我觉得你的方法很好。您可能可以跳过子字符串,否则您将被卡住。
您上面的输入无效,因为您不能在这样的列表输入法中使用信息格式;如果你在前面加上 :
那么将使用信息格式,但不幸的是你实际上不能使用它来将传入文本限制为信息格式(不知道为什么 - 它可以在其他情况下)。即:
input a :e8601dz19. b :e8601dz19. c :.;
这是合法的,但对你没有帮助,因为它试图将 28 长位插入其中(我不确定它是否右对齐,但绝对不是像它那样左对齐将在格式化输入中)。您正在使用格式化输入,但打算使用修改后的列表输入,因此出现了问题。
如果您没有所有缺失的数据,您可以这样做,例如:
data _null_;
infile datalines dlm=',' dsd missover;
informat a b e8601dt19.;
input
@1 a e8601dt19.
@"," b e8601dt19.
@"," c .;
format a b is8601dt.;
put a= b= c=;
datalines;
2013-01-19T09:40:39.812+0000,2013-01-19T09:40:39.812+0000,text
,2013-01-19T09:40:39.812+0000,text
, ,text
;
run;
这适用于第一行,基本上是将前 19 个读入 a,然后跳到下一个逗号并读入 b。但是请注意,每隔一行它都会失败,因为它为 a 吃掉了太多字符。你所做的任何使它适应工作的事情(这可能是可以完成的)都将远远超过你所做的只是子字符串化。
我会这样做:
data _null_;
infile datalines dlm=',' dsd missover;
informat a b e8601dt19.;
length a_c b_c ;
input
a_c $ b_c $ c $;
a = input(a_c,??e8601dt19. -l);
b = input(b_c,??e8601dt19. -l);
format a b is8601dt.;
put a= b= c=;
datalines;
2013-01-19T09:40:39.812+0000,2013-01-19T09:40:39.812+0000,text
,2013-01-19T09:40:39.812+0000,text
, ,text
;
run;
无需子字符串,只需使用 w
缩短为 19。如果您希望使用 TZ 信息,也可以通过编程方式添加 :
。