使用dplyr的transmute_all将列值替换为列名

时间:2018-05-02 15:27:15

标签: r dplyr

数据集包含许多包含NA或1值的列,如下所示:

> data_frame(a = c(NA, 1, NA, 1, 1), b=c(1, NA, 1, 1, NA))
# A tibble: 5 x 2
      a     b
  <dbl> <dbl>
1 NA     1.00
2  1.00 NA   
3 NA     1.00
4  1.00  1.00
5  1.00 NA  

所需输出:将所有1个值替换为列名称

> data_frame(a = c(NA, 'a', NA, 'a', 'a'), b=c('b', NA, 'b', 'b', NA))
# A tibble: 5 x 2
  a     b    
  <chr> <chr>
1 <NA>  b    
2 a     <NA> 
3 <NA>  b    
4 a     b    
5 a     <NA> 

这是我在transmute_all中使用匿名函数的尝试:

> data_frame(a = c(NA, 1, NA, 1, 1), b=c(1, NA, 1, 1, NA)) %>%
+     transmute_all(
+         funs(function(x){if (x == 1) deparse(substitute(x)) else NA})
+     )
Error in mutate_impl(.data, dots) : 
  Column `a` is of unsupported type function

编辑:尝试#2:

> data_frame(a = c(NA, 1, NA, 1, 1), b=c(1, NA, 1, 1, NA)) %>%
+     transmute_all(
+         funs(
+             ((function(x){if (!is.na(x)) deparse(substitute(x)) else NA})(.))
+             )
+     )
# A tibble: 5 x 2
  a     b    
  <lgl> <chr>
1 NA    b    
2 NA    b    
3 NA    b    
4 NA    b    
5 NA    b    
Warning messages:
1: In if (!is.na(x)) deparse(substitute(x)) else NA :
  the condition has length > 1 and only the first element will be used
2: In if (!is.na(x)) deparse(substitute(x)) else NA :
  the condition has length > 1 and only the first element will be used
> 

4 个答案:

答案 0 :(得分:2)

一个选项是map2

library(purrr)
map2_df(df1, names(df1), ~  replace(.x, .x==1, .y))
# A tibble: 5 x 2
#  a     b    
# <chr> <chr>
#1 NA    b    
#2 a     NA   
#3 NA    b    
#4 a     b    
#5 a     NA   

或@Moody_Mudskipper发表评论

imap_dfr(df1, ~replace(.x, .x==1, .y))

base R,我们可以

df1[] <- names(df1)[col(df1) *(df1 == 1)]

数据

df1 <-  data_frame(a = c(NA, 1, NA, 1, 1), b=c(1, NA, 1, 1, NA))

答案 1 :(得分:2)

基础R也应该没问题:

nn <- names(df)
for (i in seq_along(df)) {
  df[i] <- ifelse(df[i] == 1, nn[i], df[i])
}

这会产生

     a    b
1 <NA>    b
2    a <NA>
3 <NA>    b
4    a    b
5    a <NA>

答案 2 :(得分:1)

如果您想坚持使用paintEvent()解决方案,那么您几乎已经拥有它了

dplyr

答案 3 :(得分:0)

由于deparse(substitute(.))将返回长度为1的字符串,因此您可以直接使用.进行子集,因为NA的子集会返回NA

library(tidyverse)

df <- data_frame(a = c(NA, 1, NA, 1, 1), 
                 b = c(1, NA, 1, 1, NA))

df %>% mutate_all(funs(deparse(substitute(.))[.]))
#> # A tibble: 5 x 2
#>   a     b    
#>   <chr> <chr>
#> 1 <NA>  b    
#> 2 a     <NA> 
#> 3 <NA>  b    
#> 4 a     b    
#> 5 a     <NA>

不涉及解析名称的方法是重新形成长形式,因此变量名称是可以照常操作的变量。这里,强制转换为逻辑向量使得子集的行为与上面相同。如果要在重新整形为宽格式时保持行顺序,则必须添加索引列。

df %>% 
    rowid_to_column('i') %>% 
    gather(variable, value, -i) %>% 
    mutate(value = variable[as.logical(value)]) %>% 
    spread(variable, value)
#> # A tibble: 5 x 3
#>       i a     b    
#>   <int> <chr> <chr>
#> 1     1 <NA>  b    
#> 2     2 a     <NA> 
#> 3     3 <NA>  b    
#> 4     4 a     b    
#> 5     5 a     <NA>