我正在寻找一种方法来有条件地替换列子集中的某些值,该列名称保留在整洁中。 请参阅以下示例:
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.table
set
就地分配来更快地做到这一点
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