2017-10-09 52 views
0

我想將vales賦值給一個已命名的矢量,具體取決於我按行循環的df中的值。根據文檔,我發現RHS的情況是什麼時候是一個向量,而我試圖做的是讓RHS成爲一個實際的分配步驟。這可能嗎? Case_when真的不必if語句用更優雅的位置:當使用dplyr情況下爲矢量賦值時

test.df <- data.frame(cat1 = c('label1', 'label2', 'label3'), 
        cat2 = c('label3', '', ''), 
        cat3 = c('', 'label2', 'label1')) 

test.lst <- apply(test.df, 1, function(x){ 
       test.vec <- c(label1 = 0, label2 = 0, label3 = 0) 

       case_when(
        x[['cat1']]=='label1' | x[['cat2']]=='label1' | x[['cat3']]=='label1' ~ test.vec['label1'] <- 1, 
        x[['cat1']]=='label2' | x[['cat2']]=='label2' | x[['cat3']]=='label2' ~ test.vec['label2'] <- 1, 
        x[['cat1']]=='label3' | x[['cat2']]=='label3' | x[['cat3']]=='label3' ~ test.vec['label3'] <- 1 
       ) 
       }) 

回答

4

可以使用transmute功能從dplyr包只保留創建/函數調用修改列。所以你可以創建一個全新的數據框。它應該是這樣的:

test.lst <- test.df %>% 
    transmute(label1 = case_when(
    cat1 == "label1" | cat2 == "label1" | cat3 == "label1" ~ 1, 
    TRUE ~ 0 
), 
    label2 = case_when(
    cat1 == "label2" | cat2 == "label2" | cat3 == "label2" ~ 1, 
    TRUE ~ 0 
), 
    labels3 = case_when(
    cat1 == "label3" | cat2 == "label3" | cat3 == "label3" ~ 1, 
    TRUE ~ 0 
)) 

和您的輸出應該是這樣的:

label1 label2 labels3 
1  1  0  1 
2  0  1  0 
3  1  0  1 

作爲一個說明,在dplyr包和它的大多數功能都量化。因此,它們已經在每個行上執行了所需的操作,而無需使用for循環或apply/map函數。這有助於加速代碼並使其更具可讀性。

+2

由於每個'case_when()'語句只有兩種情況,'if_else()'會的工作了。 –

0

case_when是沒有必要的,這裏是一個替代的解決方案:

sapply(paste0('label', 1:3), function(x) sign(rowSums(as.matrix(test.df) == x))) 
#  label1 label2 label3 
# [1,]  1  0  1 
# [2,]  0  1  0 
# [3,]  1  0  1 
相關問題