【问题标题】:apply a custom function on grouped dataframe n rows at a time一次在分组数据帧 n 行上应用自定义函数
【发布时间】:2021-02-01 18:48:38
【问题描述】:

用户定义函数

  CollageImage <- function(path, country, strain, assay,subgroup) {
  img_out <- magick::image_read(path) %>%
    magick::image_trim() %>%
    magick::image_convert(format = "jpeg") %>%
    magick::image_montage(
      tile = tile,
      geometry = paste(500, "x", 500, "+5+5", sep = "")
    ) %>%
    magick::image_border(geometry = "10x80", color = "#FFFFFF") %>%
    magick::image_annotate(
      paste(country, "\n", strain,
            sep = " "
      ),
      weight = 700,
      size = 30,
      location = "+0+0",
      gravity = "north"
    ) %>%
    magick::image_convert("jpg")
  
  #' write the image to file
  img_out %>%
    magick::image_write(
      format = "jpeg",
      path = here::here(paste(country, strain, assay,subgroup, "collage.jpg", sep = "_")),
      quality = 100,
      density = 300
    )
  #' check the collage info
  magick::image_info(img_out)
}
    

分组数据框

out_df <- df %>% dplyr::group_by(country ,strain)

分组映射以在分组数据帧上应用函数

out_df %>% 
  dplyr::group_map( ~ CollageEachGroup(
  path = .x$path,
  country = .y$country,
  assay = .x$assay,
  strain = .y$strain,
  subgroup
))
  

我想通过在每个组中一次移动 10 行的窗口来应用该功能。感谢有关如何执行此操作的任何输入。例如,如果一个组中有 19 个图像,我想写 2 个文件。 1 将是 10 个文件的拼贴画,而其他将是 9 个文件的拼贴画。而且,文件名必须是A_UK_19_1.csv 和A_UK_19_2.csv

这是我想解决的一种方法(来自 So answers),但这不是一种优雅的方法。

- Filter each group put
- create a block for each group as follows

    df_subset$bloc <-
      rep(seq(1, 1 + nrow(df_subset) %/% bloc_len), each = bloc_len, length.out = nrow(df_subset))


