2016-07-05 83 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")) 
    ) 
    
相关问题