2017-12-27 882 views
1

這裏是我想要做的事:優雅的方式,如果else語句的多組

創建分配樣本秩,以行的多個子集的新列基於有多少行是每個子集。分組變量是「層」列。

我通常使用嵌套ifelse語句隨機分配排名,如下所示。有時候這樣做足夠了,但最近我一直在處理越來越多的分組。 40個嵌套ifelse語句可能開始看起來有點過分。

是否有一個更優雅/更快/最簡單的代碼方式來使用dplyr或data.table,可能與apply,lapply,sapply等結合使用?

我試圖使用data.table語句,但我不知道如何使用nrow插入示例函數。

重現數據:

dta <- data.frame(
    uniqueID = c(950513, 951634, 951640, 951641,951646, 952732, 952895, 952909, 952910, 952911, 952912,952923, 952924, 952925, 952926, 952927, 952928L, 952933, 
      952934, 952935), 
    stratum = c("group9","group6","group15","group13","group9","group8","group9","group15","group15","group15","group15", "group13", "group13", 
      "group1", "group1", "group1", "group1", "group1", "group1", "group1") 
) 

下面是我通常會指派一個隨機等級,使用netsed ifelse聲明:

dta<- dta[order(dta$stratum),] 
set.seed(7265)                             

dta$rank <- ifelse(dta$stratum== "group1",sample(1:nrow(dta[dta$stratum== "group1",])), 
       ifelse(dta$stratum=="group6",sample(1:nrow(dta[dta$stratum== "group6",])), 
         ifelse(dta$stratum=="group8",sample(1:nrow(dta[dta$stratum== "group8",])), 
          ifelse(dta$stratum=="group9",sample(1:nrow(dta[dta$stratum== "group9",])), 
            ifelse(dta$stratum=="group13",sample(1:nrow(dta[dta$stratum== "group13",])), 
              ifelse(dta$stratum=="group15",sample(1:nrow(dta[dta$stratum== "group15",])), 
                0)))))) 

回答

1

使用data.table解決方案:

library(data.table) 
setDT(dta)[, rank := sample(1:.N), stratum] 

#  uniqueID stratum rank 
# 1: 952925 group1 4 
# 2: 952926 group1 2 
# 3: 952927 group1 1 
# 4: 952928 group1 6 
# 5: 952933 group1 7 
# 6: 952934 group1 3 
# 7: 952935 group1 5 
# 8: 951641 group13 2 
# 9: 952923 group13 1 
# 10: 952924 group13 3 
# ... 

說明:

  1. 從1 Transform對象爲data.tablesetDT()
  2. 樣品每組(, stratum])軍銜.N(有多少行是每個組中)
1

使用dplyr,你可以做

library(dplyr) 
dta %>% 
    group_by(stratum) %>% 
    mutate(rank=sample.int(n())) 

group_by允許你在一次行的一個子集進行操作,我們使用內置0從dplyr獲取函數以獲取每組中的行數。我選擇使用效率更高的sample.int而不是sample,但它基本上做同樣的事情。

在一般情況下,嵌套的if-else語句與case_when()dplyr更好地處理,但你在這種情況下,正在做什麼用group_by()

+0

謝謝。我只能接受一個答案,但這個作品也很好! – st2coker

2

是更好地處理考慮基礎R的by,旨在通過因子分裂dataframes( s):

dta$rank <- unlist(by(dta, dta$stratum, FUN=function(df) sample(1:nrow(df)))) 

# uniqueID stratum rank 
# 14 952925 group1 6 
# 15 952926 group1 2 
# 16 952927 group1 1 
# 17 952928 group1 3 
# 18 952933 group1 5 
# 19 952934 group1 7 
# 20 952935 group1 4 
# 4 951641 group13 2 
# 12 952923 group13 1 
# 13 952924 group13 3 
# 3 951640 group15 1 
# 8 952909 group15 3 
# 9 952910 group15 5 
# 10 952911 group15 2 
# 11 952912 group15 4 
# 2 951634 group6 1 
# 6 952732 group8 1 
# 1 950513 group9 2 
# 5 951646 group9 1 
# 7 952895 group9 3 
+1

我幾乎發佈了這個hahah'轉換(dta,rank = unname(unlist(by(dta,stratum,function(x)sample(nrow(x))))))' – Onyambu

+1

偉大的思想家們都像他們說的一樣思考!很高興在這裏看到基地R的支持!乾杯 – Parfait