行方式操作,选择助手和dplyr中的mutate函数

时间:2018-01-20 06:31:38

标签: r select dplyr mutate rowwise

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

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的平均值,但仅包含NaN s。在研究了一下代码之后,我理解了第二个问题。 .函数中添加的“select()”指的是原始my_df数据框,其中没有a_2b_2列。因此,生成NaN是有道理的,因为我要求R计算不存在的值的均值。

然后我尝试使用dplyrcurrent_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()内部的事实,但是我正在展示这是否有办法列出我想要的变量必须单独指定它们。

感谢您的时间。

1 个答案:

答案 0 :(得分:2)

有点晚了,但这是问题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比较棘手,也许不可取(?)