2013-02-22 54 views
0

我試圖從包含缺少觀察值的數據框中對子行進行子集分析。我可以選擇符合特定條件的行。但是,使用!時,我無法選擇不符合相同條件的行。最終,我能夠通過使用-排除不符合所需條件的行。當缺少觀察數據時對子行進行邏輯比較

有沒有辦法用!排除所需的行?

下面是一個例子的數據集:

df = read.table(text = " 
    state county var1.a var2.a var1.b var2.b 
     1  1  10  25  20  25 
     1  2  20  15  20  15 
     2  1  30  NA  40  25 
     2  2  40  35  10  35 
     3  1  20  45  10  NA 
     3  2  20  55  20  55 
     4  1  NA  65  NA  NA 
     4  2  80  NA  30  NA 
     5  1  NA  15  NA  15 
     5  2  NA  15  NA  35 
", na.strings = "NA", header = TRUE) 

# 1. works, selects Rows 2, 6 and 9, rows in which columns 3 and 5 are the same and 
# columns 4 and 6 are the same 

df[ (which((((df$var1.a == df$var1.b) | (is.na(df$var1.a) & is.na(df$var1.b))) & 
       ((df$var2.a == df$var2.b) | (is.na(df$var2.a) & is.na(df$var2.b)))) , arr.ind=TRUE)),] 

# 2. does not work when excluding Rows 2, 6 and 9, does not retain Row 7 

df[ (which(!(((df$var1.a == df$var1.b) | (is.na(df$var1.a) & is.na(df$var1.b))) & 
       ((df$var2.a == df$var2.b) | (is.na(df$var2.a) & is.na(df$var2.b)))) , arr.ind=TRUE)),] 

# 3. does not work, does not select any rows 

df[!(which((((df$var1.a == df$var1.b) | (is.na(df$var1.a) & is.na(df$var1.b))) & 
       ((df$var2.a == df$var2.b) | (is.na(df$var2.a) & is.na(df$var2.b)))) , arr.ind=TRUE)),] 

# 4. works, selects Rows 1,3,4,5,7,8,10 

df[-(which((((df$var1.a == df$var1.b) | (is.na(df$var1.a) & is.na(df$var1.b))) & 
       ((df$var2.a == df$var2.b) | (is.na(df$var2.a) & is.na(df$var2.b)))) , arr.ind=TRUE)),] 

第二which上述聲明不會選擇第7行,因爲:

(((df$var1.a == df$var1.b) | (is.na(df$var1.a) & is.na(df$var1.b))) & 
    ((df$var2.a == df$var2.b) | (is.na(df$var2.a) & is.na(df$var2.b)))) 

回報:

# [1] FALSE TRUE FALSE FALSE FALSE TRUE NA FALSE TRUE FALSE 

所以,我想我明白爲什麼!在這種情況下不起作用;但我無法弄清楚如何獲得:

# [1] FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE 

如何修改第二which聲明,除了行1,3,4,5,8,10也返回第7行?如果沒有缺失的觀察結果,則第二個which聲明可以工作。

即使沒有缺失觀察值,第三個which聲明也不起作用。我知道-用於刪除行或列。而且我知道!用於邏輯比較。我想第三個which聲明不符合邏輯比較的要求,但第二個which聲明。

我想我可以使用第一個which語句來選擇滿足所需條件的行,並使用第四個which語句來選擇不滿足所需條件的行。但是,我想知道如何通過使用!來選擇不符合所需條件的行。

回答

2

你錯過了一個是NA而另一個不是的情況;它應該是FALSE然後因爲它不匹配,但你得到一個NA。由於這是唯一的情況,當你得到一個NA,我們可以在之後檢查它。這裏有一種方法:

> ok1 <- ((df$var1.a == df$var1.b) | (is.na(df$var1.a) & is.na(df$var1.b))) 
> ok2 <- ((df$var2.a == df$var2.b) | (is.na(df$var2.a) & is.na(df$var2.b))) 
> ok.both <- ok1 & !is.na(ok1) & ok2 & !is.na(ok2) 
> ok.both 
[1] FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE 

而且,這可能是做一個新的功能要做到這一點,像這樣有用:

eqna <- function(a, b) { 
    ok <- ((a == b) | (is.na(a) & is.na(b))) 
    ok & !is.na(ok) 
} 

你會使用這種方式:

> with(df, eqna(var1.a, var1.b) & eqna(var2.a, var2.b)) 
[1] FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE 
+0

隨着hadley的評論,以此答案:http://stackoverflow.com/a/14903764/210673 – Aaron 2013-02-22 21:58:45

0

我可能在這裏寫錯了(從我的手機上寫下來),但看起來#2不起作用的原因僅僅是由於括號。

!只會否定您的子句的前半部分。嘗試在!之後立即添加另一組parens,並在逗號之前將其關閉。

另外,請記住,!只是反轉邏輯值。即它交換T/F,同時將NA留作NA。