dput(df)
structure(list(png_file = c("A_UK_1_lp21_pmn1__1.png", "A_UK_1_xno9_pmn1__1.png", 
"A_UK_2.14.3_lp21_pmn1__1.png", "A_UK_2.14.3_xno9_pmn1__1.png", 
"A_UK_2.2_lp21_zn78__1.png", "A_UK_2.2_xno9_zn78__1.png", "A_UK_2.3_lp21_pmn1__1.png", 
"A_UK_2.3_xno9_pmn1__1.png", "A_UK_2.4_lp21_yun7__1.png", "A_UK_2.8.1_lp21_pmn1__1.png", 
"A_UK_2.8.1_xno9_pmn1__1.png", "A_UK_2.8.2_lp21_pmn1__1.png", 
"A_UK_2.8.2_xno9_pmn1__1.png", "B_UK_2.1_lp21_pmn1__1.png", "B_UK_2.1_xno9_pmn1__1.png", 
"B_UK_2.14.1_lp21_pmn1__1.png", "B_UK_2.14.1_xno9_pmn1__1.png", 
"B_UK_2.14.2_lp21_pmn1__1.png", "B_UK_2.14.2_xno9_pmn1__1.png", 
"A_UK_2.14.3_lp21_pmn1__1.png", "A_UK_2.14.3_xno9_pmn1__1.png", 
"A_UK_2.2_lp21_zn78__1.png", "A_UK_2.2_xno9_zn78__1.png", "A_UK_2.3_lp21_pmn1__1.png", 
"A_UK_2.3_xno9_pmn1__1.png", "A_UK_2.4_lp21_yun7__1.png", "A_UK_2.8.1_lp21_pmn1__1.png", 
"A_UK_2.8.1_xno9_pmn1__1.png", "A_UK_2.8.2_lp21_pmn1__1.png", 
"A_UK_2.8.2_xno9_pmn1__1.png", "B_UK_2.14.1_lp21_pmn1__1.png", 
"B_UK_2.14.1_xno9_pmn1__1.png", "B_UK_2.14.2_lp21_pmn1__1.png", 
"B_UK_2.14.2_xno9_pmn1__1.png", "A_UK_2.2_lp21_zn78__1.png", 
"A_UK_2.2_xno9_zn78__1.png", "A_UK_2.3_lp21_pmn1__1.png", "A_UK_2.3_xno9_pmn1__1.png", 
"A_UK_2.4_lp21_yun7__1.png", "A_UK_2.9.1_lp21_yun7__1.png", "B_UK_2.12.1_lp21_yun7__1.png", 
"B_UK_2.12.2_lp21_yun7__1.png", "B_UK_2.7.1_lp21_pmn1__1.png", 
"B_UK_2.7.1_xno9_pmn1__1.png", "B_UK_2.7.4_lp21_yun7__1.png", 
"B_UK_2.9.2_lp21_yun7__1.png", "A_UK_2.4_lp21_yun7__1.png", "A_UK_2.5.4_lp21_pmn1__1.png", 
"A_UK_2.5.4_xno9_pmn1__1.png", "A_UK_2.6.4_lp21_yun7__1.png", 
"B_UK_2.5.3_lp21_yun7__1.png", "A_UK_2.4_lp21_yun7__1.png"), 
    path = c("C:/path/A_UK_1_lp21_pmn1__1.png", "C:/path/A_UK_1_xno9_pmn1__1.png", 
    "C:/path/A_UK_2.14.3_lp21_pmn1__1.png", "C:/path/A_UK_2.14.3_xno9_pmn1__1.png", 
    "C:/path/A_UK_2.2_lp21_zn78__1.png", "C:/path/A_UK_2.2_xno9_zn78__1.png", 
    "C:/path/A_UK_2.3_lp21_pmn1__1.png", "C:/path/A_UK_2.3_xno9_pmn1__1.png", 
    "C:/path/A_UK_2.4_lp21_yun7__1.png", "C:/path/A_UK_2.8.1_lp21_pmn1__1.png", 
    "C:/path/A_UK_2.8.1_xno9_pmn1__1.png", "C:/path/A_UK_2.8.2_lp21_pmn1__1.png", 
    "C:/path/A_UK_2.8.2_xno9_pmn1__1.png", "C:/path/B_UK_2.1_lp21_pmn1__1.png", 
    "C:/path/B_UK_2.1_xno9_pmn1__1.png", "C:/path/B_UK_2.14.1_lp21_pmn1__1.png", 
    "C:/path/B_UK_2.14.1_xno9_pmn1__1.png", "C:/path/B_UK_2.14.2_lp21_pmn1__1.png", 
    "C:/path/B_UK_2.14.2_xno9_pmn1__1.png", "C:/path/A_UK_2.14.3_lp21_pmn1__1.png", 
    "C:/path/A_UK_2.14.3_xno9_pmn1__1.png", "C:/path/A_UK_2.2_lp21_zn78__1.png", 
    "C:/path/A_UK_2.2_xno9_zn78__1.png", "C:/path/A_UK_2.3_lp21_pmn1__1.png", 
    "C:/path/A_UK_2.3_xno9_pmn1__1.png", "C:/path/A_UK_2.4_lp21_yun7__1.png", 
    "C:/path/A_UK_2.8.1_lp21_pmn1__1.png", "C:/path/A_UK_2.8.1_xno9_pmn1__1.png", 
    "C:/path/A_UK_2.8.2_lp21_pmn1__1.png", "C:/path/A_UK_2.8.2_xno9_pmn1__1.png", 
    "C:/path/B_UK_2.14.1_lp21_pmn1__1.png", "C:/path/B_UK_2.14.1_xno9_pmn1__1.png", 
    "C:/path/B_UK_2.14.2_lp21_pmn1__1.png", "C:/path/B_UK_2.14.2_xno9_pmn1__1.png", 
    "C:/path/A_UK_2.2_lp21_zn78__1.png", "C:/path/A_UK_2.2_xno9_zn78__1.png", 
    "C:/path/A_UK_2.3_lp21_pmn1__1.png", "C:/path/A_UK_2.3_xno9_pmn1__1.png", 
    "C:/path/A_UK_2.4_lp21_yun7__1.png", "C:/path/A_UK_2.9.1_lp21_yun7__1.png", 
    "C:/path/B_UK_2.12.1_lp21_yun7__1.png", "C:/path/B_UK_2.12.2_lp21_yun7__1.png", 
    "C:/path/B_UK_2.7.1_lp21_pmn1__1.png", "C:/path/B_UK_2.7.1_xno9_pmn1__1.png", 
    "C:/path/B_UK_2.7.4_lp21_yun7__1.png", "C:/path/B_UK_2.9.2_lp21_yun7__1.png", 
    "C:/path/A_UK_2.4_lp21_yun7__1.png", "C:/path/A_UK_2.5.4_lp21_pmn1__1.png", 
    "C:/path/A_UK_2.5.4_xno9_pmn1__1.png", "C:/path/A_UK_2.6.4_lp21_yun7__1.png", 
    "C:/path/B_UK_2.5.3_lp21_yun7__1.png", "C:/path/A_UK_2.4_lp21_yun7__1.png"
    ), assay = c("A", "A", "A", "A", "A", "A", "A", "A", "A", 
    "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "A", "A", 
    "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", 
    "B", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", 
    "B", "A", "A", "A", "A", "B", "A"), country = c("UK", "UK", 
    "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", 
    "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", 
    "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", 
    "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", 
    "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK", "UK"
    ), strain = c("Covid_123", "Covid_123", "Covid_123", "Covid_123", 
    "Covid_123", "Covid_123", "Covid_123", "Covid_123", "Covid_123", 
    "Covid_123", "Covid_123", "Covid_123", "Covid_123", "Covid_123", 
    "Covid_123", "Covid_123", "Covid_123", "Covid_123", "Covid_123", 
    "Covid_125", "Covid_125", "Covid_125", "Covid_125", "Covid_125", 
    "Covid_125", "Covid_125", "Covid_125", "Covid_125", "Covid_125", 
    "Covid_125", "Covid_125", "Covid_125", "Covid_125", "Covid_125", 
    "Covid_127", "Covid_127", "Covid_127", "Covid_127", "Covid_127", 
    "Covid_127", "Covid_127", "Covid_127", "Covid_127", "Covid_127", 
    "Covid_127", "Covid_127", "Covid_127", "Covid_127", "Covid_127", 
    "Covid_127", "Covid_127", "Covid_128")), spec = structure(list(
    cols = list(png_file = structure(list(), class = c("collector_character", 
    "collector")), path = structure(list(), class = c("collector_character", 
    "collector")), assay = structure(list(), class = c("collector_character", 
    "collector")), country = structure(list(), class = c("collector_character", 
    "collector")), strain = structure(list(), class = c("collector_character", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), delim = ","), class = "col_spec"), row.names = c(NA, 
-52L), class = c("tbl_df", "tbl", "data.frame"))
 
 

【问题讨论】:

  • 在您在帖子末尾给出的示例中,您提到了 10 行的组,那么为什么 19 行没有按照您的建议切成 10+9 而不是 12+7?
  • @Waldi 我的错,它的 10 + 9。更新 Q

标签: r dplyr data.table tidyverse purrr


【解决方案1】:

您可以使用 slider::slide 到 create subgroups :

library(dplyr)
library(purrr)
library(slider)

N <- 10

Collage <- function(country,strain,subgroupnumber,data) {
  cat(paste('Processing:',country,'-',strain,'/',subgroupnumber),'\n')
  cat(paste(nrow(data) , ' files to read \n'))
  cat(paste(data$png_file,collapse=' ; '),'\n')
  cat('\n')
}

res <- df %>% group_by(country,strain) %>% 
  group_walk(~{
    group <- .y
    subgroups <- slider::slide(.x,.f=~.x,.step = N ,.after = N-1)
    # Remove empty elements
    subgroups <- subgroups[lengths(subgroups) != 0]
    
    # Run wished function on each subgroup
    subgroups %>% iwalk(~{
      Collage(group[1],group[2],.y,.x)
  })

})

Processing: UK - Covid_123 / 1 
10  files to read 
A_UK_1_lp21_pmn1__1.png ; A_UK_1_xno9_pmn1__1.png ; A_UK_2.14.3_lp21_pmn1__1.png ; A_UK_2.14.3_xno9_pmn1__1.png ; A_UK_2.2_lp21_zn78__1.png ; A_UK_2.2_xno9_zn78__1.png ; A_UK_2.3_lp21_pmn1__1.png ; A_UK_2.3_xno9_pmn1__1.png ; A_UK_2.4_lp21_yun7__1.png ; A_UK_2.8.1_lp21_pmn1__1.png 

Processing: UK - Covid_123 / 2 
9  files to read 
A_UK_2.8.1_xno9_pmn1__1.png ; A_UK_2.8.2_lp21_pmn1__1.png ; A_UK_2.8.2_xno9_pmn1__1.png ; B_UK_2.1_lp21_pmn1__1.png ; B_UK_2.1_xno9_pmn1__1.png ; B_UK_2.14.1_lp21_pmn1__1.png ; B_UK_2.14.1_xno9_pmn1__1.png ; B_UK_2.14.2_lp21_pmn1__1.png ; B_UK_2.14.2_xno9_pmn1__1.png 

Processing: UK - Covid_125 / 1 
10  files to read 
A_UK_2.14.3_lp21_pmn1__1.png ; A_UK_2.14.3_xno9_pmn1__1.png ; A_UK_2.2_lp21_zn78__1.png ; A_UK_2.2_xno9_zn78__1.png ; A_UK_2.3_lp21_pmn1__1.png ; A_UK_2.3_xno9_pmn1__1.png ; A_UK_2.4_lp21_yun7__1.png ; A_UK_2.8.1_lp21_pmn1__1.png ; A_UK_2.8.1_xno9_pmn1__1.png ; A_UK_2.8.2_lp21_pmn1__1.png 

Processing: UK - Covid_125 / 2 
5  files to read 
A_UK_2.8.2_xno9_pmn1__1.png ; B_UK_2.14.1_lp21_pmn1__1.png ; B_UK_2.14.1_xno9_pmn1__1.png ; B_UK_2.14.2_lp21_pmn1__1.png ; B_UK_2.14.2_xno9_pmn1__1.png 

Processing: UK - Covid_127 / 1 
10  files to read 
A_UK_2.2_lp21_zn78__1.png ; A_UK_2.2_xno9_zn78__1.png ; A_UK_2.3_lp21_pmn1__1.png ; A_UK_2.3_xno9_pmn1__1.png ; A_UK_2.4_lp21_yun7__1.png ; A_UK_2.9.1_lp21_yun7__1.png ; B_UK_2.12.1_lp21_yun7__1.png ; B_UK_2.12.2_lp21_yun7__1.png ; B_UK_2.7.1_lp21_pmn1__1.png ; B_UK_2.7.1_xno9_pmn1__1.png 

Processing: UK - Covid_127 / 2 
7  files to read 
B_UK_2.7.4_lp21_yun7__1.png ; B_UK_2.9.2_lp21_yun7__1.png ; A_UK_2.4_lp21_yun7__1.png ; A_UK_2.5.4_lp21_pmn1__1.png ; A_UK_2.5.4_xno9_pmn1__1.png ; A_UK_2.6.4_lp21_yun7__1.png ; B_UK_2.5.3_lp21_yun7__1.png 

Processing: UK - Covid_128 / 1 
1  files to read 
A_UK_2.4_lp21_yun7__1.png 
              1

【讨论】:

  • 谢谢,但是当我尝试传递列名时出现错误,在这种情况下Warning: Unknown or uninitialised column: country.. Error in file(con, "wb") : invalid description' argument. 例如,要命名csv文件,我想传递列名,并且在子组的情况下,组也是如此。文件名将是 RTPCR_UK_15_1.csv RTPCR_UK_15_2.csv
  • 我的理解是文件名应该取决于group_by变量,country和strain,它们存储在group[1]和group[2]中。文件的内容应该是什么?我认为这将是df 的一个子组。您如何确定assay_type 在子组中是相同的?它也应该是group_by 字段吗?
  • 对不起,我想我没有发布完整的例子是我的错误。我认为编写文件是最终目标,因此任何功能都可以工作。但是,看起来这是不可能的。我经常收到此错误Error in file(con, "wb") : invalid 'description' argument。如果组中只有 1 个文件,则您的代码可以工作,但如果有多个文件需要拼贴到 1 个文件中,则会引发上述错误。我注意到iwalk 在文件列表中,而 group_map 获取了一个组文件。你能修改你的答案以适应更新的 Q 和函数吗?
  • group_map + imap 为 Collage 提供 3 个输入:2 个 group_by 变量 country 和 strain 以及一个包含 1-10 行的子分组数据框,其余的变量。您不需要将assay 和path 显式传递给组函数Collage,因为它们已经在子分组数据帧中:.x$assay,.x$path,...然后您应该循环遍历数据帧Collage 处理每一行。
  • 查看我的编辑以说明我之前的评论。它是否回答了您的问题“一次对 n 行分组数据框应用自定义函数”?
猜你喜欢
  • 2015-02-13
  • 2015-10-23
  • 2021-10-06
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多