2013-04-24 5 views
1

as.POSIXlt에서 설명 할 수없는 이상한 동작을 발견했습니다. 다른 사람이 기대하고 있습니다. this question을 조사 할 때 때로는 초의 분수 부분이 잘못 반올림되는 것을 발견했습니다.as.POSIXlt를 사용하여 마이크로 초 단위의 반올림 오류

예를 들어, 아래의 숫자는 신기원이 시작된 이래로 특정 초를 나타내며 마지막 6 자리는 두 번째 부분의 분수입니다. 따라서 첫 번째 숫자에서 초의 비율은 .645990이어야합니다.

# Generate sequence of integers to represent date/times 
times <- seq(1366039619645990 , length.out = 11) 
options(scipen=20) 
times 
[1] 1366039619645990 1366039619645991 1366039619645992 1366039619645993 1366039619645994 1366039619645995 
[7] 1366039619645996 1366039619645997 1366039619645998 1366039619645999 1366039619646000 

# Convert to date/time with microseconds 
options(digits.secs = 6) 
as.POSIXlt(times/1e6, tz="EST", origin="1970-01-01") + 5e-7 
[1] "2013-04-15 10:26:59.645990 EST" "2013-04-15 10:26:59.645991 EST" "2013-04-15 10:26:59.645992 EST" 
[4] "2013-04-15 10:26:59.645993 EST" "2013-04-15 10:26:59.645994 EST" "2013-04-15 10:26:59.645995 EST" 
[7] "2013-04-15 10:26:59.645996 EST" "2013-04-15 10:26:59.645997 EST" "2013-04-15 10:26:59.645998 EST" 
[10] "2013-04-15 10:26:59.645999 EST" "2013-04-15 10:26:59.646000 EST" 

는 달리 I 라운딩 에러가 발생, I 번째의 소수 부분의 정확한 표현을 얻을 수있는 시간 반 최소 변화와 같은 작은 증분을 추가한다는 것을 발견했다. 위의 숫자 순서대로 as.POSIXlt을 실행하면 잘 작동하지만, 하나의 숫자 즉, .645999로 끝나야하는 번호를 .645로 잘라내려고하면 그 이유는 모르겠습니다!
# Now just convert the date/time that should end in .645999 
as.POSIXlt(times[10]/1e6, tz="EST", origin="1970-01-01") + 5e-7 
[1] "2013-04-15 10:26:59.645 EST" 

상기 단일 소자 당량 as.POSIXlt 의해 반환 된 벡터의 번째 요소를 비교. 무슨 일 이니?

세션 정보 : 나는 적절한 대답을 얻었다하지 않은 (그것으로 계속 찾고)하지만이 재미라고 생각

R version 2.15.2 (2012-10-26) 
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit) 

locale: 
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8 

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] raster_2.0-41 sp_1.0-5  

loaded via a namespace (and not attached): 
[1] grid_2.15.2  lattice_0.20-13 tools_2.15.2 
+0

내 컴퓨터에서'times/1e6'을 할 때'times'의 모든 소수를 버립니다. 사실 나는'2013 년 4 월 15 일 10시 26 분 59 초 동부 11 번 ... – Michele

+0

@Michele 감사합니다! - 내 예제에서 하나의 핵심 코드가 누락되었습니다. 이제 추가하십시오! –

+0

@Michele 다시 시도해 주시겠습니까? 'options (digits.secs = 6)'를 먼저 실행하십시오. –

답변

2

이것은 반올림 문제로 보이는데, 소수 자릿수의 유효 자릿수가 삭제됩니다. POSIXlt 클래스의 개체에 대해 print.POSIXlt에 사용되는 format.POSIXlt의 형식 메서드에 (?) 코드를 사용하지 않습니다.

예를 들어 아래 두 값을 사용하는 경우 format.POSIXlt은 다음 라인을 사용하여 자필로 포장하여 분수 초를 연속적으로 더 큰 자리 수로 반올림 한 절대 값을 테스트합니다. 초이 때 당신이 볼 수 있듯이

secs <- c(59.645998 , 59.645999) 
sapply(seq_len(np) - 1L , function(x) abs(secs - round(secs, x))) 
     [,1]  [,2]  [,3]  [,4]  [,5]  [,6] 
[1,] 0.354002 0.045998 0.004002 0.000002 0.000002 0.000002 
[2,] 0.354001 0.045999 0.004001 0.000001 0.000001 0.000001 

는 .xxx999 3 개 이상의 자리 반올림 따라서 인쇄에 영향을 미치는 0.000001을 제공합니다 : 0.000001이 같은 사실은 위의 방법에서 찾을 수 있기 때문에

# the number of digits used for the fractional seconds is gotten here 
np <- getOption("digits.secs") 

# and the length of digits to be printed is controlled in this loop 
for (i in seq_len(np) - 1L) if (all(abs(secs - round(secs, 
       i)) < 0.000001)) { 
       np <- i 
       break 
      } 

입니다 다음과 같습니다.

따라서 반올림에 사용 된 테스트로 인해 소수 자릿수가 소수점 이하 3 자리로 잘립니다. 나는 for 루프의 테스트 값이 5e-7로 설정 되었다면이 문제는 사라질 것이라고 생각한다.

결과가 벡터 POSIXlt 인 경우 다른 인쇄 방법이 호출되어야합니다.

1

가 :

times <- seq(1366039619645990 , length.out = 11) 
# Convert to date/time wz="EST", origin="1970-01-01") + 5e-7 
options(digits.secs = 6) 

test <- as.POSIXlt(times/1e6, tz="EST", origin="1970-01-01") + 5e-7 

test1[1] <- NULL 
for(i in 1:11) 
    test1[i] <- as.POSIXlt(times[i]/1e6, tz="EST", origin="1970-01-01") + 5e-7 

> identical(test, test1) 
[1] TRUE 

BTW, 하나의 문에서 내가 가진 당신과 같은 결과 ...

> test 
[1] "2013-04-15 10:26:59.645990 EST" "2013-04-15 10:26:59.645991 EST" "2013-04-15 10:26:59.645992 EST" 
[4] "2013-04-15 10:26:59.645993 EST" "2013-04-15 10:26:59.645994 EST" "2013-04-15 10:26:59.645995 EST" 
[7] "2013-04-15 10:26:59.645996 EST" "2013-04-15 10:26:59.645997 EST" "2013-04-15 10:26:59.645998 EST" 
[10] "2013-04-15 10:26:59.645999 EST" "2013-04-15 10:26:59.646000 EST" 
> test[10] 
[1] "2013-04-15 10:26:59.645 EST" 
> as.POSIXlt(times[10]/1e6, tz="EST", origin="1970-01-01") + 5e-7 
[1] "2013-04-15 10:26:59.645 EST" 

마지막 두 문장을 보면,이 문제는 주로 t o 벡터가 아닌 단일 값을 표시. 그러나이 경우에도 반올림이 아닌 floor을 통해 잘 렸을 것입니다.

+0

+1은 반올림 또는 잘림의 문제 여야합니다. –

관련 문제