如何将一个函数Map到R中tibble的每一行?

xam8gpfp  于 2023-02-14  发布在  其他
关注(0)|答案(4)|浏览(107)

我正在尝试将一个函数Map到tibble中的每一行。请看下面的代码。我所需的工作流程如下-
1.将包含子列表的列表转换为tibble
1.将tibble的每一行Map到函数
我想要的输出应该是一个列表,对于Map到函数的每一行都有一个tibble作为输出。

# Packages 
library(tidyverse)
library(purrr)

# Function i want to map
sample_func <- function(tib){
    
    a <- tib$name
    b <- tib$qty
    c <- tib$price
    d <- tib$add
    
    e <- b+c+d
    
    t <- tibble(e = c(e), stock = c(a))
    
    return(t)
    
}

# Define the list with multiple sublists
lst <- list(c( "CHR1", 15, 222.14, 6), c( "CHR2", 10, 119.20, 10))

# Convert each sublist to a tibble and bind the rows
tib <- bind_rows(lapply(lst, function(x) {
    tibble(name = x[1], qty = x[2] %>% as.numeric(), price = x[3] %>% as.numeric(), 
           add = x[4] %>% as.numeric())
}))

# Apply the function to each row in the tibble using map()
result <- tib %>% 
    rowwise() %>% 
    mutate(temp = map(list(name, qty, price, add), sample_func)) %>%
    unnest(temp)

我想要的结果应该是-

[[1]]
# A tibble: 1 × 2
      e name 
  <dbl> <chr>
1  243. CHR1 

[[2]]
# A tibble: 1 × 2
      e name 
  <dbl> <chr>
1  139. CHR2

然而,当最后的行Map,我得到以下错误-

Error in `mutate()`:
! Problem while computing `temp = map(list(name, qty, price, add), sample_func)`.
ℹ The error occurred in row 1.
Caused by error in `map()`:
ℹ In index: 1.
Caused by error in `tib$name`:
! $ operator is invalid for atomic vectors

我到底做错了什么?

deikduxw

deikduxw1#

另一种方法是将sample_func函数的输入更改为列名而不是tibble,然后可以使用pmap()执行此操作:

# Function i want to map
sample_func <- function(name, qty, price, add){
  
  a <- name
  b <- qty
  c <- price
  d <- add
  
  e <- b+c+d
  
  t <- tibble(e = c(e), stock = c(a))
  
  return(t)
  
}

# Define the list with multiple sublists
lst <- list(c( "CHR1", 15, 222.14, 6), c( "CHR2", 10, 119.20, 10))

# Convert each sublist to a tibble and bind the rows
tib <- bind_rows(lapply(lst, function(x) {
  tibble(name = x[1], qty = x[2] %>% as.numeric(), price = x[3] %>% as.numeric(), 
         add = x[4] %>% as.numeric())
}))

# Apply the function to each row in the tibble using map()
pmap(tib, sample_func)
ztmd8pv5

ztmd8pv52#

你可以将tibble的列作为vector传递给函数,而不是将tibble传递给函数。

library(dplyr)
library(purrr)

sample_func <- function(name, qty, price, add){
    res <- tibble(e = qty + price + add, stock = name)
    return(res)
}

然后可以使用pmap-

out <- tib %>%
  mutate(res = pmap(list(name, qty, price, add), sample_func))

out

# A tibble: 2 × 5
#   name    qty price   add res             
#  <chr> <dbl> <dbl> <dbl> <list>          
#1 CHR1     15  222.     6 <tibble [1 × 2]>
#2 CHR2     10  119.    10 <tibble [1 × 2]>

out$res
#[[1]]
# A tibble: 1 × 2
#      e stock
#  <dbl> <chr>
#1  243. CHR1 

#[[2]]
# A tibble: 1 × 2
#      e stock
#  <dbl> <chr>
#1  139. CHR2

您可以使用unnest来获取单独的列。

out %>% unnest(res)

#  name    qty price   add     e stock
#  <chr> <dbl> <dbl> <dbl> <dbl> <chr>
#1 CHR1     15  222.     6  243. CHR1 
#2 CHR2     10  119.    10  139. CHR2
vh0rcniy

vh0rcniy3#

我们可以只将sample_func应用于pick ed数据集和unnest

library(dplyr)
library(tidyr)
tib %>% 
  transmute(temp = sample_func(pick(everything()))) %>% 
  unnest(where(is_tibble))
  • 输出
# A tibble: 2 × 2
      e stock
  <dbl> <chr>
1  243. CHR1 
2  139. CHR2

如果我们想把它看作tibble s的list

tib %>%
   rowwise %>% 
   reframe(temp = list(sample_func(pick(everything())))) %>% 
   pull(temp)
  • 输出
[[1]]
# A tibble: 1 × 2
      e stock
  <dbl> <chr>
1  243. CHR1 

[[2]]
# A tibble: 1 × 2
      e stock
  <dbl> <chr>
1  139. CHR2
8tntrjer

8tntrjer4#

为了得到你想要的输出,并且不改变你的函数或tibble,我们可以使用dplyr::rowwise()dplyr::group_map()
对于rowwise,我们告诉'dplyr'把每一行当作一个组,对于group_map,我们对每一组(在我们的例子中是行)应用一个函数,这个函数把每一组的data.frame作为输入.x,它非常适合你的sample_func()

library(dplyr)

tib %>% 
  rowwise() %>% 
  group_map(~ sample_func(.x))

#> [[1]]
#> # A tibble: 1 × 2
#>       e stock
#>   <dbl> <chr>
#> 1  243. CHR1 
#> 
#> [[2]]
#> # A tibble: 1 × 2
#>       e stock
#>   <dbl> <chr>
#> 1  139. CHR2

数据来自OP

library(tidyverse)

# Function i want to map
sample_func <- function(tib){
  
  a <- tib$name
  b <- tib$qty
  c <- tib$price
  d <- tib$add
  
  e <- b+c+d
  
  t <- tibble(e = c(e), stock = c(a))
  
  return(t)
  
}

# Define the list with multiple sublists
lst <- list(c( "CHR1", 15, 222.14, 6), c( "CHR2", 10, 119.20, 10))

# Convert each sublist to a tibble and bind the rows
tib <- bind_rows(lapply(lst, function(x) {
  tibble(name = x[1], qty = x[2] %>% as.numeric(), price = x[3] %>% as.numeric(), 
         add = x[4] %>% as.numeric())
}))

创建于2023年2月12日,使用reprex v2.0.2

相关问题