2017-06-20 75 views
0

給定下面的data.table,如何獲得期望的結果? 'grpFreq'列包含原始data.table中每個'grp'的計數,'posCnt'列包含每個組'val'中正數的計數,'比'列是posCnt/grpFreq。返回組頻率,滿足條件的值的計數和比率,按data.table中的組計算

library(data.table) 

DT <- data.table(grp = c(1,2,5,5,5,5,3,4,4,4), val = c(-1,0,1,1,-1,1,1,-1,-1,1)) 
DT 

    grp val 
1: 1 -1 
2: 2 0 
3: 5 1 
4: 5 1 
5: 5 -1 
6: 5 1 
7: 3 1 
8: 4 -1 
9: 4 -1 
10: 4 1 

這個期望的結果:

# grp grpFreq posCnt ratio 
# 1  1  0  0 
# 2  1  0  0 
# 3  1  1  1 
# 4  3  1  0.33 
# 5  4  3  0.75 

下試圖讓我的方式的一部分。首先,從「VAL」列中的值> 0的計數都在這裏最右邊的列(「-1」,而不是需要「0」列):

dcast(DT, grp~val, length) 

    grp -1 0 1 
1: 1 1 0 0 
2: 2 0 1 0 
3: 3 0 0 1 
4: 4 2 0 1 
5: 5 1 0 3 

第二,這讓我一個每個'grp'的頻率計數,但不是與上述相同的形式:

library(dplyr) 
DT %>% 
    group_by(grp) %>% 
    mutate(count = n()) 

    grp val count 
    (dbl) (dbl) (int) 
1  1 -1  1 
2  2  0  1 
3  5  1  4 
4  5  1  4 
5  5 -1  4 
6  5  1  4 
7  3  1  1 
8  4 -1  3 
9  4 -1  3 
10  4  1  3 

任何想法?非常感謝!!

+0

我建議執行所有的計算作爲一個'dplyr'管道的一部分。你的'dplyr'代碼的問題在於你'group_by(grp)',但是你不會在這些組中進行「概括」,你只是'mutate'。 'mutate'將返回數據集中相同數量的行,而不是'grp'中每個值的單個實體。這就是爲什麼它不像你期望的那樣工作。 –

+0

另外,不確定是否有特定的原因用'data.table'創建示例數據。你可以像'dplyr'包一樣輕鬆地使用'data.frame()'或'data_frame()'。只是說,如果你認爲你需要使用'data.table'庫來創建你的樣本數據。 –

+0

Hi @StevenMortimer。感謝您缺少的鏈接。當時我無法理解語法,但現在有意義。所以每個元素的結果都可用於管道中的後續元素,很好。我的數據恰好在data.table中,因此在這裏使用。 –

回答

1
DT <- data.table(grp = c(1,2,5,5,5,5,3,4,4,4), val = c(-1,0,1,1,-1,1,1,-1,-1,1)) 

DT %>% 
    group_by(grp) %>% 
    summarize(grpFreq = length(grp), 
      posCnt = sum(val > 0)) %>% 
    mutate(ratio = posCnt/grpFreq) 

# A tibble: 5 × 4 
    grp grpFreq posCnt  ratio 
    <dbl> <int> <int>  <dbl> 
1  1  1  0 0.0000000 
2  2  1  0 0.0000000 
3  3  1  1 1.0000000 
4  4  3  1 0.3333333 
5  5  4  3 0.7500000 
+0

嗨史蒂文。感謝您的dplyr版本。 @Imo首先回答如此標記爲解決方案,儘管這在使用我的數據集50k行和3k列時是等同的。 –

+0

只要你知道提出的答案的順序取決於upvotes或反對票的數量,而不是當有人按時間順序回答問題時。我在@lmo之前15分鐘回答,但因爲它的投票次數較少,所以名單較低。無論頁面上的順序如何,您都應該標記最能回答您問題的答案。 –

+0

@SteveMortimer謝謝你的提醒。這2個答案與我目前的使用相同。我只用時間順序來打破領帶。道歉回憶。現在修復。 –

2

data.table,你可以在一個呼叫做

DT[order(grp), .(grpFreq=.N, posCnt=sum(val > 0), ratio=sum(val > 0)/.N), by=grp] 

或更好的使用鏈和:=

DT[order(grp), .(grpFreq=.N, posCnt=sum(val > 0)), by=grp][, ratio := posCnt/grpFreq][] 

第二種方法可能是優選的,因爲它減少計算數量並且使用:=進行分配的內存效率很高。第二次調用結束時的[]在實踐中並不是必需的,但會告知data.table將結果打印到屏幕上。

兩個返回

grp grpFreq posCnt  ratio 
1: 1  1  0 0.0000000 
2: 2  1  0 0.0000000 
3: 3  1  1 1.0000000 
4: 4  3  1 0.3333333 
5: 5  4  3 0.7500000 
+0

Hi @Imo。我的代碼甚至沒有接近這個!謝謝你的澄清。要解密我在[link](https://s3.amazonaws。)上使用DataCamp備忘單的語法,COM/assets.datacamp.com/IMG /博客/數據+表+欺騙+ sheet.pdf) –