如何使用mutate按行创建变量应用函数

时间:2018-04-18 14:54:10

标签: r dplyr apply mutate

我有一个数据框,我想创建一个应用在行内工作的函数的新变量。请参阅下面的示例。

library(tidyverse)

n <- 100
z0 <- data.frame(A = sample(c("y","n",NA), n, replace = T, prob = c(.4,.4,.1)),
                 B = sample(c("y","n",NA), n, replace = T, prob = c(.4,.4,.1)),
                 C = sample(c("y","n",NA), n, replace = T, prob = c(.4,.4,.1)))

z0 %>% apply(1, function(x) any("y" == x)) -> z0$new
summary(z0)

我想用mutate做这件事,但我失败了。我很感激任何建议。

2 个答案:

答案 0 :(得分:2)

这是一个整齐的方法。让我们创建一个具有所有可能性的数据框,以确保不会遗漏任何内容。

library(tidyverse)
(z0 <- data_frame(A = c("y", "n", NA, NA, NA), 
                 B = c("n", "n", "y", "n", NA), 
                 C = c("n", "n", "n", "n", NA)))
#> # A tibble: 5 x 3
#>   A     B     C    
#>   <chr> <chr> <chr>
#> 1 y     n     n    
#> 2 n     n     n    
#> 3 <NA>  y     n    
#> 4 <NA>  n     n    
#> 5 <NA>  <NA>  <NA>

这是一种使用purrr::pmap_lgl的安全方法,要求您明确输入要包含的变量,以查看"y"可能出现的位置:

z0 %>% 
  mutate(new = pmap_lgl(., ~ any("y" == c(..1, ..2, ..3))))

这是一种使用purrrlyr(一个包含purrr孤立函数的小包的方法),它的好处是可以使用...来表示所有变量:

z0 %>% 
  purrrlyr::by_row(~ any("y" == ...), .collate = "rows", .to = "new")

两者都给出了相同的结果:

#> # tibble [5 × 4]
#>   A     B     C     new
#>   <chr> <chr> <chr> <lgl>  
#> 1 y     n     n     TRUE   
#> 2 n     n     n     FALSE  
#> 3 <NA>  y     n     TRUE   
#> 4 <NA>  n     n     NA     
#> 5 <NA>  <NA>  <NA>  NA

编辑:第一个解决方案(所谓的“安全”)不适用于因子变量(可能还有其他类)as discussed here。似乎事情被强制转换为数字,这就是为什么这个(非常愚蠢的)代码给出了期望的结果:

z0 %>% 
  mutate(new = pmap(., 
     ~ any(as.numeric(factor("y", levels = c("n", "y"))) == 
           c(..1, ..2, ..3))))

答案 1 :(得分:2)

这将适用于因子或字符列。

library(tidyverse)
z0 %>% 
  mutate(new_var = rowSums(.[c('A','B','C')] == 'y', na.rm = T) > 0)

另一种选择(我猜的更慢)是使用rowwise

z0 %>% 
  mutate_at(c('A', 'B', 'C'), as.character) %>% 
  rowwise %>% 
  mutate(newvar = any(c(A, B, C) == 'y', na.rm = T))