2016-07-14 79 views
0

我試圖找到一個沒有複雜子集和/或逐行迭代的優雅解決方案。我會通過例子來解釋:彙總條件語句

# Load data 
df1 <- mtcars 

# Can aggregate with simple math functions i.e. mean or sum 
hp_by_cyl <- aggregate(hp ~ cyl, data=df1, mean) 
> hp_by_cyl 
    cyl  hp 
1 4 82.63636 
2 6 122.28571 
3 8 209.21429 

好的。但是,在我真正更復雜的數據中,我希望彙總一個邏輯值 - 即,如果屬於類別A的任何行的x爲真,則y = 1。所以致以例如我可以創建邏輯變量柱:

df1$logic <- ifelse(df1$gear==4 & df1$hp < 150, 1, 0) 
# How do I aggregate the logical values levels of cyl to answer yes/no 
# if any car with x cylinders has 4 gears and < 150 hp ? 
# So I want an finished table like this: 
cyl  logic 
4  1 
6  1 
8  0 

我的問題是如何使用集合體(或替代)命令,以產生像這樣的表?即組合邏輯狀態而不是數值?

我還需要處理也是在現實中編碼缺失值,從而效仿這種複雜性,我會做出一個邏輯的99:

df1[5, ]$logic <- 99 

如果cyl一個價值的一定水平是1, 99可以忽略 - 但如果所有其他人都是0,那麼聚合應該是99.

道歉,如果有一個簡單的答案我沒有看到我的真實數據,它似乎令人望而生畏。我可以破解一個令人討厭的解決方案,但我知道它會很慢,我有一個14000 X 140大小的數據集。預先感謝所有。

+3

什麼問題? – Carl

+0

我不知道如何編寫它來生成我想要的彙總表。編輯爲clariaty – user2498193

回答

1

首先,不要打擾0/1/99,只是將它保留爲TRUE/FALSE/NA。

df1$logic <- df1$gear==4 & df1$hp < 150 

然後,只需用聚合或anytapply

aggregate(logic ~ cyl, data=df1, any) 
## cyl logic 
## 1 4 TRUE 
## 2 6 TRUE 
## 3 8 FALSE 

with(df1, tapply(logic, cyl, any)) 
## 4  6  8 
## TRUE TRUE FALSE 

的plyr包,特別是ddply功能,是許多人認爲更直觀的另一種選擇。

library(plyr) 
ddply(df1, ~cyl, summarize, isany = any(gear==4 & hp < 150)) 
## cyl isany 
## 1 4 TRUE 
## 2 6 TRUE 
## 3 8 FALSE 
+0

嗨亞倫。嗯是的,這可能會工作,我會盡力讓你知道。改變0/1/99可能會很棘手,因爲東西之間相互依賴,我可能需要區分實際NA和編碼錯誤。我也想出了另一個解決方案,但它不是那麼幹淨。 'result < - aggregate(logic〜cyl,data = df1,sum);結果< - ifelse(結果> 99,1,結果)'。這當然依賴於沒有99 1的!因此,正如我說的不是那樣乾淨你的 – user2498193

+0

你應該處理您的各種missingness當您創建邏輯列,這樣的邏輯列本身可以是TRUE/FALSE/NA。 – Aaron

+0

如果我以前沒有錯誤,它不應該出現......所以在實時數據中嘗試你的方法,但對於每個分組變量,結果是'.Primitive(「any」)'。不知道爲什麼看不到任何明顯的原因,但我仍在探索它。編輯:好吧,通過取出我因某種原因遺留在內的'function(x)'來修復它。好的,謝謝你解決我的問題! – user2498193

2

我想這是你想要的東西:

aggregate(hp~cyl,data=mtcars,function(x) ifelse(mean(x)<150,1,0)) 

編輯: dplyr是你的朋友:

mtcars %>% group_by_(~cyl) %>% summarise_(logic=~ifelse(mean(hp)<150 & sum(wt)>3,1,0)) 

這有一個更復雜的邏輯語句,所以希望有幫助。如果您想一次處理2個以上的變量,則不是最好的方法。

+0

作品在玩具的例子 - 將檢查主要數據和回來確認/併發症!感謝您澄清我的問題和答案! – user2498193

+2

'as.integer(mean(x)<150)'可以取代'ifelse()'二進制結果,並且效率更高。 –

+0

其實不 - 再看一遍 - 這是不一樣的。您平均完成了一項測試。這是有效的,因爲這個例子很粗糙,但它不是我在上面提出的,我故意設置了一列邏輯值。在實際數據中,「邏輯」列是大量工作的結果,不能簡化,因爲您已在此處完成 – user2498193