применить пользовательскую функцию к сгруппированному фрейму данных из n строк одновременно

#r #dplyr #data.table #tidyverse #purrr

#r #dplyr #data.table #tidyverse #муррр

Вопрос:

Определяемая пользователем функция

   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), но это не элегантный способ.

 - 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"))
 
 
 

Комментарии:

1. В примере, который вы приводите в конце своего сообщения, вы упоминаете группы из 10 строк, так почему 19 строк не вырезаны в 10 9 вместо 12 7, как вы предлагаете?

2. @Waldi мой плохой, его 10 9. обновленный вопрос

Ответ №1:

Вы могли бы использовать slider::slide для создания подгрупп :

 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
 

Комментарии:

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

2. Я понимаю, что имя файла должно зависеть от group_by переменных, country и strain которые хранятся в group[1] и group[2] . Каким должно быть содержимое файла? Я думал, что это будет подгруппа df . Как вы можете быть уверены, что assay_type это одно и то же в подгруппе? Должно ли это также быть group_by полем?

3. Извините, я предполагаю, что это моя ошибка — не публиковать полный пример. Я думал, что запись файла является конечной целью, поэтому любая функция будет работать. Но, похоже, это невозможно. Я постоянно получаю эту ошибку Error in file(con, "wb") : invalid 'description' argument . Если в группе есть только 1 файл, ваш код работает, но если есть несколько файлов, которые необходимо объединить в 1 файл, он выдает указанную выше ошибку. Я замечаю, что iwalk это находится в списке файлов, в то время как group_map взял файлы группы. сможете ли вы изменить свой ответ, чтобы он соответствовал обновленному вопросу и функции?

4. group_map imap предоставляет 3 входных данных для Collage : 2 group_by переменных country и strain подгруппированного фрейма данных, содержащего от 1 до 10 строк с остальными переменными. Вам не нужно assay path явно передавать и групповой функции Collage , потому что они уже находятся в подгруппированном фрейме данных : .x$assay , .x$path , … Затем вы должны перебирать Collage фрейм данных для обработки каждой строки.

5. См. Мою правку, чтобы проиллюстрировать мой предыдущий комментарий. Отвечает ли это на ваш вопрос «применить пользовательскую функцию к сгруппированному фрейму данных n строк одновременно»?