1

私は巨大なデータフレームを持ってdfおり、1つの列に次のような「年-月」の値があります:「YYYYMM」。現在、データ型は数値です。スナップショット:

> df[[1]][1:10]
[1] 201001 201001 201001 201001 201001 201001 201001 201001 201001 201001
> str(df)
'data.frame':   2982393 obs. of  11 variables:
 $ YearMonth    : int  201001 201001 201001 201001 201001 201001 201001 201001 201001 201001 ...
 $ ...

私が欲しいのは、この値を「YYYY-MM」の形式の文字列(最終的には係数)に変換して、これを他のデータフレームと比較できるようにすることです。

値を変換する簡単な方法を見つけるのに苦労しています。

as.Dateと機能を使ってみましたformat。ただし、値には日がないため、文字列では機能しませんでした。Numerics(データフレーム列と同じ)では、他の問題も発生しました。

> as.Date("201001", format = "%Y%m")
 [1] NA

> as.Date(201001, format = "%Y%m")
 Error in as.Date.numeric(201001, format = "%Y%m") : 
    'origin' must be supplied
> as.Date(df[[1]], format = "%Y%m")
 Error in as.Date.numeric(df[[1]], format = "%Y%m") : 
    'origin' must be supplied

subset文字列を使用して連結することで、1つの値だけを変換できます。1つの要素を処理するために、以下の式を作成しました。

transformString <- function( x ) { # x = value
    return ( paste(cbind(substring(x, 1, 4),"-",substring(x,5,6)), collapse = '') )
}

問題:すべての要素をトラバースする以外に、その関数をdata.frameの列全体に適用する簡単な方法が見つかりませんでした。

transformStringVector <- function( x ) { # x = vector
    for(i in 1:length(x)) {
       x[i]<-transformString(x[i])
    }
    return ( x )
}

これはエレガントとはほど遠いものであり、パフォーマンスに悪影響を及ぼします。apply私は(以下を参照)などを使おうとしましたが、エラーに直面しました...(私は実際にはapply機能を取得していないことを認めます)

> temp <- apply(df[[1]], 1, transformString )
Error in apply(df[[1]], 1, transformString ) : 
  dim(X) must have a positive length

巨大なdata.frame内でこの変換の代替手段を持っている人はいますか?またはもっと一般的に; data.frame内の要素に文字列のような変換を適用する簡単な方法はありますか?

4

3 に答える 3

4

理由

> as.Date("201001", format = "%Y%m")
 [1] NA

動作しません。R日付には日コンポーネントが必要です。あなたの日付はそれを提供しないので、あなたは不足している値を取得します。これを回避するには、日コンポーネントを追加するだけです。

R> x = c("201001","201102")
R> x = paste(x, "01", sep="")

だから私はすべての日付を月の最初にした:

R> y = as.Date(x, "%Y%m%d")
[1] "2010-01-01" "2011-02-01"

次に、を使用formatして必要なものを取得できます。

R> format(y, "%Y-%m")
[1] "2010-01" "2011-02"
于 2012-04-10T14:58:02.520 に答える
4

date列の値を指定された形式の文字列に変換するだけで、形式を気にせずsubstr()paste()両方ともベクトルを引数として使用する場合は、次のようにします。

xx<-c(201011,201003,201002,201010,201009,201005,201001,201001,201001,201001)

paste(substr(xx,1,4),substr(xx,5,6),sep="-")
# [1] "2010-11" "2010-03" "2010-02" "2010-10" "2010-09" "2010-05" "2010-01"
# [8] "2010-01" "2010-01" "2010-01"

このように、あなたは使用する必要はありませんapply()

于 2012-04-10T15:05:41.040 に答える
2

これをdata.frameに具体的に適用することについての質問に答えるために、演算子を使用して列にアクセスできます$。したがって、ここで提供されている関数のいずれか(substrバリアントを使用した場合)を使用して実行できます。ファクターへの変換を計画している場合は、最初にそれを行います。

> df <- data.frame(a=1:5,b=5:1,d=200101:200105)
> df
  a b      d
1 1 5 200101
2 2 4 200102
3 3 3 200103
4 4 2 200104
5 5 1 200105
> #Convert to a factor now for performance reasons.
> df$d <- as.factor(df$d)
> df$d <- paste(substr(df$d, 1, 4), "-", substr(df$d, 5,6), sep="")
> df
  a b       d
1 1 5 2001-01
2 2 4 2001-02
3 3 3 2001-03
4 4 2 2001-04
5 5 1 2001-05

> typeof(df$d)
[1] "character"
> df$d <- as.factor(df$d)
> df
  a b       d
1 1 5 2001-01
2 2 4 2001-02
3 3 3 2001-03
4 4 2 2001-04
5 5 1 2001-05
> typeof(df$d)
[1] "integer"

data.frameの「巨大さ」によっては、最初に係数に変換してから、レベルをハイフンでつながれた日付に変換することで、パフォーマンスが向上する場合があることに注意してください。

> df <- data.frame(a=rep(1:5,1000000),b=rep(5:1,1000000),d=rep(200101:200105, 1000000))
> nrow(df)
 [1] 5000000
> # Hyphenate first
> system.time(df$d <- paste(substr(df$d, 1, 4), "-", substr(df$d, 5,6), sep="")) + system.time(df$d <- as.factor(df$d))
  user  system elapsed 
  9.65    0.61   10.31 
>
> #Factor first
> system.time(df$d <- as.factor(df$d)) + system.time(levels(df$d) <- paste(substr(levels(df$d), 1, 4), "-", substr(levels(df$d), 5,6), sep=""))
 user  system elapsed 
 0.68    0.25    0.93 

したがって、data.frameのプロパティによっては、最初にファクタリングを実行することでパフォーマンスを10倍向上させることができる場合があります。

PSパフォーマンスを本当に気にする場合は、ハッシュで裏付けられたファクタリングを使用することで、ファクタリングコード(高速ソリューションの最も遅い部分)でより良いプロパティを取得できる可能性があります。

于 2012-04-10T15:11:28.117 に答える