仅使用 tidy 有条件地将行子集的值替换为 R 中的列名

  • 本文关键字:替换 子集 tidy 有条件 r dplyr
  • 更新时间 :
  • 英文 :


我正在寻找一种方法来有条件地替换列子集中的某些值,该列名称保留在整洁中。 请参阅以下示例:

wl <- data_frame(x=1:4,
multi=c("Y","Y","Y","Y"),
ABC=c("","Y","Y",""), 
ABD=c("","","",""),
ABE=c("Y","Y","","Y"))
# A tibble: 4 x 5
x multi ABC   ABD   ABE  
<int> <chr> <chr> <chr> <chr>
1     1 Y     ""    ""    Y    
2     2 Y     Y     ""    Y    
3     3 Y     Y     ""    ""   
4     4 Y     ""    ""    Y   
df <- wl %>% mutate_at(vars(matches("AB")),
funs(replace(.,.=='Y',values="column name")))
# A tibble: 4 x 5
x multi ABC         ABD   ABE        
<int> <chr> <chr>       <chr> <chr>      
1     1 Y     ""          ""    column name
2     2 Y     column name ""    column name
3     3 Y     column name ""    ""         
4     4 Y     ""          ""    column name

除了它是实际的列名而不是"列名"。 我在这里使用了两个不同的答案来获得条件列的突变(这就是我得到我的示例的方式(以及如何用列名称替换某些值(在我当前的例子中未使用,但答案在这里(。

我可以结合这两个答案来让它工作:

w <- which(df=="column name",arr.ind=TRUE)
df[w] <- names(df)[w[,"col"]]                 
# A tibble: 4 x 5
x multi ABC   ABD   ABE  
<int> <chr> <chr> <chr> <chr>
1     1 Y     ""    ""    ABE  
2     2 Y     ABC   ""    ABE  
3     3 Y     ABC   ""    ""   
4     4 Y     ""    ""    ABE 

我承认上面的过程是完全有效的,但纯粹出于好奇,有没有办法在没有第二块代码的情况下做到这一点? 是否有一些函数可以插入replace(.,.=='Y',values="column name")步骤的values=部分,可以捕获列名并在单个mutate_at函数中执行整个过程?

你可以在mutate_at函数中做一点tidyeval来获取列名,然后用一个ifelse(或你可能想要的任何其他逻辑结构(来替换某些值。

library(tidyverse)
wl %>%
mutate_at(vars(starts_with("AB")), function(x) {
x_var <- rlang::enquo(x)
ifelse(x == "Y", rlang::quo_name(x_var), x)
})
#> # A tibble: 4 x 5
#>       x multi ABC   ABD   ABE  
#>   <int> <chr> <chr> <chr> <chr>
#> 1     1 Y     ""    ""    ABE  
#> 2     2 Y     ABC   ""    ABE  
#> 3     3 Y     ABC   ""    ""   
#> 4     4 Y     ""    ""    ABE

创建于 2018-08-16 由 reprex 包 (v0.2.0(.

您可以使用replace_na

wl%>%
mutate_at(vars(starts_with('AB')),~`is.na<-`(.x,.x=='Y'))%>%
replace_na(set_names(as.list(names(.)),names(.)))
# A tibble: 4 x 5
x     multi ABC   ABD   ABE  
<chr> <chr> <chr> <chr> <chr>
1 1     Y     ""    ""    ABE  
2 2     Y     ABC   ""    ABE  
3 3     Y     ABC   ""    ""   
4 4     Y     ""    ""    ABE  

这是一个带有imap的选项

library(purrr)
AB_cols <- grep("^AB", names(wl)) # find positions of columns that start with "AB"
wl[AB_cols] <- imap(.x = wl[AB_cols], .f = ~replace(.x, .x == "Y", .y))
wl
# A tibble: 4 x 5
#      x multi ABC   ABD   ABE  
#  <int> <chr> <chr> <chr> <chr>
#1     1 Y     ""    ""    ABE  
#2     2 Y     ABC   ""    ABE  
#3     3 Y     ABC   ""    ""   
#4     4 Y     ""    ""    ABE 

withtidy verse

library(dplyr)
wl %>% 
mutate_at(vars(starts_with("AB")),
funs(c("", deparse(substitute(.)))[(.=="Y" & !is.na(.)) + 1]))
# A tibble: 4 x 5
#     x multi ABC   ABD   ABE  
#  <int> <chr> <chr> <chr> <chr>
#1     1 Y     ""    ""    ABE  
#2     2 Y     ABC   ""    ABE  
#3     3 Y     ABC   ""    ""   
#4     4 Y     ""    ""    ABE  

使用base R

nm1 <- grep("^AB", names(wl))
i1 <- wl[,(nm1)] == "Y" & !is.na(wl[,(nm1)])
wl[,(nm1)][i1] <- names(wl)[(nm1)][col(wl[,(nm1)])][i1]
wl
# A tibble: 4 x 5
#      x multi ABC   ABD   ABE  
#  <int> <chr> <chr> <chr> <chr>
#1     1 Y     ""    ""    ABE  
#2     2 Y     ABC   ""    ABE  
#3     3 Y     ABC   ""    ""   
#4     4 Y     ""    ""    ABE  

或者,我们可以通过使用data.tableset就地分配来更快地做到这一点

library(data.table)
setDT(wl)
for(j in nm1) set(wl, i=which(wl[[j]] == "Y"), j=j, names(wl)[j])
wl
#   x multi ABC ABD ABE
#1: 1     Y         ABE
#2: 2     Y ABC     ABE
#3: 3     Y ABC        
#4: 4     Y         ABE

最新更新