2016-06-09 104 views
1

**編輯,因爲我是doofus - 與更換,不無**生成按組的隨機數替換

我有一個大的肥胖型(> 50萬行)數據集4​​21個基團,由兩個限定分組變量。樣品數據如下:

df<-data.frame(group_one=rep((0:9),26), group_two=rep((letters),10)) 

head(df) 

    group_one group_two 
1   0   a 
2   1   b 
3   2   c 
4   3   d 
5   4   e 
6   5   f 

...等等。

我想要的是通過(group_one x group_two)中的成員資格的分層樣本的某個數字(k = 12,但該數字可能會有所不同)。每個組的成員資格都應該用一個新的列sample_membership來表示,該列的值爲1到k(現在再次是12)。我應該可以通過sample_membership進行子集化,並獲得12個不同的樣本,每個樣本在考慮group_one和group_two時都具有代表性。因此

最終數據會是這個樣子:

group_one group_two sample_membership 
1   0   a     1 
2   0   a    12 
3   0   a     5 
4   1   a     5 
5   1   a     7 
6   1   a     9 

的思考?首先十分感謝!

+1

你的標題說「沒有替換」,但你的問題沒有提到它。您是否想要取樣而不更換(並且您保證每個分組<= 12行)? – Gregor

+0

這是一個錯誤。一定要更換。我對這種混亂表示歉意。 – seehuus

+0

隨意編輯您的問題標題以糾正錯誤。 – Gregor

回答

4

這裏有一個單行data.table方法,如果你有很長的data.frame,你一定要考慮這個問題。

library(data.table) 

setDT(df) 

df[, sample_membership := sample.int(12, .N, replace=TRUE), keyby = .(group_one, group_two)] 

df 
# group_one group_two sample_membership 
# 1:   0   a     9 
# 2:   0   a     8 
# 3:   0   c    10 
# 4:   0   c     4 
# 5:   0   e     9 
# ---          
# 256:   9   v     4 
# 257:   9   x     7 
# 258:   9   x    11 
# 259:   9   z     3 
# 260:   9   z     8 

對於沒有更換採樣,使用replace=FALSE,但在其他地方所指出的,請確保您有每組少於ķ成員。 OR:

如果你想用「抽樣避免不必要更換」(使這個了 - 不知道正確的術語是什麼在這裏),因爲你每組有超過ķ成員,但仍想保留該組的大小均勻越好,你可以這樣做:

# example with bigger groups 
k <- 12L 
big_df <- data.frame(group_one=rep((0:9),260), group_two=rep((letters),100)) 
setDT(big_df) 

big_df[, sample_round := rep(1:.N, each=k, length.out=.N), keyby = .(group_one, group_two)] 
big_df[, sample_membership := sample.int(k, .N, replace=FALSE), keyby = .(group_one, group_two, sample_round)] 
head(big_df, 15) # you can see first repeat does not occur until row k+1 

在每個「採樣圓」(前K組中的組中的觀察,第二K意見等)有不放回抽樣。然後,如有必要,下一輪採樣可以再次提供所有k個分配。

這種方法將真正均勻分層樣本(但只有在每個組中有多個k成員時纔可能完全平均)。

0

未經檢驗的例子使用dplyr,如果它不起作用,它可能會指向你在正確的方向。

library(dplyr) 
set.seed(123) 
df <- data.frame(
    group_one = as.integer(runif(1000, 1, 6)), 
    group_two = sample(LETTERS[1:6], 1000, TRUE) 
) %>% 
    group_by(group_one, group_two) %>% 
    mutate(
    sample_membership = sample(seq(1, length(group_one)), length(group_one), FALSE) 
) 

祝你好運!

+0

僅供參考,您可以使用'dplyr :: n()'代替'length(group_one)''只需保存一些輸入內容。 – Shorpy

+0

謝謝,雖然這個做的隨機分佈從1到(group_one x group_two)中的項目數量,並且在12時不會達到峯值。不知道我是否可以將每個組中的項目數除以12,並將round/truncate 。我會考慮。再次感謝! – seehuus

4

也許這樣的事情?:

library(dplyr) 
    df %>% 
    group_by(group_one, group_two) %>% 
    mutate(sample_membership = sample(1:12, n(), replace = FALSE)) 
2

這是一個基礎R方法,即假定您的data.frame由組排序:

# get number of observations for each group 
groupCnt <- with(df, aggregate(group_one, list(group_one, group_two), FUN=length))$x 

# for reproducibility, set the seed 
set.seed(1234)  
# get sample by group 
df$sample <- c(sapply(groupCnt, function(i) sample(12, i, replace=TRUE))) 
+0

這很好,但似乎有一些(group_one x group_two)與零成員的組合,因此groupCnt最終會有一些NAs。如果我爲這些NAs交換零,結果是df $ sample的行少於df,因此失敗。思考? – seehuus

+0

它似乎在你的例子中工作。你能提供一個data.frame發生這種情況嗎? 'aggregate'只創建一個data.frame,只存在組1和組2的組合。由於groupCnt是使用'length'函數構造的,因此它不應該生成NA。 – lmo

+0

一種可能性是,您的原始數據中每組有12個以上的觀察值。如果是這種情況,您必須將樣品限制在前12個(或隨機選擇的12個)樣品中,在每個組內進行替換,或將k增加到每個組的最大數量以上。 – lmo