这是我的数据框
data.frame(
condition = as.factor(c("ecoli_RPMI", "staph_RPMI", "RPMI", "ecoli_DMEM", "staph_DMEM", "DMEM", "ecoli_RPMI", "staph_RPMI", "RPMI", "ecoli_DMEM", "staph_DMEM", "DMEM")),
time = as.numeric(c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2)),
value = as.numeric(c(0.3, 0.3, 0.2, 0.4, 0.4, 0.1, 0.9, 0.8, 0.1, 0.7, 0.8, 0.2)))
我有更多的条件,代表细菌,即大肠杆菌或葡萄球菌,然后是它们生长的介质,以便条件写成这样,即“ecoli_RPMI”,“staph_RPMI”,“ecoli_DMEM”,“staph_DMEM”。我有多个时间点 (50) 左右以及多种细菌和培养基。
我也有媒体控制的条件。即“RPMI”、“DMEM”在多个时间点也再次具有相应的值
我正在尝试减去与介质对照(在同一行上)对应的“值”,即从带有 RPMI 后缀的所有细菌中减去“RPMI”值,x_RPMI 即“ecoli_RPMI”、“staph_RPMI”并分配值名为“ Corrected.values”的新列,例如:ecoli_RPMI 的值 - RPMI 的值
想要的结果是这样的
data.frame(
condition = as.factor(c("ecoli_RPMI", "staph_RPMI", "RPMI", "ecoli_DMEM", "staph_DMEM", "DMEM", "ecoli_RPMI", "staph_RPMI", "RPMI", "ecoli_DMEM", "staph_DMEM", "DMEM")),
time = as.numeric(c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2)),
value = as.numeric(c(0.3, 0.3, 0.2, 0.4, 0.4, 0.1, 0.9, 0.8, 0.1, 0.7, 0.8, 0.2)),
corrected_value = as.numeric(c(0.1, 0.1, 0, 0.3, 0.3, 0, 0.8, 0.7, 0, 0.5, 0.6, 0)))
我已经尝试过各种方法:
使用
mutate
和 case_when
进行 group by 语句
有点像这样
df %>%
group_by(time)%>%
mutate(corrected_value = case_when(
conditions == "ecoli_RPMI" ~ value - value[Conditions == "RPMI"],
输入了所有的可能性,但他的似乎不起作用。我想知道是否可以使用字符串参数来简化它,因为字符串在所有条件下都是一致的,即始终
"bacteria"_"media"
我也尝试过
pivot_wider
但没有任何运气
非常感谢您的帮助!
我认为最简单的解决方案是将条件变量拆分为两个变量(细菌、培养基),然后对分组数据进行减法。你可以这样做:
data.frame(condition = as.factor(
c(
"ecoli_RPMI",
"staph_RPMI",
"RPMI",
"ecoli_DMEM",
"staph_DMEM",
"DMEM",
"ecoli_RPMI",
"staph_RPMI",
"RPMI",
"ecoli_DMEM",
"staph_DMEM",
"DMEM"
)
),
time = as.numeric(c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2)),
value = as.numeric(c(
0.3, 0.3, 0.2, 0.4, 0.4, 0.1, 0.9, 0.8, 0.1, 0.7, 0.8, 0.2
))) %>%
mutate(
bacterium = case_when(
str_detect(condition, "ecoli") ~ "Ecoli",
str_detect(condition, "staph") ~ "Staph",
TRUE ~ "None"
),
medium = case_when(
str_detect(condition, "RPMI") ~ "RPMI",
str_detect(condition, "DMEM") ~ "DMEM",
TRUE ~ "None"
)
) %>%
group_by(medium, time) %>%
mutate(corrected.values = value - value[bacterium == "None"]) %>%
ungroup()
我正在使用 str_detect() 从条件中提取细菌和培养基。然后,对于每个时间点和培养基组合,您可以从整个组中减去没有细菌时获得的值。
这会产生这个结果,这似乎就是您正在寻找的结果。
# A tibble: 12 × 6
condition time value bacterium medium corrected.values
<fct> <dbl> <dbl> <chr> <chr> <dbl>
1 ecoli_RPMI 1 0.3 Ecoli RPMI 0.1
2 staph_RPMI 1 0.3 Staph RPMI 0.1
3 RPMI 1 0.2 None RPMI 0
4 ecoli_DMEM 1 0.4 Ecoli DMEM 0.3
5 staph_DMEM 1 0.4 Staph DMEM 0.3
6 DMEM 1 0.1 None DMEM 0
7 ecoli_RPMI 2 0.9 Ecoli RPMI 0.8
8 staph_RPMI 2 0.8 Staph RPMI 0.7
9 RPMI 2 0.1 None RPMI 0
10 ecoli_DMEM 2 0.7 Ecoli DMEM 0.5
11 staph_DMEM 2 0.8 Staph DMEM 0.6
12 DMEM 2 0.2 None DMEM 0
以下是两种方法:
第一个使用
group_modify()
:
在这里,我们首先动态创建一个组
bacteria
。然后我们使用 group_modify()
来对所有分组变量进行 .keep
。神奇的事情发生在我们的函数 .f
中,我们将其应用于分组数据 dat
以及包含分组信息的 tibble grp
,其中每个组信息都存储在单独的列中。
我们基本上计算
corrected_values
调用中的 mutate
减去 value
,其中 condition
等于整个 grp$bacteria
列中的当前细菌组 value
。
library(tidyverse)
dat |>
group_by(time,
bacteria = gsub("^.*_(\\w*$)", "\\1", condition)) |>
group_modify(.keep = FALSE,
.f = \(dat, grp) {
dat |> mutate(corrected_values = value - value[condition == grp$bacteria]) |>
ungroup()
})
#> # A tibble: 12 x 5
#> time bacteria condition value corrected_values
#> <dbl> <chr> <fct> <dbl> <dbl>
#> 1 1 DMEM ecoli_DMEM 0.4 0.3
#> 2 1 DMEM staph_DMEM 0.4 0.3
#> 3 1 DMEM DMEM 0.1 0
#> 4 1 RPMI ecoli_RPMI 0.3 0.1
#> 5 1 RPMI staph_RPMI 0.3 0.1
#> 6 1 RPMI RPMI 0.2 0
#> 7 2 DMEM ecoli_DMEM 0.7 0.5
#> 8 2 DMEM staph_DMEM 0.8 0.6
#> 9 2 DMEM DMEM 0.2 0
#> 10 2 RPMI ecoli_RPMI 0.9 0.8
#> 11 2 RPMI staph_RPMI 0.8 0.7
#> 12 2 RPMI RPMI 0.1 0
第二个使用
pivot_wider() |> mutate(across()) |> pivot_longer() |> left_join()
。
诀窍在于
across()
语句,其中我们迭代每一列(time
除外),然后 get
具有相应后缀的列,并从当前列 col
中减去它。
library(tidyverse)
dat |>
pivot_wider(names_from = condition,
values_from = value) |>
mutate(across(! time,
\(col) col - get(gsub("^.*_(\\w*$)", "\\1", cur_column()))
)
) |>
pivot_longer(cols = !time,
names_to = "condition",
values_to = "corrected_values") |>
left_join(dat, by = c("time", "condition"))
#> # A tibble: 12 x 4
#> time condition corrected_values value
#> <dbl> <chr> <dbl> <dbl>
#> 1 1 ecoli_RPMI 0.1 0.3
#> 2 1 staph_RPMI 0.1 0.3
#> 3 1 RPMI 0 0.2
#> 4 1 ecoli_DMEM 0.3 0.4
#> 5 1 staph_DMEM 0.3 0.4
#> 6 1 DMEM 0 0.1
#> 7 2 ecoli_RPMI 0.8 0.9
#> 8 2 staph_RPMI 0.7 0.8
#> 9 2 RPMI 0 0.1
#> 10 2 ecoli_DMEM 0.5 0.7
#> 11 2 staph_DMEM 0.6 0.8
#> 12 2 DMEM 0 0.2
来自OP的数据
dat <- data.frame( condition = as.factor(c("ecoli_RPMI", "staph_RPMI", "RPMI", "ecoli_DMEM", "staph_DMEM", "DMEM", "ecoli_RPMI", "staph_RPMI", "RPMI", "ecoli_DMEM", "staph_DMEM", "DMEM")), time = as.numeric(c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2)), value = as.numeric(c(0.3, 0.3, 0.2, 0.4, 0.4, 0.1, 0.9, 0.8, 0.1, 0.7, 0.8, 0.2)))
由 reprex 包于 2023 年 7 月 27 日创建(v2.0.1)
您可以使用以下方法,将条件分为成分应变和介质,然后(每次)从包含应变的行中减去不包含应变的行:
data |>
separate(condition, c("strain", "medium"), "_", remove = FALSE, fill = "left") |>
group_by(time, medium) |>
mutate(corrected_value = value - value[is.na(strain)]) |>
ungroup()
产量:
# A tibble: 12 × 6
condition strain medium time value corrected_value
<fct> <chr> <chr> <dbl> <dbl> <dbl>
1 ecoli_RPMI ecoli RPMI 1 0.3 0.1
2 staph_RPMI staph RPMI 1 0.3 0.1
3 RPMI NA RPMI 1 0.2 0
4 ecoli_DMEM ecoli DMEM 1 0.4 0.3
5 staph_DMEM staph DMEM 1 0.4 0.3
6 DMEM NA DMEM 1 0.1 0
7 ecoli_RPMI ecoli RPMI 2 0.9 0.8
8 staph_RPMI staph RPMI 2 0.8 0.7
9 RPMI NA RPMI 2 0.1 0
10 ecoli_DMEM ecoli DMEM 2 0.7 0.5
11 staph_DMEM staph DMEM 2 0.8 0.6
12 DMEM NA DMEM 2 0.2 0
或者,考虑将数据重塑为语义上更有意义的格式:
data |>
separate(condition, c("strain", "medium"), "_", fill = "left") |>
pivot_wider(names_from = strain) |>
rename(baseline = `NA`) |>
pivot_longer(! c(medium, time, baseline), names_to = "strain") |>
mutate(corrected_value = value - baseline)
# A tibble: 8 × 6
medium time baseline strain value corrected_value
<chr> <dbl> <dbl> <chr> <dbl> <dbl>
1 RPMI 1 0.2 ecoli 0.3 0.1
2 RPMI 1 0.2 staph 0.3 0.1
3 DMEM 1 0.1 ecoli 0.4 0.3
4 DMEM 1 0.1 staph 0.4 0.3
5 RPMI 2 0.1 ecoli 0.9 0.8
6 RPMI 2 0.1 staph 0.8 0.7
7 DMEM 2 0.2 ecoli 0.7 0.5
8 DMEM 2 0.2 staph 0.8 0.6