2015-11-19 15 views
11

Gibt es eine elegante Möglichkeit, NA als 0 (na.rm = TRUE) in dplyr zu behandeln?NA in dplyr Zeilensumme ignorieren

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 

auch wenn ich weiß, dass dies in vielen anderen Fällen nicht das gewünschte Ergebnis ist

Antwort

22

Sie diese verwenden:

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)) 

Ausgang:

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

das ist wunderbar! Vielen Dank – ckluss

+0

Sie sind herzlich willkommen @ckluss. Ich habe den "dplyr-ic" Weg (wenn ich das in dem Sinne sagen kann, dass dplyr auf traditionelle Weise wie in den Tutorials verwendet wird) getan. Die Verwendung anderer Basisfunktionen (allein oder in Verbindung mit dplyr) ist jedoch definitiv effizienter als meine. Die Antworten von StevenBeaupre und Akrun sind effizienter und Sie wären wahrscheinlich besser dran, wenn Ihnen die Geschwindigkeit wichtig ist. – LyzandeR

+0

@LyzandeR Ich denke, die OP wollte den 'dplyr'ish Weg. Also mach dir keine Sorgen über die Effizienz. – akrun

0

Versuchen Sie, diese

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

data Resultierende ist

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

Eine weitere Option:

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

Benchmark

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

Vielleicht könnten Sie akrun's hinzufügen? Ich sehe es bei 1,33 gegen Ihre 1,00 in Einheit = "relativ" (mit dieser Variante: 'Daten%>% mutieren (Summe = Reduzieren (Funktion (x, y) x + ersetzen (y, is.na (y), 0),., init = rep (0, n()))) ') – Frank

+1

@Frank Sicher, ich werde den Benchmark aktualisieren. –

5

Oder wir können replaceNA mit 0 und dann den Code des OP

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

Basierend verwenden, um auf den Benchmarks @ Steven Beaupré Daten verwenden, scheint es, als auch effizient.

Verwandte Themen