【问题标题】:row-wise operations, select helpers and the mutate function in dplyrdplyr 中的逐行操作、选择助手和 mutate 函数
【发布时间】:2018-01-20 06:31:37
【问题描述】:

我将使用以下数据集来说明我的问题:

my_df <- data.frame(
    a = 1:10,
    b = 10:1
)
colnames(my_df) <- c("a", "b")

第 1 部分

我使用mutate() 函数在我的数据集中创建两个新变量,并且我想计算同一个mutate() 调用中两个新列的行均值。但是,我真的希望能够使用 select() 助手,例如 starts_with()ends_with()contains()

我的第一次尝试:

 my_df %>%
    mutate(
        a_2 = a^2,
        b_2 = b^2,
        mean = rowMeans(select(ends_with("2")))
    )
Error in mutate_impl(.data, dots) : 
  Evaluation error: No tidyselect variables were registered.

我明白为什么会出现错误 - select() 函数没有给出任何 .data 参数。所以我将代码更改为...

...我第二次尝试在select() 函数中添加“.”:

my_df %>%
    mutate(
        a_2 = a^2,
        b_2 = b^2,
        mean = rowMeans(select(., ends_with("2")))
    )
    a  b a_2 b_2 mean
1   1 10   1 100  NaN
2   2  9   4  81  NaN
3   3  8   9  64  NaN
4   4  7  16  49  NaN
5   5  6  25  36  NaN
6   6  5  36  25  NaN
7   7  4  49  16  NaN
8   8  3  64   9  NaN
9   9  2  81   4  NaN
10 10  1 100   1  NaN

第二次尝试后的新问题是mean列没有像预期的那样包含a_2b_2的均值,而只包含NaNs。在研究了一下代码之后,我理解了第二个问题。 select()函数中添加的“.”指的是原始的my_df数据框,它没有a_2b_2列。所以产生NaNs 是有道理的,因为我要求R 计算不存在值的均值。

然后我尝试使用dplyr 函数,例如current_vars(),看看它是否会有所作为:

 my_df %>%
    mutate(
        a_2 = a^2,
        b_2 = b^2,
        mean = rowMeans(select(current_vars(), ends_with("2")))
    )
Error in mutate_impl(.data, dots) : 
  Evaluation error: Variable context not set.

但是,这显然不是使用此功能的方式。解决方案是简单地添加第二个mutate() 函数:

 my_df %>%
    mutate(
        a_2 = a^2,
        b_2 = b^2
    ) %>%
    mutate(mean = rowMeans(select(., ends_with("2"))))
    a  b a_2 b_2 mean
1   1 10   1 100 50.5
2   2  9   4  81 42.5
3   3  8   9  64 36.5
4   4  7  16  49 32.5
5   5  6  25  36 30.5
6   6  5  36  25 30.5
7   7  4  49  16 32.5
8   8  3  64   9 36.5
9   9  2  81   4 42.5
10 10  1 100   1 50.5

问题 1:有没有办法在同一个 mutate() 调用中执行此任务?无论如何,使用第二个mutate() 函数并不是真正的问题。但是,我很想知道是否存在引用当前存在变量的方法。 mutate() 函数允许在同一 mutate() 调用中创建变量后立即使用它们;但是,当函数嵌套时,这会成为问题,如我上面的示例所示。

第 2 部分

我也意识到在我的解决方案中使用rowMeans() 有效;但是,这并不是真正的 dplyr- 做事方式,尤其是因为我需要在其中使用 select()。所以,我决定改用rowwise()mean() 函数。但再一次,我想为此使用select() 助手之一,而不必在c() 函数中列出所有变量。我试过了:

 my_df %>%
    mutate(
        a_2 = a^2,
        b_2 = b^2
    ) %>%
    rowwise() %>%
    mutate(
        mean = mean(ends_with("2"))
    )
Error in mutate_impl(.data, dots) : 
  Evaluation error: No tidyselect variables were registered.

我怀疑代码中的错误是由于ends_with() 不在select() 内,但我展示这个是为了询问是否有一种方法可以列出我想要的变量而不必指定它们个人。

感谢您的宝贵时间。

【问题讨论】:

  • 您在#2 中的问题让我感到困惑。 my_df %&gt;% mutate(a_2 = a^2, b_2 = b^2) %&gt;% rowwise()%&gt;% select(. , ends_with("2")) 是您要在其上运行 means() 的对象,但这永远不会起作用,因为 rowMeans() 被设计为水平工作,而 means() 不是。
  • @InfiniteFlashChess “对于#1,我在引用”是什么意思?另外,关于问题#2,means() 函数属于哪个包?是的,我在问题中指定我正在尝试计算水平平均值。这就是为什么我在第一部分使用rowMeans(),在第二部分使用rowwise()mean() 的组合。
  • 好吧,关键是函数mean() 不会按照您想要的方式运行。我在“引用 #1”,因为它似乎值得赏金。很可能,我们需要哈德利(或这里非常精通的人)来回答它:)
  • @InfiniteFlashChess 我明白这一点。均值函数的输入是一个数值向量。其实rowwise()mean()组合起来是可以的;但是,您需要在 c() 函数中手动指定列名。我只是想知道是否有一种方法可以使用其中一个选择助手来执行相同的任务。
  • SavedByJESUS,肯定会考虑赏金问题 #1 并有人尝试回答它(我也有兴趣正确执行 #1!)

标签: r select dplyr rowwise


【解决方案1】:

有点晚了,不过这里有一个问题1的解决方案,供参考。

如果你必须在没有管道的情况下这样做,你会写:

tmp1 = mutate(my_df, a_2 = a^2, b_2 = b^2)
tmp2 = select(tmp1, ends_with("2"))
tmp3 = rowMeans(tmp2)
tmp4 = mutate(tmp1, m=tmp3)

或者,使用更少的中间步骤:

tmp1 = mutate(my_df, a_2 = a^2, b_2 = b^2)
tmp4 = mutate(tmp1, m=rowMeans(select(tmp1, ends_with("2"))) )

请注意,计算tmp4 需要使用tmp1 两次。因此,在管道版本中,您还需要第二次显式引用 .(像往常一样,第一个引用是隐式的,作为 mutate 的第一个参数):

my_df %>%
  mutate(a_2 = a^2, b_2 = b^2) %>%
  mutate(mean = rowMeans(select(., ends_with("2"))) )

对于问题 #2:避免调用 rowMeans 比较棘手,而且可能不理想 (?)

【讨论】:

    【解决方案2】:

    幸运的是,由于 dplyr > 1.0.0,有一种 dplyr 方式可以通过使用 c_across 来完全满足您的需求。这很有帮助,因为它将解决方案扩展到可能具有 Row 实现的其他函数,例如 RowMeans()。

    试试这个:

    my_df %>%
      mutate(
        a_2 = a^2,
        b_2 = b^2,
        ) %>% 
      rowwise() %>% 
      mutate( mean = mean(c_across(ends_with("2"))) )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-21
      • 1970-01-01
      相关资源
      最近更新 更多