2015-11-19 6 views
11

dplyrでNAを0(na.rm = TRUE)として扱うためのエレガントな方法はありますか?dplyr行の合計でNAを無視する

data <- data.frame(a=c(1,2,3,4), b=c(4,NA,5,6), c=c(7,8,9,NA)) 

data %>% mutate(sum = a + b + c) 

a b c sum 
1 4 7 12 
2 NA 8 NA 
3 5 9 17 
4 6 NA NA 

but I like to get 

a b c sum 
1 4 7 12 
2 NA 8 10 
3 5 9 17 
4 6 NA 10 

私は、これは他の多くの例では望ましい結果ではないことを知っている場合でも

答えて

22

次のとおりです。

library(dplyr) 
data %>% 
    #rowwise will make sure the sum operation will occur on each row 
    rowwise() %>% 
    #then a simple sum(..., na.rm=TRUE) is enough to result in what you need 
    mutate(sum = sum(a,b,c, na.rm=TRUE)) 

出力:

Source: local data frame [4 x 4] 
Groups: <by row> 

     a  b  c sum 
    (dbl) (dbl) (dbl) (dbl) 
1  1  4  7 12 
2  2 NA  8 10 
3  3  5  9 17 
4  4  6 NA 10 
+0

素晴らしいです!ありがとうございました – ckluss

+0

あなたは大歓迎です。私はこれを行うことの最も良い方法を提供しました(私がこれを言うことができれば、それは伝統的な方法でdplyrを使っているという意味で)。しかし、他の基本関数(単独またはdplyrと組み合わせて)を使うことは、私の場合よりもはるかに効率的です。 StevenBeaupreとAkrunの答えはより効率的なので、スピードがあなたにとって重要であるならば、おそらくそれらの方が良いでしょう。 – LyzandeR

+0

@LyzandeR私はOPが 'dplyr'を欲しかったと思う。だから、効率を心配しないでください。 – akrun

0

data結果として得られるこの

data$sum <- apply(data, 1, sum, na.rm = T) 

を試してみてはあなたがこれを使用することができ

a b c sum 
1 1 4 7 12 
2 2 NA 8 10 
3 3 5 9 17 
4 4 6 NA 10 
12

別のオプション:

data %>% 
    mutate(sum = rowSums(., na.rm = TRUE)) 

ベンチマーク

library(microbenchmark) 
mbm <- microbenchmark(
steven = data %>% mutate(sum = rowSums(., na.rm = TRUE)), 
lyz = data %>% rowwise() %>% mutate(sum = sum(a, b, c, na.rm=TRUE)), 
nar = apply(data, 1, sum, na.rm = TRUE), 
akrun = data %>% mutate_each(funs(replace(., which(is.na(.)), 0))) %>% mutate(sum=a+b+c), 
frank = data %>% mutate(sum = Reduce(function(x,y) x + replace(y, is.na(y), 0), ., 
            init=rep(0, n()))), 
times = 10) 

enter image description here

#Unit: milliseconds 
# expr   min   lq  mean  median   uq  max neval cld 
# steven 9.493812 9.558736 18.31476 10.10280 22.55230 65.15325 10 a 
# lyz 6791.690570 6836.243782 6978.29684 6915.16098 7138.67733 7321.61117 10 c 
# nar 702.537055 723.256808 799.79996 805.71028 849.43815 909.36413 10 b 
# akrun 11.372550 11.388473 28.49560 11.44698 20.21214 155.23165 10 a 
# frank 20.206747 20.695986 32.69899 21.12998 25.11939 118.14779 10 a 
+1

あなたはakrunを追加できますか?私は1.33対1.00の単位であなたの1.00を参照してください(このバリエーションを使用して、この変形例を使用してください:%データ%%mutate(合計= Reduce(関数(x、y)x + replace(y、is.na(y)、0 )、。、init = rep(0、n()))) ') – Frank

+1

@Frank確かに、ベンチマークを更新します。 –

5

それとも我々はその後、0とreplaceNAとは@Stevenボープレデータを使ってベンチマークに基づいてOPのコード

data %>% 
    mutate_each(funs(replace(., which(is.na(.)), 0))) %>% 
    mutate(Sum= a+b+c) 
    #or as @Frank mentioned 
    #mutate(Sum = Reduce(`+`, .)) 

を使用することができ、同様に効率的であると思われます。