2016-07-05 25 views
0

我有一個數據框與大量的變量。這些變量的子集名稱中包含單個數字(例如x1_vx2_v),我想爲任意大小的子集重新編碼這些變量的值。我使用for循環嘗試了以下內容,但它不記錄任何內容。如何通過字符串(變量)和重新編碼值進行循環?

library(car) 
library(magrittr) 

# Sample df 
x1_v <- seq(1:5) 
x2_v <- rep(5,5) 
fun <- c("a","b","c","r","q") 
data <- data.frame(x1_v, x2_v, fun) 

# Loop 
for (i in 1:2){ 
paste0("data$x", i, "_v") %>% 
    assign(paste0("data$x", i, "_v") %>% 
    recode("c(0, 5) = NA")) 
} 

我知道通過使用循環和assign()這違反了幾乎所有的R協議,但我想了解

  1. 爲什麼這不起作用
  2. 我怎麼可能會使用類似申請解決此問題。

我認爲製作一個列表是有道理的,但我希望將所有數據保留在數據框架類中。

+0

'庫(車)'我猜的引用'重新編碼()' – thelatemail

+0

這可能有助於提供你想要什麼樣的輸出是一個例子? –

回答

0
  1. 這是行不通的位:

    assign(paste0("data$x", i, "_v") %>% 
        recode("c(0, 5) = NA") 
    

    你傳入recode一個字符串,如「數據$ x1_v」爲var時,它需要一個向量變量。如果你想進入組合字符串來形成表達式和函數調用的領域,你應該看看eval(),但我認爲這對你正在嘗試做的事情有點矯枉過正。避免這種編程風格的另一個原因是它不會很好地與%>%一起玩。

  2. 如果我正確地讀取了您的代碼,您正試圖重新編碼與名稱中的特定模式匹配的數據框中的列。您已要求提供矢量化解決方案,並且dplyr有設施可以幫助解決這個問題。 dplyr::mutate_at()將是不錯的選擇。有一個dplyr::recode(),但它需要你詳盡地指定所有的情況,並對類型非常挑剔。例如,這是我能來與dplyr::recode()捕捉你的意圖最接近:

    library(dplyr) 
    data %>% 
        mutate_at(.funs = funs(recode(., `0` = NA_real_, 
                 `5` = NA_real_, 
                 `1` = 1, 
                 `2` = 2, 
                 `3` = 3, 
                 `4` = 4)), 
           .cols = vars(matches("x[0-9].*_v")) 
        ) 
    

    注意使用.cols = vars(matches("x[0-9].*_v")這是做列名正則表達式匹配找到x#_v的。另外,funs()裏面的.指的是'我正在操作的列'。而不是'通過管道傳遞的輸出'。

    也許ifelse()if_else()是更好的選擇。 ifelse()(更慢和更小型安全的):

    data %>% 
        mutate_at(.funs = funs(ifelse(. == 0| . == 5, 
                yes = NA, 
                no = .)), 
           .cols = vars(matches("x[0-9].*_v")) 
        ) 
    

    if_else()需要的x2_vx1_v類型是相同的,它們是當前沒有。 x2_v <- rep(as.integer(5),5)會解決這個問題。然後,你可以這樣做:

    data %>% 
        mutate_at(.funs = funs(if_else(. == 0| . == 5, 
                true = NA_integer_, 
                false = .)), 
           .cols = vars(matches("x[0-9].*_v")) 
    ) 
    
相關問題