2016-05-09 10 views
0

dplyrの「動詞」を使用して、Rデータフレームの列に関数が複数の列に依存する場合、データフレーム?dplyrを使用してRデータフレームの複数の列の関数を適用する

私が直面する状況の具体的な例があります。私はこのようなデータフレームを持っている:

df <- data.frame(
    d1 = c('2016-01-30 08:40:00 UTC', '2016-03-06 09:30:00 UTC'), 
    d2 = c('2016-01-30 16:20:00 UTC', '2016-03-06 13:20:00 UTC'), 
    tz = c('America/Los_Angeles', 'America/Chicago'), stringsAsFactors = FALSE) 

私はこのようなデータフレームを取得するには、現地時間のUTC時刻を変換したい:

    d1     d2     tz 
1 2016-01-30 00:40:00 2016-01-30 08:20:00 America/Los_Angeles 
2 2016-03-06 03:30:00 2016-03-06 07:20:00  America/Chicago 

これを行うために、私は、適用したいと思います日付列に、lubridateライブラリを使用して、ローカル時刻にUTC時刻を変換する以下の機能、:

getLocTime <- function(d, tz) { 
    as.character(with_tz(ymd_hms(d), tz)) 
} 

dplyrを使用するには、その変換が

ようです
df %>% mutate(d1 = getLocTime(d1, tz), d2 = getLocTime(d2, tz)) 

トリックを行う必要があります。しかし、それは苦情Error in eval(expr, envir, enclos): invalid 'tz' valueで失敗します。

私はローカル時刻に変換を行うことができた唯一の方法はかなり不格好割り当て

df[c('d1', 'd2')] <- lapply(c('d1', 'd2'), 
          function(x) unlist(Map(getLocTime, df[[x]], df$tz))) 

である実際にdplyrイディオムを使用して、この変換を実行するための自然な方法はありますか?

+3

「getLocTime(c)」(2016-01-30 08:40:00 UTC、「2016-03-06 09:30:00 UTC」)、c(「America/Los_Angeles」、「America /シカゴ "))'第一の 'mutate'のためには動作しません。あなたは、あなたの関数をベクトル化することができます。 'vgetLocTime < - Vectorize(getLocTime、c(" d "、" tz "))'。 – lukeA

+1

あなたの関数を 'Vectorize'して@lukeAを提案したならば、' mutate_each'を使って複数の列を変更しやすくすることもできます: 'df%>%mutate_each(funs(getLocTime(。、tz))、matches(" d "))' – eipi10

+0

@lukeA:パーフェクト、それは動作します!ありがとうございました。 (dplyrのドキュメントは、列変換関数を適用するときにベクトル化する必要性についてより明白になるかもしれません...) – egnha

答えて

3

getLocTimeがベクトル化されていないため、lukeAで述べたように問題が発生します。だから、どちらかあなたが提案としての機能をベクトル化、またはあなたがあなたの関数の行方向を実行します。getLocTimeは、単一の番号ではなくベクトルと呼ばれていることを確認します

df %>% rowwise() %>% mutate(d1 = getLocTime(d1, tz), d2 = getLocTime(d2, tz)) 

。どのアプローチがより速いかを判断するために、私はあなたに任せます。

+0

私はタイミングをチェックしていませんが、過去の経験に基づいて、 'rowwise'はかなり遅くなる傾向があります。 – eipi10

関連する問題