代码之家  ›  专栏  ›  技术社区  ›  geotheory

使用purr::pmap管理.f列表名称

  •  4
  • geotheory  · 技术社区  · 7 年前

    以下操作正常:

    pmap_dbl(iris, ~ ..1 + ..2 + ..3 + ..4)
    

    文件 .l 规定 A list of lists. ... List names will be used if present. 是的。这表明您应该能够使用列表名称(即列名)。然而:

    pmap_dbl(iris, ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width)
    Error in .f(Sepal.Length = .l[[c(1L, i)]], Sepal.Width = .l[[c(2L, i)]],  : 
      object 'Sepal.Length' not found
    

    如何在实践中利用列表名称?

    2 回复  |  直到 7 年前
        1
  •  7
  •   moodymudskipper    7 年前

    公式参数 ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width 传递给 purrr::as_mapper 是的。

    purrr::as_mapper(~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width)
    # function (..., .x = ..1, .y = ..2, . = ..1) 
    # Sepal.Length + Sepal.Width + Petal.Length + Petal.Width
    

    你可以看到这个函数无法直接知道这些变量是什么。

    我可以想出三种方法来解决这个问题。我将使用@zacdav的示例,因为它比您的示例更紧凑、可读性更强:

    named_list <- list(one = c(1, 1),
                       two = c(2, 2),
                       three = c(3, 3))
    

    明确定义

    您可以显式地定义这些变量,如@zacdav的答案所示—它将起作用。


    探索点论证

    有一种方法可以通过 ... 函数返回的参数 as_mapper 是的。

    当名称可用时,函数的参数将被命名,正如doc换句话说所述。

    这就解释了为什么 pmap(named_list, function(x,y,z) x+y+z) 将失败并出现错误:

    未使用的参数(1=.L[[C(1,i)]]、2=.L[[C(2,i)]]、3=.L[[C(3,i)]])

    见:

    pmap(named_list, ~names(list(...)))
    # [[1]]
    # [1] "one"   "two"   "three"
    # 
    # [[2]]
    # [1] "one"   "two"   "three"
    

    ( pmap(unname(named_list), function(x,y,z) x+y+z) 另一方面也可以)

    所以这是可行的:

    pmap(named_list, ~ with(list(...), one + two + three))
    # [[1]]
    # [1] 6
    # 
    # [[2]]
    # [1] 6 
    

    使用pryr::f

    pryr 为函数定义提供了一个简洁的快捷方式 pryr::f 以下内容:

    library(pryr)
    f(one + two + three)
    # function (one, three, two) 
    # one + two + three
    
    pmap(named_list, f(one + two + three))
    # [[1]]
    # [1] 6
    # 
    # [[2]]
    # [1] 6
    # 
    

    不过,使用时请小心,全局变量仍将显示为参数,函数将或不会包含在参数中,具体取决于它们的调用方式。例如:

    x <- 1
    test <- mean
    f(test(x) + lapply(iris,test2))
    # function (iris, test2, x) 
    # test(x) + lapply(iris, test2)
    

    所以这不是一般的方法,你应该只在简单的情况下使用。第二种方法虽然有点老生常谈,但还是通用的。

    而且 f 如果按字母顺序排列参数,则在处理命名列表时不应出现此问题,但在处理部分命名列表时请小心。

        2
  •  3
  •   zacdav    7 年前
    library(purrr)
    named_list <- list(one = c(1, 1),
                       two = c(2, 2),
                       three = c(3, 3))
    
    pmap(named_list, function(one, two, three) one + two + three)
    

    甚至在 pmap 文档:

    # Matching arguments by name
    l <- list(a = x, b = y, c = z)
    pmap(l, function(c, b, a) a / (b + c))
    

    这样做是因为它希望看到每个命名元素。

    pmap_dbl(iris, function(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species) Sepal.Length + Sepal.Width)
    

    你也可以利用 ... 看起来:

    pmap_dbl(iris, function(Sepal.Length, Sepal.Width, ...) Sepal.Length + Sepal.Width)
    

    理想情况下,此示例将仅使用 rowSums 但实际上。