2012-06-07 3 views
5

R에서 밀리 초의 반올림에 다음과 같은 문제가 발생했습니다. Milliseconds puzzle when calling strptime in R : 반올림 밀리 초로 R 문제가 발생했습니다.

> options(digits.secs=3) 
> as.POSIXlt("13:29:56.061", format='%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.060 UTC" 
> as.POSIXlt("13:29:56.062", format='%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.061 UTC" 
> as.POSIXlt("13:29:56.063", format='%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.063 UTC" 

나는 URL을 배경 정보를 제공하지만 내 문제가 해결되지 않는 것으로 나타났습니다.

또한이 URL은 문제를 다루지 만 해결하지는 않습니다 : R xts: .001 millisecond in index. 이러한 경우

나는 다음을 참조하십시오

> x <- as.POSIXlt("13:29:56.061", format='%H:%M:%OS', tz='UTC') 
> print(as.numeric(x), digits=20) 
[1] 1339075796.0610001087 
URL은이 단지 디스플레이 문제가 있지만이 옵션을 선없이 "%OS3" 같은 문장을 사용하는 것이하지 않는 것으로 나타났습니다 것을 나타내는 것 같다

올바른 숫자의 숫자를 픽업하는 것처럼 보입니다.

내가 사용 버전은 Windows에서 32 비트 2.15.0이다 그러나 이것은 R.

을 위해 다른 상황에서 내 원래의 데이터가 내가 찾아 내야 CSV 파일 내에서 이러한 날짜 시간 문자열을 것을

참고 존재하는 것 문자열에서 올바른 밀리 초 시간으로 변환하는 방법.

+1

여기서 format()의 사용은 불필요하고 혼란 스럽습니다. . . – mdsumner

+0

그래, 우리는'format = '% H : % M : % OS' '가 필요하다. –

+0

참조 http://stackoverflow.com/a/7730759/210673 – Aaron

답변

5

나는 그것을 볼 수 없습니다 :

> options(digits.secs = 4) 
> as.POSIXlt("13:29:56.061", format = '%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.061 UTC" 
> as.POSIXlt("13:29:56.062", format = '%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.062 UTC" 
> as.POSIXlt("13:29:56.063", format = '%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.063 UTC" 
> options(digits.secs = 3) 
> as.POSIXlt("13:29:56.061", format = '%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.061 UTC" 
> as.POSIXlt("13:29:56.062", format = '%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.062 UTC" 
> as.POSIXlt("13:29:56.063", format = '%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.063 UTC" 

"%OSn" 형식 문자열로

> sessionInfo() 
R version 2.15.0 Patched (2012-04-14 r59019) 
Platform: x86_64-unknown-linux-gnu (64-bit) 

locale: 
[1] LC_CTYPE=en_GB.utf8  LC_NUMERIC=C    
[3] LC_TIME=en_GB.utf8  LC_COLLATE=en_GB.utf8  
[5] LC_MONETARY=en_GB.utf8 LC_MESSAGES=en_GB.utf8 
[7] LC_PAPER=C    LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C   
[11] LC_MEASUREMENT=en_GB.utf8 LC_IDENTIFICATION=C  

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

, 하나 개의 강제 절단

와 함께. 분수 초를 부동 소수점으로 정확하게 표현할 수없는 경우 잘림이 잘못된 방향으로 잘 갈 수 있습니다. 당신이 잘못된 방향으로가는 것을 볼 경우 당신은 또한 당신이 원하는 단위로 명시 적으로 반올림 또는 ( 0.0005를 표시하는 경우)에서 작동하고자하는 부분의 절반 추가 할 수 있습니다

> t1 <- as.POSIXlt("13:29:56.061", format = '%H:%M:%OS', tz='UTC') 
> t1 
[1] "2012-06-07 13:29:56.061 UTC" 
> t1 + 0.0005 
[1] "2012-06-07 13:29:56.061 UTC" 

(을하지만, 나는 말했다 , 여기서 문제가 보이지 않습니다.)

이 후자는 Simon Urbanek on the R-Devel mailing list on 30-May-2012으로 작성되었습니다. (이 인수 다른 기능에서하지 필요한 입력의 이름의, 형식 여기 를 호출 할 필요는 없습니다)

unclass(as.POSIXlt("13:29:56.061", '%H:%M:%OS', tz='UTC')) 
$sec 
[1] 56.061 
... 

가 :

+0

32 비트 버전으로 사용해보십시오. –

+0

@AndrewStern 32 비트 시스템이 없어도 사용할 수 없습니다. 내 답변을 업데이트했습니다. ''POSIXlt ''객체로 얻은 후에 시간 (* 0.0005)에 작은 부분을 추가하여 상황을 개선 할 수 있는지보십시오. 자세한 내용은 R-Devel 스레드를 따르십시오. –

+1

나는 재현 할 수있다 - 나는 32 비트와 64 비트 R을 Win7 64 비트 시스템에 모두 설치했다. 문제는 32 비트 R. – Fhnuzoag

1

밀리 세컨드가있다.

그렇지 않으면, 나는 (윈도우 64 비트 R 2.15.0에) 재현 할 수

options(digits.secs = 3) 
as.POSIXlt("13:29:56.061", '%H:%M:%OS', tz='UTC') 
[1] "2012-06-07 13:29:56.061 UTC" 

sessionInfo() 
R version 2.15.0 Patched (2012-05-05 r59321) 
Platform: x86_64-pc-mingw32/x64 (64-bit) 
... 
+0

unclass (as.POSIXlt ("13 : 29 : 56.061", "% H : % M : % OS", tz = 'UTC')) 그러나 화면을 사용하여 unclass 할 때 올바른 것으로 보입니다. as.POSIXlt ("13 : 29 : 56.061", "% H : % M : % OS", tz = 'UTC')를 사용하여 표시 할 때 잘못된 밀리 초를 계속 표시합니다.필자는 32 비트 버전을 사용 중이며 64 비트 버전은 레지스터가 더 크기 때문에 더 정확할 수 있습니다. –

+1

결함이있는 화면이어야합니다. – mdsumner

3

Milliseconds puzzle when calling strptime in R과 같은 문제가있다.

귀하의 예 :

> x <- as.POSIXlt("13:29:56.061", format='%H:%M:%OS', tz='UTC') 
> print(as.numeric(x), digits=20) 
[1] 1339075796.0610001087 

문제를 대표하지 않습니다. as.numeric(x)은 숫자로 변환하기 전에 POSIXlt 객체를 POSIXct로 변환하므로 다른 부동 소수점 정밀도 반올림 오류가 발생합니다.

그건 print.POSIXlt (즉 format.POSIXlt)이 작동하는 방식이 아닙니다. 당신이 볼 필요가 있도록 POSIXlt리스트의 각 요소는 개별적으로 구성 format.POSIXlt 형식 : 당신이 56.060를 볼 수 있도록

print(x$sec, digits=20) 
[1] 56.060999999999999943 

그리고 그 숫자가 세 번째 소수점 자리에서 잘립니다. 테스트에서

> format(x, "%H:%M:%OS6") 
[1] "13:29:56.060999" 
1

나는이 문제가 여전히 32 비트 R 3.01을 위해 존재하는지와이의 32 비트 구현에 고유 부동 소수점 데이터의 절단에 의한 것을주의했다 : 직접 format를 호출하여이를 볼 수 있습니다 POSIXlt 날짜 시간에 대한 print, format 및 as.character 연산자.

기본 데이터는 하나의 사례 (32 비트)에서는 잘리지 않는 다른 유형으로 저장되지 않고 다른 데이터 (64 비트)에서는 저장되지 않지만 "인쇄", "형식"및 "as.character" POSIXlt 데이터를 표시 가능한 문자열로 표시하는 데 사용되는 POSIXlt 유형에 대한 함수입니다.

문서화 된 동작은 (@Gavin Simpson에서 언급 한) 추가 숫자를 자르거나 무시한다는 것이지만 32 비트 및 64 비트 버전의 경우에는 마찬가지입니다. 시연; 우리는 1000 서로 다른 시간을 생성하고 몇 가지 비교 작업을 수행 할 수 있습니다 :

> x[1:6] 
[1] "2015-10-16 13:29:56.000 UTC" "2015-10-16 13:29:56.000 UTC" 
[3] "2015-10-16 13:29:56.002 UTC" "2015-10-16 13:29:56.003 UTC" 
[5] "2015-10-16 13:29:56.003 UTC" "2015-10-16 13:29:56.005 UTC" 

그래서 그것이 : 모두 32 비트 및 64 비트 비교 연산자 그러나 아래 32 비트 내가 볼, 일치는 아래

> options(digits.sec=3) 
> x = as.POSIXlt("13:29:56.061", format='%H:%M:%OS', tz='UTC') 

> for (i in 0:999) { 
>  x[i+1] = as.POSIXlt(paste0("13:29:56.",sprintf("%03d",i)),format='%H:%M:%OS',tz='UTC') 
> } 

> sum(x[2:1000]>x[1:999]) 
[1] 999 

을 명확하게 디스플레이 문제. 의 POSIXlt 데이터 형식에 실제 숫자에 특히 초를 찾고 우리는 일이 나타나는 것을 볼 수 있습니다

> y = (x[1:6]$sec) 
> y 
[1] 56.000 56.001 56.002 56.003 56.004 56.005 
> trunc(y*1000)/1000 
[1] 56.000 56.001 56.002 56.003 56.004 56.005 
> trunc((y-floor(y))*1000)/1000 
[1] 0.000 0.000 0.002 0.003 0.003 0.005 

나는이 기본베이스 라이브러리에 고정해야 버그가 임시 수정 등이라고 제안 하지만 "print", "as.character"및 "format"함수를 덮어 쓰면 출력을 원하는 출력으로 변경할 수 있습니다.

format.POSIXlt = function(posix) { 
    return(paste0(posix$year+1900,"-",sprintf("%02d",posix$mon+1),"-",sprintf("%02d",posix$mday)," ", 
     sprintf("%02d",posix$hour),":",sprintf("%02d",posix$min),":",sprintf("%002.003f",posix$sec))) 
    } 

print.POSIXlt = function(posix) { 
    print(paste0(posix$year+1900,"-",sprintf("%02d",posix$mon+1),"-",sprintf("%02d",posix$mday)," ", 
     sprintf("%02d",posix$hour),":",sprintf("%02d",posix$min),":",sprintf("%002.003f",posix$sec))) 
    } 

as.character.POSIXlt = function(posix) { 
    return(paste0(posix$year+1900,"-",sprintf("%02d",posix$mon+1),"-",sprintf("%02d",posix$mday)," ", 
     sprintf("%02d",posix$hour),":",sprintf("%02d",posix$min),":",sprintf("%002.003f",posix$sec))) 
    } 
관련 문제