web-dev-qa-db-ja.com

潤滑剤を使用して2桁の年を4桁の年に変換するよりエレガントな方法はありますか?

日付ベクトルの年が2桁の場合、mdy()は00から68までの年を21世紀に、69から99までの年を20世紀に変換します。例えば:

library(lubridate)    
mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))

次の出力が得られます。

Multiple format matches with 5 successes: %m/%d/%y, %m/%d/%Y.
Using date format %m/%d/%y.
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC" "2004-01-02 UTC"

事後にこれを修正するには、間違った日付から100を引いて、2054と2068を1954と1968に変換します。しかし、2桁の日付を解析して、で正しく処理されるようにする、よりエレガントでエラーが発生しにくい方法はありますか。プロセス自体を解析しますか?

更新:@ JoshuaUlrichが私にstrptimeを指摘した後、私は この質問 を見つけました。これは同様の問題を扱っていますマイニングしますが、ベースRを使用します。

Rでの日付処理への優れた追加は、日付解析関数内の2桁の日付の世紀選択カットオフを処理するための何らかの方法のようです。

31
eipi10

これを可能にする関数は次のとおりです。

library(lubridate)
x <- mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))


foo <- function(x, year=1968){
  m <- year(x) %% 100
  year(x) <- ifelse(m > year %% 100, 1900+m, 2000+m)
  x
}

やってみて:

x
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"

foo(x)
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"

foo(x, 1950)
[1] "1954-01-02 UTC" "1968-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"

ここでのちょっとした魔法は、モジュラス演算子%%を使用して除算の小数部分を返すことです。したがって、1968 %% 100は68を生成します。

27
Andrie

私はこれとまったく同じバグ/機能を経験しました。

私は、Excelタイプの日付(これが最も得られる場所)からRが使用できるものに変換するのに役立つ、次の2つの簡単な関数を作成することになりました。

受け入れられた答えには何も問題はありません-それは私がパッケージにあまり負荷をかけたくないということだけです。

まず、年を分割して置き換えるヘルパー...

year1900 <- function(dd_y, yrFlip = 50)
{
    dd_y <- as.numeric(dd_y)
    dd_y[dd_y > yrFlip] <- dd_y[dd_y > yrFlip] + 1900
    dd_y[dd_y < yrFlip] <- dd_y[dd_y < yrFlip] + 2000
    return(dd_y)
}

これは、タイプに応じて、Excelの日付を「修正」する関数によって使用されます。

XLdate <- function(Xd, type = 'b-Y')
{
    switch(type,
        'b-Y' = as.Date(paste0(substr(Xd, 5, 9), "-", substr(Xd, 1, 3), "-01"), format = "%Y-%b-%d"),
        'b-y' = as.Date(paste0(year1900(substr(Xd, 5, 6)), "-", substr(Xd, 1, 3), "-01"), 
                        format = "%Y-%b-%d"),
        'Y-b' = as.Date(paste0(substr(Xd, 1, 3), "-", substr(Xd, 5, 9), "-01"), format =     "%Y-%b-%d")
        )
}

お役に立てれば。

3
ricardo

別のオプションは次のとおりです。

xxx <- c("01-Jan-54","01-Feb-68","01-Aug-69","01-May-99","01-Jun-04", "
       31-Dec-68","01-Jan-69", "31-Dec-99")

dmy(paste0(sub("\\d\\d$","",xxx) , ifelse( (tt <- 
   sub("\\d\\d-\\D\\D\\D-","",xxx)  ) > 20 ,paste0("19",tt),paste0("20",tt))))

エレガントでも短い解決策もありませんが。 lubridateがカットオフ日を指定するオプションを追加した方が良いと思います。

0
skan