r-使用modify_depth和modify_if(purrr)基于深度和“ if”条件插入列表中



我正在学习一些purrr命令,特别是modify_*功能系列。我正在准备在杂货店中的项目中添加price箱(有关我的尝试和错误代码,请参见下文(。

library(tidyverse)

数据

easybuy <- list(
  "5520 N Division St, Spokane, WA 99208, USA",
  list("bananas", "oranges"),
  canned = list("olives", "fish", "jam"),
  list("pork", "beef"),
  list("hammer", "tape")
) %>%
  map(list) %>%
  # name the sublists
  set_names(c("address",
              "fruit",
              "canned",
              "meat",
              "other")) %>%
  # except for address, names the sublists "items"
  modify_at(c(2:5), ~ set_names(.x, "items"))

窥视:

glimpse(easybuy)
#> List of 5
#>  $ address:List of 1
#>   ..$ : chr "5520 N Division St, Spokane, WA 99208, USA"
#>  $ fruit  :List of 1
#>   ..$ items:List of 2
#>   .. ..$ : chr "bananas"
#>   .. ..$ : chr "oranges"
#>  $ canned :List of 1
#>   ..$ items:List of 3
#>   .. ..$ : chr "olives"
#>   .. ..$ : chr "fish"
#>   .. ..$ : chr "jam"
#>  $ meat   :List of 1
#>   ..$ items:List of 2
#>   .. ..$ : chr "pork"
#>   .. ..$ : chr "beef"
#>  $ other  :List of 1
#>   ..$ items:List of 2
#>   .. ..$ : chr "hammer"
#>   .. ..$ : chr "tape"

我的尝试

想法:进入两个深度,寻找"项目",附加"价格"。我不确定是否可以嵌套modify函数。

easybuy %>% 
  modify_depth(2, ~ modify_at(., "items", ~ append("price")))
#> Error: character indexing requires a named object

所需的

我想要以下结构(请注意每个项目下的"价格" (:

List of 5
 $ address:List of 1
  ..$ : chr "5520 N Division St, Spokane, WA 99208, USA"
 $ fruit  :List of 1
  ..$ items:List of 2
  .. ..$ :List of 2
  .. .. ..$ : chr "bananas"
  .. .. ..$ : chr "price"
  .. ..$ :List of 2
  .. .. ..$ : chr "oranges"
  .. .. ..$ : chr "price"
 $ canned :List of 1
  ..$ items:List of 3
  .. ..$ :List of 2
  .. .. ..$ : chr "olives"
  .. .. ..$ : chr "price"
  .. ..$ :List of 2
  .. .. ..$ : chr "fish"
  .. .. ..$ : chr "price"
  .. ..$ :List of 2
  .. .. ..$ : chr "jam"
  .. .. ..$ : chr "price"
 $ meat   :List of 1
  ..$ items:List of 2
  .. ..$ :List of 2
  .. .. ..$ : chr "pork"
  .. .. ..$ : chr "price"
  .. ..$ :List of 2
  .. .. ..$ : chr "beef"
  .. .. ..$ : chr "price"
 $ other  :List of 1
  ..$ items:List of 2
  .. ..$ :List of 2
  .. .. ..$ : chr "hammer"
  .. .. ..$ : chr "price"
  .. ..$ :List of 2
  .. .. ..$ : chr "tape"
  .. .. ..$ : chr "price"

这似乎有效。map_iffunction(x) !is.null(names(x))仅在项目的名称不是NULL时才确保更改发生。~modify_depth(.x, 2, function(y) list(y, "price"))创建您需要的列表。

library(tidyverse)
easybuy2 <- easybuy %>%
  map_if(function(x) !is.null(names(x)),
         ~modify_depth(.x, 2, function(y) list(y, "price")))

这是第二个项目的样子。

easybuy2[[2]][[1]]
# [[1]]
# [[1]][[1]]
# [1] "bananas"
# 
# [[1]][[2]]
# [1] "price"
# 
# 
# [[2]]
# [[2]][[1]]
# [1] "oranges"
# 
# [[2]][[2]]
# [1] "price"

或这也有效。

easybuy3 <- easybuy %>% 
  modify_at(2:5, ~modify_depth(.x, 2, function(y) list(y, "price")))
identical(easybuy2, easybuy3)
# [1] TRUE

update

easybuy4 <- easybuy %>%
  map_if(function(x){
    name <- names(x) 
    if(is.null(name)){
      return(FALSE)
    } else {
      return(name %in% "items")
    }
  },
~modify_depth(.x, 2, function(y) list(y, "price")))
identical(easybuy2, easybuy4)
# [1] TRUE

最新更新