R-如何使用map()到map()

时间:2018-08-20 15:00:49

标签: r dplyr purrr

我需要访问另一个nest()函数内部的nest()函数中的小表。

x <- list( factory = c('a','b','c','d'), cost = c(21,30,44,100))
x <- as.data.frame(x)
x <-  x %>%
        melt('cost','factory')
colnames(x) <- c('cost','client','type')
x <- x %>%
  group_by(client)%>%
  nest()

for (m in 1:4) {
  if(m==1){
    x$scene <- m
    x2 <- x
  }else{
    x3 <- x
    x3$scene <- m
    x2 <- rbind(x2,x3)
  }
}
x2 <- x2 %>%
  group_by(scene) %>%
  nest()

我想做的是在第一个向量内部应用一个函数,例如:

test <- function(df){
  df$data %>%
  mutate(increa = cost + 15)
}

x2$data%>%
  map(test)

dput(x2)结果a:

  

结构(列表(场景= 1:4,数据=列表(结构(列表(客户=   structure(1L,.Label =“ factory”,class =“ factor”),       数据=列表(结构(列表(成本= c(21,30,44,100),type = c(“ a”,       “ b”,“ c”,“ d”)),row.names = c(NA,-4L),class = c(“ tbl_df”,       “ tbl”,“ data.frame”))))),row.names = c(NA,-1L),class = c(“ tbl_df”,“ tbl”,“ data.frame”))),结构(list(客户=   structure(1L,.Label =“ factory”,class =“ factor”),       数据=列表(结构(列表(成本= c(21,30,44,100),type = c(“ a”,       “ b”,“ c”,“ d”)),row.names = c(NA,-4L),class = c(“ tbl_df”,       “ tbl”,“ data.frame”))))),row.names = c(NA,-1L),class = c(“ tbl_df”,“ tbl”,“ data.frame”))),结构(list(客户=   structure(1L,.Label =“ factory”,class =“ factor”),       数据=列表(结构(列表(成本= c(21,30,44,100),type = c(“ a”,       “ b”,“ c”,“ d”)),row.names = c(NA,-4L),class = c(“ tbl_df”,       “ tbl”,“ data.frame”))))),row.names = c(NA,-1L),class = c(“ tbl_df”,“ tbl”,“ data.frame”))),结构(list(客户=   structure(1L,.Label =“ factory”,class =“ factor”),       数据=列表(结构(列表(成本= c(21,30,44,100),type = c(“ a”,       “ b”,“ c”,“ d”)),row.names = c(NA,-4L),class = c(“ tbl_df”,       “ tbl”,“ data.frame”))))),row.names = c(NA,-1L),class = c(“ tbl_df”,“ tbl”,“ data.frame”))))))),行。名称= c(NA,-4L),类=   c(“ tbl_df”,“ tbl”,“ data.frame”))

预期结果:

[[1]]
[[1]]$`factory`
[1] "a" "b" "c" "d"

[[1]]$cost
[1]  21  30  44 100

[[1]]$increa
[1]  36  45  59 115


[[2]]
[[2]]$`factory`
[1] "a" "b" "c" "d"

[[2]]$cost
[1]  21  30  44 100

[[2]]$increa
[1]  36  45  59 115


[[3]]
[[3]]$`factory`
[1] "a" "b" "c" "d"

[[3]]$cost
[1]  21  30  44 100

[[3]]$increa
[1]  36  45  59 115


[[4]]
[[4]]$`factory`
[1] "a" "b" "c" "d"

[[4]]$cost
[1]  21  30  44 100

[[4]]$increa
[1]  36  45  59 115

有人可以帮助我解决这个问题吗?

答案

这是我一直在寻找的结果:

map(x2$data, function(df) map(df$data, function(df) df <- mutate(df,increa = cost + 15)))

2 个答案:

答案 0 :(得分:0)

要获得所需的输出,我认为首先提取要具有的信息级别然后计算新列会比较容易。另一方面,如果您要操纵此结构中的数据并保留它,则mapmutate的嵌套调用是必需的-

library(tidyverse)

第一个解决方案-提取信息,然后计算新列:
我们可以使用

达到所需的信息水平
map(x2$data, ~ .x$data) 

