2016-11-04 15 views
2

ベクトルをサブセット化しようとする効率的な関数またはコードスニペットを希望し、サブセットに要素がない場合はNAを返します。このサブセット動作はAの一部として使用する場合、大きくない、例えば、サブセットが空の場合はNAを返す関数

v1 = c(1, 1, NA) 

コードunique(v1[!is.na(v1)])戻る大きいつのエントリが、

v2 = c(NA, NA, NA) 

のコードunique(v2[!is.na(v2)])戻るためlogical(0)dplyr鎖はsummarise_eachまたはsummariseを含有する。 logical(0)の代わりにNAを返すよう、2番目の操作をしたいと思います。

この背景の背景には、spread複数のコマンドを使用してthis questionを解決しようとしていることがあります。我々は(別のカラム名とはいえ)所望の出力を達成することができ、複数のスプレッドを使用して、今すぐ

set.seed(10) 
tmp_dat <- data_frame(
    Person = rep(c("greg", "sally", "sue"), each=2), 
    Time = rep(c("Pre", "Post"), 3), 
    Score1 = round(rnorm(6, mean = 80, sd=4), 0), 
    Score2 = round(jitter(Score1, 15), 0), 
    Score3 = 5 + (Score1 + Score2)/2 
) 

> tmp_dat 
Source: local data frame [6 x 5] 

    Person Time Score1 Score2 Score3 
    <chr> <chr> <dbl> <dbl> <dbl> 
1 greg Pre  80  78 84.0 
2 greg Post  79  80 84.5 
3 sally Pre  75  74 79.5 
4 sally Post  78  78 83.0 
5 sue Pre  81  78 84.5 
6 sue Post  82  81 86.5 

:例のデータは、以前の質問から取られすぎがある場合、今

tmp_dat %>% 
    mutate(Time_2 = Time, 
      Time_3 = Time) %>% 
    spread(Time, Score1, sep = '.') %>% 
    spread(Time_2, Score2, sep = '.') %>% 
    spread(Time_3, Score3, sep = '.') %>% 
    group_by(Person) %>% 
    summarise_each(funs(((function(x)x[!is.na(x)])(.)))) 

を、問題が発生します多くのNAさん:

# Replace last two entries in the last row with NA's 
tmp_dat$Score2[6] <- NA 
tmp_dat$Score3[6] <- NA 

今すぐsummarise_eachでコードスニペットを実行すると、エラーが発生します。

Error in eval(substitute(expr), envir, enclos) : expecting a single value 
+1

あなたの行が常にただ1つの値を返すことを知っているならば、最後に '[1]'を追加してください: 'unique(v2 [!is.na(v2)])[1]'。それ以外の場合は、独自の関数を定義するだけです。 'uniqueNotNA <-function(x){ind < - !is.na(x); if(sum(ind)== 0)NA else unique(x [ind])}' – nicola

+0

ありがとうございます。これは効率的ですか?私は最後に[1]が好きです – Alex

答えて

1

これは、簡単に私たちがdplyr/tidyrを使用する必要がある場合は、オプションがgatherに「スコア」の列」になり、複数のvalue.var

library(data.table) 
dcast(setDT(tmp_dat), Person ~paste0("Time.", Time), 
       value.var = c("Score1", "Score2", "Score3")) 
#  Person Score1_Time.Post Score1_Time.Pre Score2_Time.Post Score2_Time.Pre Score3_Time.Post Score3_Time.Pre 
#1: greg    79    80    80    78    84.5   84.0 
#2: sally    78    75    78    74    83.0   79.5 
#3: sue    82    81    NA    78    NA   84.5 

を取ることができたdata.tableからdcastで行うことができます列を単一の列( 'Time1')に変換してから実行します。spread

library(dplyr) 
library(tidyr) 
gather(tmp_dat, Var, Val, Score1:Score3) %>% 
      mutate(TimeN = 'Time', Var = sub("\\D+", "", Var)) %>% 
      unite(Time1, TimeN, Time, Var) %>% 
      spread(Time1, Val) 
# # A tibble: 3 × 7 
# Person Time_Post_1 Time_Post_2 Time_Post_3 Time_Pre_1 Time_Pre_2 Time_Pre_3 
# * <chr>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl> 
#1 greg   79   80  84.5   80   78  84.0 
#2 sally   78   78  83.0   75   74  79.5 
#3 sue   82   NA   NA   81   78  84.5 
+0

ありがとう@akrun。しかし、もし私が他の 'summarize'操作をしようとすると、空のベクトルを返す可能性があるので、' summarize'は失敗します。私はこれらの状況でプレースホルダを返すことができれば嬉しいです。 – Alex

+0

@Alex 'dcast'には、あなたが使う' fun.aggregate'があります。 – akrun

+0

@Alex私はdplyrソリューションで更新しましたが、いくつかの 'summary'ソリューションを探している場合、その例は異なるはずです – akrun

関連する問題