2016-04-28 8 views
2

私はdata.tableを使用しています。「season」という新しい列を作成しようとしています。 .. "MonthName"という列に基づいています。月の日付に基づいてデータテーブルにシーズンカラムを追加する

月の値に基づいてデータテーブルにシーズン列を追加する方が効率的な方法があるかどうかは疑問です。

これは、300,000回の観測のうちの最初の6回です。この表を「dt」とします。私はエラーを取得

rrp totaldemand Year Month Finyear hourminute AvgPriceByTOD MonthName Season 
1: 35.27500  1999  1 1999  00:00  33.09037  Jan  NA 
2: 21.01167  1999  1 1999  00:00  33.09037  Jan Summer 
3: 25.28667  1999  2 1999  00:00  33.09037  Feb Summer 
4: 18.42334  1999  2 1999  00:00  33.09037  Feb  NA 
5: 16.67499  1999  2 1999  00:00  33.09037  Feb  NA 
6: 18.90001  1999  2 1999  00:00  33.09037  Feb Summer 

を::

dt[, Season := ifelse(MonthName = c("Jun", "Jul", "Aug"),"Winter", ifelse(MonthName = c("Dec", "Jan", "Feb"), "Summer", ifelse(MonthName = c("Sep", "Oct", "Nov"), "Spring" , ifelse(MonthName = c("Mar", "Apr", "May"), "Autumn", NA))))] 

返します

rrp   Year Month Finyear hourminute AvgPriceByTOD MonthName 
1: 35.27500  1999  1 1999  00:00  33.09037  Jan 
2: 21.01167  1999  1 1999  00:00  33.09037  Jan 
3: 25.28667  1999  2 1999  00:00  33.09037  Feb 
4: 18.42334  1999  2 1999  00:00  33.09037  Feb 
5: 16.67499  1999  2 1999  00:00  33.09037  Feb 
6: 18.90001  1999  2 1999  00:00  33.09037  Feb 

私は、次のコードを試してみました的な理由のために、この一緒に

Warning messages: 
1: In MonthName == c("Jun", "Jul", "Aug") : 
    longer object length is not a multiple of shorter object length 
2: In MonthName == c("Dec", "Jan", "Feb") : 
    longer object length is not a multiple of shorter object length 
3: In MonthName == c("Sep", "Oct", "Nov") : 
    longer object length is not a multiple of shorter object length 
4: In MonthName == c("Mar", "Apr", "May") : 
    longer object length is not a multiple of shorter object length 

をそのIわからない、夏のいくつかの月は「夏」は正しく割り当てられますが、他のものはNAが割り当てられます。たとえば、行1と2は両方とも夏でなければなりません。

ありがとうございます!

+1

%Month%%in%c( "Jun"、...) '、not = ' – SymbolixAU

+2

**エラー**ではありません**警告** – SymbolixAU

+0

重複したレベルを作成して削除するのは理想的ではありませんが、通常は数字の月に' cut'を使用します: 'droplevels(cut dt $ Month、breaks = c(0,2,5,8,11,13)、labels = c( 'Winter'、 'Spring'、 'Summer'、 'Autumn'、 'Winter'))) ' – alistaire

答えて

7

一つの非常に簡単な方法は、季節に月名をマッピングするためのルックアップテーブルを使用することです:

# create a named vector where names are the month names and elements are seasons 
seasons <- rep(c("winter","spring","summer","fall"), each = 3) 
names(seasons) <- month.abb[c(6:12,1:5)] # thanks thelatemail for pointing out month.abb 
seasons 
#  Jun  Jul  Aug  Sep  Oct  Nov  Dec  Jan 
#"winter" "winter" "winter" "spring" "spring" "spring" "summer" "summer" 
#  Feb  Mar  Apr  May 
#"summer" "fall" "fall" "fall" 

それを使用します。

dt[, season := seasons[MonthName]] 

データ:

dt <- setDT(read.table(text=" rrp   Year Month Finyear hourminute AvgPriceByTOD MonthName 
1: 35.27500  1999  1 1999  00:00  33.09037  Jan 
2: 21.01167  1999  1 1999  00:00  33.09037  Jan 
3: 25.28667  1999  2 1999  00:00  33.09037  Feb 
4: 18.42334  1999  2 1999  00:00  33.09037  Feb 
5: 16.67499  1999  2 1999  00:00  33.09037  Feb 
6: 18.90001  1999  2 1999  00:00  33.09037  Feb", 
    header = TRUE, stringsAsFactors = FALSE)) 
+0

あなたは南半球のどこかにいます。 – alistaire

+0

@alistaire - 私は米国を推測すると思います: "fall";) – SymbolixAU

+0

@allistaire、OPのマッピングに基づいて月を季節にマッピングしました。 "落ちる"は私の貢献だった。 – Jota

4

タイピングのビットが、コードが効率的である

dt[MonthName %in% c("Jun","Jul","Aug"), Season := "Winter"] 
dt[MonthName %in% c("Dec","Jan","Feb"), Season := "Summer"] 
dt[MonthName %in% c("Sep","Oct","Nov"), Season := "Spring"] 
dt[is.na(MonthName), Season := "Autumn"] 

ここではdata.table

のサブセットにすることによって、基準割り当てるI入れ子ifelse S

のロットにこれを好みます

値がベクター内にあるかどうかを確認する場合は、%in%を使用する必要があります。異なる動作を参照してください。

myVec <- c("a","b","c") 

"a" == myVec 
[1] TRUE FALSE FALSE 

"a" %in% myVec 
[1] TRUE 
+2

おそらく参照テーブルを作成して 'ref < - data.table(MonthName = month.abb [c(12,1:11)]、season = rep(c(" Summer "、" Autumn " "Winter"、 "Spring")、each = 3)); dt [ref、on = "MonthName"] ' – thelatemail

+0

@thelatemail - 私から+1を得たJotaの回答に似ています:) – SymbolixAU

+0

おっと...私がコメントを書いている間、ページはリフレッシュされませんでした。 – thelatemail