2016-07-23 108 views
0

我只會理解函數rowSums的一個(對我來說)奇怪的行爲。想象一下,我有這個超級簡單的數據框:RowSums NA + NA給出0

a = c(NA, NA,3) 
b = c(2,NA,2) 
df = data.frame(a,b) 
df 
    a b 
1 NA 2 
2 NA NA 
3 3 2 

現在我想第三列是其他兩個的總和。我不能使用只是因爲+NA

df$c <- df$a + df$b 
df 
    a b c 
1 NA 2 NA 
2 NA NA NA 
3 3 2 5 

,但如果我用rowSumsNA作爲0計算,如果只有一個NA一切,而行正常工作:

df$d <- rowSums(df, na.rm=T) 
df 
    a b c d 
1 NA 2 NA 2 
2 NA NA NA 0 
3 3 2 5 10 

我錯過了什麼?

感謝所有

+0

我在想,爲什麼沒有人回答'基地:: psum' – rawr

回答

6

一個與rowSums選擇是與na.rm=TRUE得到rowSums與否定(!)邏輯矩陣的否定(!rowSums乘根據該NA值轉換具有所有NAS行到NA之後(NA^

rowSums(df, na.rm=TRUE) *NA^!rowSums(!is.na(df)) 
#[1] 2 NA 10 
+5

這是一個有趣的黑客攻擊:'NA^0 == 1'。 – lmo

+2

您應該將此添加爲鏈接問題的答案 – rawr

5

因爲

sum(numeric(0)) 
# 0 

一旦你rowSums使用na.rm = TRUE,第二行是numeric(0)。採取sum後,爲0.

如果您想保留NA所有NA的情況下,這將是一個兩階段的工作。我建議寫一個小函數用於該目的:

my_rowSums <- function(x) { 
    if (is.data.frame(x)) x <- as.matrix(x) 
    z <- base::rowSums(x, na.rm = TRUE) 
    z[!base::rowSums(!is.na(x))] <- NA 
    z 
    } 

my_rowSums(df) 
# [1] 2 NA 10 

這可以是特別有用的,如果輸入x是數據幀(如在你的情況)。 base::rowSums將首先檢查輸入是否爲矩陣。如果它得到一個數據幀,它會首先將它轉換成一個矩陣。類型轉換實際上比實際的行和計算更昂貴。請注意我們兩次撥打base::rowSums。爲了減少類型轉換的開銷,我們應該確保x事先是一個矩陣。

對於@ akrun的 「黑客」 的答案,我建議:

akrun_rowSums <- function (x) { 
    if (is.data.frame(x)) x <- as.matrix(x) 
    rowSums(x, na.rm=TRUE) *NA^!rowSums(!is.na(x)) 
    } 

akrun_rowSums(df) 
# [1] 2 NA 10 
+0

mm ok ..但是如果我想在第三欄中保留NA,該怎麼辦? – matteo

+4

這可能是一個2步驟的過程。例如,'df $ new < - rowSums(df,na.rm = T); is.na(df $ new)< - rowSums(is.na(df))== length(df)' – lmo