是否可以使用for循环和mutate()?

时间:2019-12-10 21:36:57

标签: r dplyr purrr

我正在尝试编写一个代码,该代码将自动扰乱多个96孔板的列。

这是数据的一个小例子:

plate <- data.frame(column = rep(c(rep("02", 4), rep("03", 4), rep("04", 4)), 2),
                    row = rep(c("A", "B", "C", "D"), 6),
                    plate_id = c(rep("Plate_1", 12), rep("Plate_2", 12)),
                    compound = 1:24) %>%
  mutate(well_id = paste0(row, column))

   column row plate_id compound well_id
1      02   A  Plate_1        1     A02
2      02   B  Plate_1        2     B02
3      02   C  Plate_1        3     C02
4      02   D  Plate_1        4     D02
5      03   A  Plate_1        5     A03
6      03   B  Plate_1        6     B03
7      03   C  Plate_1        7     C03
8      03   D  Plate_1        8     D03
9      04   A  Plate_1        9     A04
10     04   B  Plate_1       10     B04
11     04   C  Plate_1       11     C04
12     04   D  Plate_1       12     D04
13     02   A  Plate_2       13     A02
14     02   B  Plate_2       14     B02
15     02   C  Plate_2       15     C02
16     02   D  Plate_2       16     D02
17     03   A  Plate_2       17     A03
18     03   B  Plate_2       18     B03
19     03   C  Plate_2       19     C03
20     03   D  Plate_2       20     D03
21     04   A  Plate_2       21     A04
22     04   B  Plate_2       22     B04
23     04   C  Plate_2       23     C04
24     04   D  Plate_2       24     D04

到目前为止,我所做的是:

all_col <- plate$column %>% unique()
col_list <- rep(list(all_col), plate$plate_id %>% unique() %>% length())
set.seed(2248)
random_col_list <- lapply(col_list, function(x) sample(x))
names(random_col_list) <- plate$plate_id %>% unique()

plate_randomized <- plate %>% #there has to be a better way...
  mutate(newcol = case_when(column == all_col[1] & plate_id == "Plate_1" ~ random_col_list$Plate_1[1],
                            column == all_col[2] & plate_id == "Plate_1" ~ random_col_list$Plate_1[2],
                            column == all_col[3] & plate_id == "Plate_1" ~ random_col_list$Plate_1[3],
                            column == all_col[1] & plate_id == "Plate_2" ~ random_col_list$Plate_2[1],
                            column == all_col[2] & plate_id == "Plate_2" ~ random_col_list$Plate_2[2],
                            column == all_col[3] & plate_id == "Plate_2" ~ random_col_list$Plate_2[3]),
         new_id = paste0(row, newcol))

   column row plate_id compound well_id newcol new_id
1      02   A  Plate_1        1     A02     03    A03
2      02   B  Plate_1        2     B02     03    B03
3      02   C  Plate_1        3     C02     03    C03
4      02   D  Plate_1        4     D02     03    D03
5      03   A  Plate_1        5     A03     02    A02
6      03   B  Plate_1        6     B03     02    B02
7      03   C  Plate_1        7     C03     02    C02
8      03   D  Plate_1        8     D03     02    D02
9      04   A  Plate_1        9     A04     04    A04
10     04   B  Plate_1       10     B04     04    B04
11     04   C  Plate_1       11     C04     04    C04
12     04   D  Plate_1       12     D04     04    D04
13     02   A  Plate_2       13     A02     04    A04
14     02   B  Plate_2       14     B02     04    B04
15     02   C  Plate_2       15     C02     04    C04
16     02   D  Plate_2       16     D02     04    D04
17     03   A  Plate_2       17     A03     02    A02
18     03   B  Plate_2       18     B03     02    B02
19     03   C  Plate_2       19     C03     02    C02
20     03   D  Plate_2       20     D03     02    D02
21     04   A  Plate_2       21     A04     03    A03
22     04   B  Plate_2       22     B04     03    B03
23     04   C  Plate_2       23     C04     03    C03
24     04   D  Plate_2       24     D04     03    D03

这可以满足我的需求,但是理想情况下,我可以在all_colrandom_col_list索引以及每个plate_id上“循环”,因为这是一个大数据集。

这是与this question类似的问题,但是答案并未说明如何使用purr::map!!!!!,所以我不知道如何使用解决这个问题。

2 个答案:

答案 0 :(得分:1)

我猜dplyr的方法是改变列级别的顺序,并对向量进行重新排序。然后,我们编写了一个在子集中执行此操作的函数:

library(purrr)
library(tidyr)
library(dplyr)

swap_col=function(df){
df %>% 
mutate(newcol=factor(column,levels=sample(unique(column)))) %>%
mutate(newcol=as.character(sort(newcol))) %>%
mutate(newid=paste0(row,newcol))
}

我们可以在一个子集上对此进行测试:

swap_col(subset(plate,plate_id=="Plate_1"))

   column row plate_id compound well_id newcol newid
1      02   A  Plate_1        1     A02     02   A02
2      02   B  Plate_1        2     B02     02   B02
3      02   C  Plate_1        3     C02     02   C02
4      02   D  Plate_1        4     D02     02   D02
5      03   A  Plate_1        5     A03     04   A04
6      03   B  Plate_1        6     B03     04   B04
7      03   C  Plate_1        7     C03     04   C04
8      03   D  Plate_1        8     D03     04   D04
9      04   A  Plate_1        9     A04     03   A03
10     04   B  Plate_1       10     B04     03   B03
11     04   C  Plate_1       11     C04     03   C03
12     04   D  Plate_1       12     D04     03   D03

现在我们使用purrr应用于每个子集

plate %>% split(.$plate_id) %>% map_dfr(swap_col)

答案 1 :(得分:1)

如果您想使用purrrdplyr,请执行以下操作:

首先编写一个可以执行所需功能的函数

newcol = function(all_col_list, col, plate, output){
    col_index = which(all_col_list %in% col)
    var = output[[plate]][col_index]
    return(as.character(var))
}

然后使用mutate和map2:

plate_randomized <- plate %>%  #there is a better way...
  mutate(newcol = map2(column, plate_id, ~ newcol(all_col,.x, .y, 
random_col_list)),
     new_id = paste0(row, newcol))

   column row plate_id compound well_id newcol new_id
1      02   A  Plate_1        1     A02     02    A02
2      02   B  Plate_1        2     B02     02    B02
3      02   C  Plate_1        3     C02     02    C02
4      02   D  Plate_1        4     D02     02    D02
5      03   A  Plate_1        5     A03     04    A04
6      03   B  Plate_1        6     B03     04    B04
7      03   C  Plate_1        7     C03     04    C04
8      03   D  Plate_1        8     D03     04    D04
9      04   A  Plate_1        9     A04     03    A03
10     04   B  Plate_1       10     B04     03    B03
11     04   C  Plate_1       11     C04     03    C03
12     04   D  Plate_1       12     D04     03    D03
13     02   A  Plate_2       13     A02     04    A04
14     02   B  Plate_2       14     B02     04    B04
15     02   C  Plate_2       15     C02     04    C04
16     02   D  Plate_2       16     D02     04    D04
17     03   A  Plate_2       17     A03     03    A03
18     03   B  Plate_2       18     B03     03    B03
19     03   C  Plate_2       19     C03     03    C03
20     03   D  Plate_2       20     D03     03    D03
21     04   A  Plate_2       21     A04     02    A02
22     04   B  Plate_2       22     B04     02    B02
23     04   C  Plate_2       23     C04     02    C02
24     04   D  Plate_2       24     D04     02    D02