我有一些数据列,只要相应的列为> 0,我就需要设置为NA。
我可以使用mutate和两列的名称来完成此操作,但我想要一个范围版本,我从第一列的名称创建相应列的名称
(x<-data.frame(x1=(1:4),map.x1=c(0,0,7,0),x2=c(2,2,2,2),map.x2=c(0,7,0,0)))
mutate(x, x1=ifelse(map.x1>0, NA, x1))
mutate_at(x, vars(starts_with("x")), function(v) {
m.name <- paste0("map.", deparse(substitute(v)))
ifelse(get(m.name)>0, NA, v)
)
}
我可以看到ifelse()不满意,因为它希望第一个参数成为一个对象,并且我已经给出了一个表达式。
我找不到办法。我甚至想知道是否有某种方法可以避免函数(v)并在paste0()或get()中使用(。)
我也在考虑重塑,所以我可以做一个变异。这里的最佳做法是什么?
答案 0 :(得分:1)
这是获得所需输出的一种方法。无需编写自定义函数。重塑文件就足够了。
library(tibble)
library(dplyr)
library(stats)
# creating dataframe with proper names
x <-
tibble::as_data_frame(cbind(
x_1 = c(1:4),
map.x_1 = c(0, 0, 7, 0),
x_2 = c(2, 2, 2, 2),
map.x_2 = c(0, 7, 0, 0)
)) %>%
tibble::rownames_to_column(df = ., var = 'id')
# converting to long format
x_long <- stats::reshape(
as.data.frame(x),
timevar = "level",
varying = dput(as.character(as.vector(names(
x[, base::grep("^x|^map", names(x))]
)))),
direction = "long",
idvar = c("id"),
sep = "_"
)
#> c("x_1", "map.x_1", "x_2", "map.x_2")
# converting the dataframe based on condition
x_long %>%
group_by(.data = ., level) %>%
dplyr::mutate(.data = .,
x = base::ifelse(test = map.x > 0,
yes = NA,
no = x))
#> # A tibble: 8 x 4
#> # Groups: level [2]
#> id level x map.x
#> <chr> <dbl> <dbl> <dbl>
#> 1 1 1.00 1.00 0
#> 2 2 1.00 2.00 0
#> 3 3 1.00 NA 7.00
#> 4 4 1.00 4.00 0
#> 5 1 2.00 2.00 0
#> 6 2 2.00 NA 7.00
#> 7 3 2.00 2.00 0
#> 8 4 2.00 2.00 0
由reprex package创建于2018-02-14(v0.1.1.9000)。
答案 1 :(得分:1)
这是一种无需重塑数据的解决方案。
library(dplyr)
library(rlang)
custom_mutate <- function(df, v){
v <- enquo(v)
map.v <- paste0("map.", quo_name(v))
df %>%
mutate(UQE(v) := ifelse((!!sym(map.v)) > 0, NA, (!!v))) %>%
pull(UQE(v))
}
mutate_at(x, vars(starts_with("x")), funs(custom_mutate(df = x, v = .)))
# x1 map.x1 x2 map.x2
# 1 1 0 2 0
# 2 2 0 NA 7
# 3 NA 7 2 0
# 4 4 0 2 0
mutate_at
调用中的函数仅应用于列,而不应用于整个数据帧。因此,您必须明确告诉函数在哪里查找map.x1
列
要从您使用的列中获取名称,首先需要使用enquo
转换v
中的quosure
。然后,您可以使用quo_name
构建map.
- 名称。在以下mutate
调用中,您必须告诉dplyr
,v
是一个结果(因此UQE
缠绕它,这与{{1}类似在!!
- FALSE
语句的一部分前面。}
对于ifelse
列,您必须使用map.x1
- 包中的sym
- 函数来获取裸名称(不带引号),然后再次使用rlang
来说明!!
将此作为列名称。
我试图解释我的解决方案,而不是技术方面。有关如何使用dplyr进行编程的详细说明,请参见此处:Programming with dplyr