R:purrr:使用pmap进行行操作,但这次涉及很多列

R:purrr:使用pmap进行行操作,但这次涉及很多列,r,parameter-passing,rows,purrr,pmap,R,Parameter Passing,Rows,Purrr,Pmap,这不是重复的问题,例如 我了解如何使用pmap在数据帧上执行行操作: library(tidyverse) df1 = tribble(~col_1, ~col_2, ~col_3, 1, 5, 12, 9, 3, 3, 6, 10, 7) foo = function(col_1, col_2, col_3) { mean(c(col_1,

这不是重复的问题,例如

我了解如何使用pmap在数据帧上执行行操作:

library(tidyverse)

df1 = tribble(~col_1, ~col_2, ~col_3,
               1,      5,      12,
               9,      3,      3,
               6,     10,     7)

foo = function(col_1, col_2, col_3) {
  mean(c(col_1, col_2, col_3))
}

df1 %>% pmap_dbl(foo)
这使函数foo应用于每一行:

[1] 6.000000 5.000000 7.666667
但是,当我有超过几个列时,这会变得非常笨拙,因为我必须显式地将它们全部传入。如果我在我的数据帧df2中有8列,我想应用一个功能条,它可能涉及到每一列,会怎么样

set.seed(12345)
df2 = rnorm(n=24) %>% matrix(nrow=3) %>% as_tibble() %>%
  setNames(c("col_1", "col_2", "col_3", "col_4", "col_5", "col_6", "col_7", "col_8"))

bar = function(col_1, col_2, col_3, col_4, col_5, col_6, col_7, col_8) {
  # imagine we do some complicated row-wise operation here
  mean(c(col_1, col_2, col_3, col_4, col_5, col_6, col_7, col_8))
}

df2 %>% pmap_dbl(bar)
给出:

[1]  0.45085420  0.02639697 -0.28121651
[1]  0.45085420  0.02639697 -0.28121651

这显然是不够的——我必须为每一列添加一个新的参数。这需要大量的输入,而且会使代码可读性降低,更加脆弱。似乎应该有一种方法让它接受一个参数x,然后通过x$colu_1等访问我想要的变量,或者无论如何比上面更优雅的东西。有没有任何方法可以使用purrr清理此代码?

我所能想到的最简单但可能不是最安全的方法是利用。。。参数,以获取任意数量的列

图书馆管理员 第12345集 df2%matrixnrow=3%>%as_tible%>% 集合名称集合1、集合2、集合3、集合4、集合5、集合6、集合7、集合8 >警告:`as_tible.matrix`需要具有列名或`name_repair`参数的矩阵。使用兼容性“.name\u repair”。 >此警告在每个会话中显示一次。 杆%pmap\u dblbar > [1] 0.45085420 0.02639697 -0.28121651
由v0.3.0于2019-08-05创建,我能想到的最简单但可能不是最安全的方法是利用。。。参数,以获取任意数量的列

图书馆管理员 第12345集 %nRas%nRow%2% 集合名称集合1、集合2、集合3、集合4、集合5、集合6、集合7、集合8 >警告:`as_tible.matrix`需要具有列名或`name_repair`参数的矩阵。使用兼容性“.name\u repair”。 >此警告在每个会话中显示一次。 杆%pmap\u dblbar > [1] 0.45085420 0.02639697 -0.28121651 由v0.3.0于2019-08-05创建,您可以使用。。。一旦它们出现在你的函数中,就列出它们

dot_tester <- function(...) {
  dots <- list(...)
  dots$Sepal.Length + dots$Petal.Width
}

purrr::pmap(head(iris), dot_tester)
但是,这并不会改变代码的脆弱性,因为您仍然需要显式地、准确地匹配列名作为函数中的名称。奖金是不必在中列出它们,您可以使用。。。一旦它们出现在你的函数中,就列出它们

dot_tester <- function(...) {
  dots <- list(...)
  dots$Sepal.Length + dots$Petal.Width
}

purrr::pmap(head(iris), dot_tester)

但是,这并不会改变代码的脆弱性,因为您仍然需要显式地、准确地匹配列名作为函数中的名称。好处是不必在@Brian的答案中列出它们,但我还发现了另一种使用purr::transpose的方法,它允许我使用单个命名变量x而不是…,并且可以按名称访问任何列:

foo = function(x) {
  (x$col_1 + x$col_2 + x$col_3)/3
}

df1 %>% transpose() %>% map_dbl(foo)
这给出了正确的答案:

[1] 6.000000 5.000000 7.666667
对于另一个数据帧:

set.seed(12345)
df2 = rnorm(n=24) %>% matrix(nrow=3) %>% as_tibble() %>%
  setNames(c("col_1", "col_2", "col_3", "col_4", "col_5", "col_6", "col_7", "col_8"))

bar = function(x) {
  mean(as.double(x))
}

df2 %>% transpose() %>% map_dbl(bar)
给出:

[1]  0.45085420  0.02639697 -0.28121651
[1]  0.45085420  0.02639697 -0.28121651
但我也可以通过参考各个专栏来做到这一点:

bar_2 = function(x) {
  x$col_2 + x$col_5 / x$col_3
}

df2 %>% transpose() %>% map_dbl(bar_2)

[1]  0.1347090 -1.2776983  0.8232767

我意识到这些特殊的例子可以很容易地用mutate来完成,但对于需要真正的行式迭代的时候,我认为这已经足够好了。

@Brian的答案很有效,但我还发现了另一种使用purr::transpose的方法,它允许我使用单个命名变量x,而不是。。。,并可以按名称访问任何列:

foo = function(x) {
  (x$col_1 + x$col_2 + x$col_3)/3
}

df1 %>% transpose() %>% map_dbl(foo)
这给出了正确的答案:

[1] 6.000000 5.000000 7.666667
对于另一个数据帧:

set.seed(12345)
df2 = rnorm(n=24) %>% matrix(nrow=3) %>% as_tibble() %>%
  setNames(c("col_1", "col_2", "col_3", "col_4", "col_5", "col_6", "col_7", "col_8"))

bar = function(x) {
  mean(as.double(x))
}

df2 %>% transpose() %>% map_dbl(bar)
给出:

[1]  0.45085420  0.02639697 -0.28121651
[1]  0.45085420  0.02639697 -0.28121651
但我也可以通过参考各个专栏来做到这一点:

bar_2 = function(x) {
  x$col_2 + x$col_5 / x$col_3
}

df2 %>% transpose() %>% map_dbl(bar_2)

[1]  0.1347090 -1.2776983  0.8232767

我意识到使用mutate可以很容易地完成这些特定的例子,但是对于调用真正的行式迭代的时候,我认为这已经足够好了。

您可以添加您期望的输出吗?我发现其中一些取决于列的顺序是否与参数进入函数的顺序一致,或者您正在使用所有列或仅使用其中的一部分。对于您的简单示例,您正在使用所有列,您可以执行类似于bar2=function的操作。。。意思是…@aosmith这只是我选择的示例的一个人工制品-一般来说,我需要能够按名称引用列并以不同的方式使用它们,而不是使用。。。作为一个catchall。你能添加你想要的输出吗?我发现其中一些取决于列的顺序是否与参数进入函数的顺序一致,或者你是处理所有列还是只处理其中的一些列。对于您的简单示例,您正在使用所有列,您可以执行类似于bar2=function的操作。。。意思是…@aosmith这只是我选择的示例的一个人工制品-一般来说,我需要能够按名称引用列并以不同的方式使用它们,而不是使用。。。作为一个总括,我需要能够通过名称来引用这些列。我的实际用例并不像调用mean那么简单,这正是我为保持示例简单而选择的。我明白了。所以不允许更改杆身?杆身可以修改。。。e、 g.对col的引用_
我可能会成为x[colu_i]或其他什么。不过我需要能够按名称引用这些列。我的实际用例并不像调用mean那么简单,这正是我为保持示例简单而选择的。我明白了。所以不允许更改杆身?杆身可以修改。。。e、 g.对colu_i的引用可能会变成x[colu_i]或其他东西。