# [[1]]
# [[1]][[1]]
# # A tibble: 4 x 2
#    cost type 
#   <dbl> <chr>
# 1    21 a    
# 2    30 b    
# 3    44 c    
# 4   100 d    
# 
# 
# [[2]]
# [[2]][[1]]
# # A tibble: 4 x 2
#    cost type 
#   <dbl> <chr>
# 1    21 a    
# 2    30 b    
# 3    44 c    
# 4   100 d    
#
# ...

由于这是一个嵌套列表结构,因此需要第二个map来计算新列。在这里,mutate函数将使用附加的规范应用于每个嵌套数据条目,以创建新的列inc。

map(x2$data, ~ map(.x$data, mutate, inc = cost + 15)) 

# [[1]]
# [[1]][[1]]
# # A tibble: 4 x 3
#    cost type    inc
#   <dbl> <chr> <dbl>
# 1    21 a        36
# 2    30 b        45
# 3    44 c        59
# 4   100 d       115
# 
# 
# [[2]]
# [[2]][[1]]
# # A tibble: 4 x 3
#    cost type    inc
#   <dbl> <chr> <dbl>
# 1    21 a        36
# 2    30 b        45
# 3    44 c        59
# 4   100 d       115
#
# ...

使用额外的功能test(使用data.frame作为输入参数并计算新列)将获得相同的结果:

test <- function(df){
    mutate(df, increa = cost + 15)
}

map(x2$data, ~ map(.x$data, test)) 

第二个解决方案-就地操作
但是,如果您想保留此嵌套结构,则可以在第一个mutate列中使用data,再使用mapmutate来使用map

x2_new <- x2 %>% 
  mutate(data = map(data, function(df1) mutate(df1, data = map(data, test))))

为验证此方法是否有效,我们再次如上所述提取所需的信息:

map(x2_new$data, ~ .x$data) 


# [[1]]
# [[1]][[1]]
# # A tibble: 4 x 3
#    cost type  increa
#   <dbl> <chr>  <dbl>
# 1    21 a         36
# 2    30 b         45
# 3    44 c         59
# 4   100 d        115
# 
# 
# [[2]]
# [[2]][[1]]
# # A tibble: 4 x 3
#    cost type  increa
#   <dbl> <chr>  <dbl>
# 1    21 a         36
# 2    30 b         45
# 3    44 c         59
# 4   100 d        115
#
# ...

第三种解决方案-破坏结构但保留信息
这是我最喜欢的解决方案,因为它将数据转换为整齐的格式并保留所有信息:

x2 %>% 
  unnest(data) %>% 
  unnest(data) %>% 
  mutate(inc = cost + 15)

# A tibble: 16 x 5
#    scene client   cost type    inc
#    <int> <fct>   <dbl> <chr> <dbl>
#  1     1 factory    21 a        36
#  2     1 factory    30 b        45
#  3     1 factory    44 c        59
#  4     1 factory   100 d       115
#  5     2 factory    21 a        36
#  6     2 factory    30 b        45
#  7     2 factory    44 c        59
#  8     2 factory   100 d       115
#  9     3 factory    21 a        36
# 10     3 factory    30 b        45
# 11     3 factory    44 c        59
# 12     3 factory   100 d       115
# 13     4 factory    21 a        36
# 14     4 factory    30 b        45
# 15     4 factory    44 c        59
# 16     4 factory   100 d       115

数据

generic_data <- structure(
  list(client = structure(1L, .Label = "factory", class = "factor"), 
       data = list(structure(list(cost = c(21, 30, 44, 100), 
                                  type = c("a", "b", "c", "d")), 
                             row.names = c(NA, -4L), 
                             class = c("tbl_df", "tbl", "data.frame")))), 
  row.names = c(NA, -1L), class = c("tbl_df", "tbl", "data.frame"))

x2 <- structure(
  list(scene = 1:4, 
       data = list(generic_data, generic_data, generic_data, generic_data)), 
  row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"))

答案 1 :(得分:0)

根据您的描述,我认为您正在寻找map_depth

从文档https://purrr.tidyverse.org/reference/map_if.html

map_depth(x,2,fun)等效于x <-map(x,〜map(。,fun))

看起来像是您确定的答案/解决方案。