7

設定

データフレームに文字列として保存された期間の列があります。それらを適切な時間オブジェクト、おそらくPOSIXltに変換したい。ほとんどの文字列は、このメソッドを使用して簡単に解析できます。

> data <- data.frame(time.string = c(
+   "1 d 2 h 3 m 4 s",
+   "10 d 20 h 30 m 40 s",
+   "--"))
> data$time.span <- strptime(data$time.string, "%j d %H h %M m %S s")
> data$time.span
[1] "2012-01-01 02:03:04" "2012-01-10 20:30:40" NA

欠落している期間はコード化され"--"ており、変換する必要がありNAます。これは既に発生していますが、保持する必要があります。

課題は、文字列がゼロ値の要素を削除することです。したがって、目的の値2012-01-01 02:00:14は string になります"1 d 2 h 14 s"。ただし、この文字列はNA単純なパーサーで解析されます。

> data2 <- data.frame(time.string = c(
+  "1 d 2 h 14 s",
+  "10 d 20 h 30 m 40 s",
+  "--"))
> data2$time.span <- strptime(data2$time.string, "%j d %H h %M m %S s")
> data2$time.span
[1] NA "2012-01-10 20:30:40" NA

質問

  1. 可能なすべての文字列形式を処理する「R Way」とは何ですか? おそらく、各要素を個別にテストして抽出してから、再結合しますか?
  2. POSIXlt は適切なターゲット クラスですか? 特定の開始時刻から自由な期間が必要なため、誤った年と月のデータ ( 2012-01-) を追加するのは面倒です。

解決

@mplourde は、日付形式のさまざまな条件のテストに基づいて、書式設定文字列を動的に作成することで、間違いなく正しい考えを持っていました。cut(Sys.Date(), breaks='years')のベースラインとしてのの追加datediffも良かったのですが、as.POSIXct() 注: R2.11 ベースを使用しています。これは後のバージョンで修正されている可能性があります

の出力はas.POSIXct()、日付コンポーネントが含まれているかどうかによって劇的に変化します。

> x <- "1 d 1 h 14 m 1 s"
> y <-     "1 h 14 m 1 s"  # Same string, no date component
> format (x)  # as specified below
[1] "%j d %H h %M m %S s"
> format (y)
[1] "% H h % M %S s"    
> as.POSIXct(x,format=format)  # Including the date baselines at year start
[1] "2012-01-01 01:14:01 EST"
> as.POSIXct(y,format=format)  # Excluding the date baselines at today start
[1] "2012-06-26 01:14:01 EDT"

したがって、difftime関数の 2 番目の引数は次のようになります。

  • 入力文字列に日のコンポーネントがある場合、現在の年の最初の日の開始
  • 入力文字列に日のコンポーネントがない場合の現在の日の開始

cutこれは、関数の単位パラメーターを変更することで実現できます。

parse.time <- function (x) {
  x <- as.character (x)
  break.unit <- ifelse(grepl("d",x),"years","days")  # chooses cut() unit
  format <- paste(c(if (grepl("d", x)) "%j d",
                    if (grepl("h", x)) "%H h",
                    if (grepl("m", x)) "%M m",
                    if (grepl("s", x)) "%S s"), collapse=" ")

  if (nchar(format) > 0) {
    difftime(as.POSIXct(x, format=format), 
             cut(Sys.Date(), breaks=break.unit),
             units="hours")
  } else {NA}

}
4

2 に答える 2

11

difftimePOSIXctオブジェクトは、またはオブジェクトのいずれかに追加できる期間オブジェクトPOSIXltです。の代わりにこれを使いたいかもしれませんPOSIXlt

文字列から時間オブジェクトへの変換に関しては、次のようなことができます。

data <- data.frame(time.string = c(
    "1 d 1 h",
    "30 m 10 s",
    "1 d 2 h 3 m 4 s",
    "2 h 3 m 4 s",
    "10 d 20 h 30 m 40 s",
    "--"))

f <- function(x) {
    x <- as.character(x)
    format <- paste(c(if (grepl('d', x)) '%j d',
                      if (grepl('h', x)) '%H h',
                      if (grepl('m', x)) '%M m',
                      if (grepl('s', x)) '%S s'), collapse=' ')

    if (nchar(format) > 0) {
        if (grepl('%j d', format)) {
            # '%j 1' is day 0. We add a day so that x = '1 d' means 24hrs.
            difftime(as.POSIXct(x, format=format) + as.difftime(1, units='days'), 
                    cut(Sys.Date(), breaks='years'),
                    units='hours')
        } else {
            as.difftime(x, format, units='hours')
        }
    } else { NA }
}

data$time.span <- sapply(data$time.string, FUN=f)
于 2012-06-21T21:38:51.007 に答える
3

lubridateで運が良くなると思います:

lubridateで日付と時刻を簡単に:

5.3. 期間

...

期間は秒単位で測定されるため、期間の長さはうるう年、うるう秒、および夏時間の影響を受けません。したがって、期間の長さは一貫しており、他の期間と簡単に比較できます。期間は、速度、レート、ライフタイムなどの時間ベースの属性を比較するときに使用する適切なオブジェクトです。lubridate は期間にベース R の difftime クラスを使用します。これを容易にするために、追加の difftime メソッドが作成されました。

lubridate は期間にベース R の difftime クラスを使用します。これを容易にするために、追加の difftime メソッドが作成されました。

...

Duration オブジェクトは、ヘルパー関数 dyears()、dweeks()、ddays()、dhours()、dminutes()、および dseconds() を使用して簡単に作成できます。タイトルの d は期間を表し、これらのオブジェクトを期間オブジェクトと区別します。これについてはセクション 5.4 で説明します。各オブジェクトは、上記の推定関係を使用して秒単位の期間を作成します。

とは言っても、文字列を解析して期間に変換する関数を (まだ) 見つけていません。


また、Ruby の Chronicを見て、時間の解析がいかに洗練されているかを確認することもできます。R用のこのようなライブラリは見つかりませんでした.

于 2012-06-21T22:01:15.977 に答える