【问题标题】:How to use across and mutate across an entire dataset that has multiple column types?如何跨具有多种列类型的整个数据集使用和变异?
【发布时间】:2021-08-17 17:53:03
【问题描述】:

我正在尝试在我的整个数据集上使用 dplyr 的 cross 和 case_when,所以每当它看到“强烈同意”时,它会将其更改为数字 5,“同意”到数字 4,依此类推。我试过查看这个answer,但我收到了一个错误,因为我的数据集有逻辑列和数字列,并且 R 正确地说“同意”不能在逻辑列中,等等。

这是我的数据:

library(dplyr)
test <- tibble(name = c("Justin", "Corey", "Sibley"),
               date = c("2021-08-09", "2021-10-29", "2021-01-01"),
               s1 = c("Agree", "Neutral", "Strongly Disagree"),
               s2rl = c("Agree", "Neutral", "Strongly Disagree"),
               f1 = c("Strongly Agree", "Disagree", "Strongly Disagree"),
               f2rl = c("Strongly Agree", "Disagree", "Strongly Disagree"),
               exam = c(90, 99, 100),
               early = c(TRUE, FALSE, FALSE))

理想情况下,我想要一个可以让我遍历整个数据集的命令。但是,如果不能这样做,我希望有一个参数允许我使用多个 cross(contains()) 参数(即,这里包含“s”或“f”)。

这是我已经尝试过但无济于事的方法:

library(dplyr)
test %>%
  mutate(across(.), 
         ~ case_when(. == "Strongly Agree" ~ 5, 
                     . == "Agree" ~ 4,
                     . == "Neutral" ~ 3,
                     . == "Disagree" ~ 2,
                     . == "Strongly Disagree" ~ 1,
                     TRUE ~ NA))

Error: Problem with `mutate()` input `..1`.
x Must subset columns with a valid subscript vector.
x Subscript has the wrong type `tbl_df<
  name: character
  date: character
  s1  : character
  s2rl: character
  f1  : character
  f2rl: character
  exam: double
>`.
ℹ It must be numeric or character.
ℹ Input `..1` is `across(.)`.

【问题讨论】:

    标签: r dplyr across


    【解决方案1】:

    我们可以使用matches 来传递正则表达式

    library(dplyr)
    test %>% 
        mutate(across(matches('^(s|f)'), ~ case_when(. == "Strongly Agree" ~ 5, 
                         . == "Agree" ~ 4,
                         . == "Neutral" ~ 3,
                         . == "Disagree" ~ 2,
                         . == "Strongly Disagree" ~ 1,
                         TRUE ~ NA_real_)))
    

    -输出

    # A tibble: 3 x 8
      name   date          s1  s2rl    f1  f2rl  exam early
      <chr>  <chr>      <dbl> <dbl> <dbl> <dbl> <dbl> <lgl>
    1 Justin 2021-08-09     4     4     5     5    90 TRUE 
    2 Corey  2021-10-29     3     3     2     2    99 FALSE
    3 Sibley 2021-01-01     1     1     1     1   100 FALSE
    

    根据?across

    across() 可以轻松地将相同的转换应用于多个列,允许您在 summarise() 和 mutate() 等“数据屏蔽”函数中使用 select() 语义。

    如果我们检查?select,它会返回用于选择列的各种select-helpers,这些列也可以在across 中使用

    Tidyverse 选择实现了 R 的方言,其中运算符可以轻松选择变量:

    :用于选择一系列连续变量。

    !用于取一组变量的补码。

    & 和 |用于选择两组变量的交集或并集。

    c() 用于组合选择。

    此外,您还可以使用选择助手。一些助手选择特定的列:

    everything():匹配所有变量。

    last_col():选择最后一个变量,可能带有偏移量。

    这些助手通过匹配名称中的模式来选择变量:

    starts_with():以前缀开头。

    ends_with():以后缀结尾。

    contains():包含一个文字字符串。

    matches():匹配正则表达式。

    num_range():匹配 x01、x02、x03 等数值范围。

    这些助手从字符向量中选择变量:

    all_of():匹配字符向量中的变量名。所有名称都必须存在,否则会引发越界错误。

    any_of():与 all_of() 相同,但不存在不存在的名称时不会引发错误。

    此助手使用函数选择变量:

    where():将函数应用于所有变量并选择函数返回 TRUE 的变量。

    【讨论】:

    • 谢谢!出于好奇,为什么“匹配”有效但 cross(.) 无效。是因为您忽略了那些不相关的列而不是绊倒 R 吗?只是想确保我对未来有所了解。
    • @J.Sabree 您是在寻找解决方案还是尝试让across(.) 工作,这是错误的
    • 不,我已经接受了你的回答——我只是好奇为什么 cross(.) 是错误的。
    • @J.Sabree 我更新了答案。这个想法是传递一些输入,以便它选择某些列或所有列。使用 select-helpers 或列名作为字符串或不带引号等,如更新
    【解决方案2】:

    我们也可以这样做。 首先使用字符 5 作为 "5" 等等...... 在这种情况下,我们必须使用NA_character_,这是字符类型的 NA 最后使用type.convert(as.is = TRUE) 获取整数:

    library(dplyr)
    test %>%
        mutate(across(s1:f2rl, 
               ~ case_when(. == "Strongly Agree" ~ "5", 
                           . == "Agree" ~ "4",
                           . == "Neutral" ~ "3",
                           . == "Disagree" ~ "2",
                           . == "Strongly Disagree" ~ "1",
                           TRUE ~ NA_character_ ))) %>% 
        type.convert(as.is = TRUE)
    
    # A tibble: 3 x 8
      name   date          s1  s2rl    f1  f2rl  exam early
      <chr>  <chr>      <int> <int> <int> <int> <int> <lgl>
    1 Justin 2021-08-09     4     4     5     5    90 TRUE 
    2 Corey  2021-10-29     3     3     2     2    99 FALSE
    3 Sibley 2021-01-01     1     1     1     1   100 FALSE
    

    【讨论】:

      猜你喜欢
      • 2021-01-17
      • 2021-12-27
      • 1970-01-01
      • 2020-02-07
      • 2015-10-26
      • 2016-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多