2016-03-30 26 views
0

誰かが、新しい列の値を設定するための引数として1つの列を取る関数を適用する次のdplyr mutate呼び出しがなぜ機能しないのか説明できますか?関数を正しい値で呼び出すようには見えません。新しいseason列は、それ自身の行の値ではなくmon列の最初の値に従って設定されます。dplyr関数の呼び出しで不正な値を返す

# Function to return season (winter, summer, or transition) given numerical month 
getSeason <- function(m) { 
    if(m >= 11 || m <= 3) 
    return(as.factor("Winter")) 
    if(m >= 5 && m <= 9) 
    return(as.factor("Summer")) 
    return(as.factor("Trans")) 
} 

getSeason(5) # Works: returns "Summer" 

mon <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) 
months <- as.data.frame(mon) 

months %>% mutate(season=getSeason(mon)) # doesn't work: all seasons set as "Winter" 

私はRバージョン3.2.4と最新の開発版dplyrを使用しています。 (これはどちらか、dplyrの最新リリースで働いていませんでした。)

答えて

4

またVectorizeを使用することができます:あなたが問題を持った理由

# Function to return season (winter, summer, or transition) given numerical month 
getSeason <- function(m) { 
    if(m >= 11 || m <= 3) 
    return(as.factor("Winter")) 
    if(m >= 5 && m <= 9) 
    return(as.factor("Summer")) 
    return(as.factor("Trans")) 
} 


getSeason <- Vectorize(getSeason) 

mon <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) 
months <- data.frame(mon = mon) 

months %>% mutate(season=gs(mon)) 
2

ifは(不気味)ベクトル化されていないので、それだけ、すなわち1monの最初の値を使用していますので、あなたはすべてのWinterを取得しています。これを避けるために

、どのベクトル化され、ifelseを使用する:あなたは本当に連続する数値を回しているようあなたは、代わりにcutを、ifelse Sを入れ子にすることは厄介な取得に十分なレベルを追加使用したい場合は

months %>% mutate(season = factor(ifelse(mon >= 11 | mon <=3, 
             'Winter', ifelse(mon >= 5 & mon <= 9, 
                  'Summer', 'Trans')))) 
# mon season 
# 1 1 Winter 
# 2 2 Winter 
# 3 3 Winter 
# 4 4 Trans 
# 5 5 Summer 
# 6 6 Summer 
# 7 7 Summer 
# 8 8 Summer 
# 9 9 Summer 
# 10 10 Trans 
# 11 11 Winter 
# 12 12 Winter 

データを因子データに変換します。これはcutの目的です。

months %>% mutate(season = droplevels(cut(months$mon, c(0, 3, 4, 9, 10, 12), 
              c('Winter', 'Trans', 'Summer', 'Trans', 'Winter')))) 

警告を発生させます。この場合、重複したレベルをクリーンアップする注droplevels、。

+0

ありがとうございます。 – Nat

5

他の回答がうまく説明しました。

私は、これは新しい機能case_whenは(開発版、dplyr_0.4.3.9001で現在入手可能な)便利になる可能性が状況だと思います。

case_whenmutateに使用するには、ドル記号表記を使用する必要があります。

months %>% mutate(season = case_when(.$mon >= 11 | .$mon <= 3 ~ "Winter", 
            .$mon >= 5 & .$mon <= 9 ~ "Summer", 
            TRUE ~ "Trans")) 

    mon season 
1 1 Winter 
2 2 Winter 
3 3 Winter 
4 4 Trans 
5 5 Summer 
6 6 Summer 
7 7 Summer 
8 8 Summer 
9 9 Summer 
10 10 Trans 
11 11 Winter 
12 12 Winter 

あなたはcase_whenの代わりに、ifまたはifelse(または新規dplyr機能if_else)を使用して機能を構築することができます。私にとっては、構文はifelseでネストするよりも、ifを使用するほうが似ています。

「他のすべて」の条件が case_whenで最後に行われ、あなただけの最終的な値を持つ他のすべてを埋めるために式の左側に TRUEを配置する必要がありますされていることを
getSeason <- function(m) { 
    factor(
     case_when(
      m >= 11 | m <= 3 ~ "Winter", 
      m >= 5 & m <= 9 ~ "Summer", 
      TRUE ~ "Trans" 
      ) 
     ) 
} 

months %>% mutate(season=getSeason(mon)) 

    mon season 
1 1 Winter 
2 2 Winter 
3 3 Winter 
4 4 Trans 
5 5 Summer 
6 6 Summer 
7 7 Summer 
8 8 Summer 
9 9 Summer 
10 10 Trans 
11 11 Winter 
12 12 Winter 

注意。

関連する問題