4

我有两组变量,例如 variablea和 variable a_avail。我正在尝试根据 的值更改 的a值,a_avail并且想知道这是否可以使用acrosswith来完成glue

这是我尝试过的。没有产生错误,但胶水似乎没有拾取 的值,.x_avail因为所有返回的值都是 NA:

library(tidyverse)

df <- tibble(a = c(0, 1, 0, 0, 0),
       a_avail = c(1, 1, 1, 0, 0),
       b = c(1, 1, 1, 0, 0),
       b_avail = c(1, 0, 0, 1, 0))

df2 <- df %>% 
  mutate(across(.cols = c(a, b),
                .fns = ~case_when(
                  glue::glue("{.x}_avail") == 1 ~ .x,
                  glue::glue("{.x}_avail") == 0 ~ as.numeric(NA)
                ),
                .names = "{.col}_new"))

df2
#> # A tibble: 5 x 6
#>       a a_avail     b b_avail a_new b_new
#>   <dbl>   <dbl> <dbl>   <dbl> <dbl> <dbl>
#> 1     0       1     1       1    NA    NA
#> 2     1       1     1       0    NA    NA
#> 3     0       1     1       0    NA    NA
#> 4     0       0     0       1    NA    NA
#> 5     0       0     0       0    NA    NA

reprex 包(v0.3.0)于 2021-02-12 创建

4

4 回答 4

2

不是一个 tidyverse 解决方案,但这应该可以

library(tidyverse)

df <- tibble(a = c(0, 1, 0, 0, 0),
             a_avail = c(1, 1, 1, 0, 0),
             b = c(1, 1, 1, 0, 0),
             b_avail = c(1, 0, 0, 1, 0))


v1 <- list('a','b')
v2 <- list('a_avail','b_avail')


v3 <- as.data.frame(mapply(function(x,y){ifelse(df[[y]] == 0, NA,df[[x]])} , v1,v2, 
                           SIMPLIFY = TRUE))

names(v3) <- paste0(v1,"_new")

df3 <- cbind(df, v3)
于 2021-02-12T16:03:40.893 回答
2

您遇到的主要问题是引用列本身,而不仅仅是将字符串(或glue对象)与数字进行比较。您可能可以将一个 tidyeval 函数放在一起,但(可能)更简单的方法是将数据重塑为长格式,以便为原始值提供一列和可用性列,在新列中添加比较,然后重新调整. 这也将扩展,因此您不必指定要执行此操作的所有列,或手动将原件与可用的准确匹配。

第一个技巧是用某种方式标记原始列,这样你就可以"a""avail". 为此,将另一个字符串附加到只有单个字符的名称上。(您可以使用不同的方法来选择列。)使用 ID 标记行 - 您可以稍后删除此列。第二个技巧是利用".value"枢轴函数中的特殊术语。

我建议逐步完成重塑步骤,看看它们是如何工作的,并根据需要进行调整。

library(dplyr)
library(tidyr)
df %>%
  rename_with(~paste(., "orig", sep = "_"), matches("^[a-z]$")) %>%
  tibble::rowid_to_column() %>%
  pivot_longer(-rowid, names_to = c("col", ".value"), names_sep = "_") %>%
  mutate(new = if_else(avail == 1, orig, NA_real_)) %>%
  pivot_wider(id_cols = rowid, names_from = col, values_from = orig:new, 
              names_glue = "{col}_{.value}")
#> # A tibble: 5 x 7
#>   rowid a_orig b_orig a_avail b_avail a_new b_new
#>   <int>  <dbl>  <dbl>   <dbl>   <dbl> <dbl> <dbl>
#> 1     1      0      1       1       1     0     1
#> 2     2      1      1       1       0     1    NA
#> 3     3      0      1       1       0     0    NA
#> 4     4      0      0       0       1    NA     0
#> 5     5      0      0       0       0    NA    NA
于 2021-04-07T18:21:48.433 回答
2

我认为你想要的输出可以通过 package.json 轻松实现purrr。在某种程度上,across我们不使用map2函数,因为我们同时处理 2 个变量,并且为了我们的目的,我们希望逐行迭代它们:

library(dplyr)
library(purrr)

df <- tibble(a = c(0, 1, 0, 0, 0),
             a_avail = c(1, 1, 1, 0, 0),
             b = c(1, 1, 1, 0, 0),
             b_avail = c(1, 0, 0, 1, 0))


df %>%
  mutate(a_new = map2_dbl(a, a_avail, ~ ifelse(.y == 1, .x, NA)),
         b_new = map2_dbl(b, b_avail, ~ ifelse(.y == 1, .x, NA)))


# A tibble: 5 x 6
      a a_avail     b b_avail a_new b_new
  <dbl>   <dbl> <dbl>   <dbl> <dbl> <dbl>
1     0       1     1       1     0     1
2     1       1     1       0     1    NA
3     0       1     1       0     0    NA
4     0       0     0       1    NA     0
5     0       0     0       0    NA    NA

在这种情况下,最好仔细考虑哪种函数最能满足您的目的,并且最符合您给出的参数集,您想用它们做什么。在这里,因为我们正在处理逐行操作,所以我更喜欢使用purrr包函数。

于 2021-04-07T23:05:39.777 回答
2

Ronak Shah 在对相关问题的回答中提出了一种绝妙的方法,我将在下面进行复制。

其实两件事

  • 在里面mutate(across..使用列/变量名而不是值cur_column()应该被用作反对.or .x
  • get()也可以与 with 一起使用glue,以便 R 将其识别为变量。

做这个

df %>% 
  mutate(across(.cols = c(a, b),
                .fns = ~case_when(
                  get(glue::glue("{cur_column()}_avail")) == 1 ~ .x,
                  get(glue::glue("{cur_column()}_avail")) == 0 ~ NA_real_
                ),
                .names = "{.col}_new"))

# A tibble: 5 x 6
      a a_avail     b b_avail a_new b_new
  <dbl>   <dbl> <dbl>   <dbl> <dbl> <dbl>
1     0       1     1       1     0     1
2     1       1     1       0     1    NA
3     0       1     1       0     0    NA
4     0       0     0       1    NA     0
5     0       0     0       0    NA    NA
于 2021-04-09T06:45:47.997 回答