假设我有以下数据帧
df1 <- data.frame(cbind("Method" = c("A", "A", "A", "A",
"B", "B", "B", "B",
"C", "C", "C", "C"),
"Sub" = c(rep(1:4, 2), c(1, 2, 4, 3)),
"Value1" = c(1, 2, 3, 4, 0, 0, 0, 0, 1, 2, 3, 4),
"Value2" = c(-1, -2, -3, -4, 0, 0, 0, 0, -1, -2, -3, -4),
"Value3" = 1:12))
Method Sub Value1 Value2 Value3
1 A 1 1 -1 1
2 A 2 2 -2 2
3 A 3 3 -3 3
4 A 4 4 -4 4
5 B 1 0 0 5
6 B 2 0 0 6
7 B 3 0 0 7
8 B 4 0 0 8
9 C 1 1 -1 9
10 C 2 2 -2 10
11 C 4 3 -3 11
12 C 3 4 -4 12
我想通过减去Method == A
观察到的值来改变Value1
和Value2
。在本例中,期望的输出将是
Method Sub Value1 Value2 Value3
1 A 1 0 0 1
2 A 2 0 0 2
3 A 3 0 0 3
4 A 4 0 0 4
5 B 1 -1 1 5
6 B 2 -2 2 6
7 B 3 -3 3 7
8 B 4 -4 4 8
9 C 1 0 0 9
10 C 2 0 0 10
11 C 4 -1 1 11
12 C 3 1 -1 12
基本上,它看起来像从df1[5:8, 3:4]和df1[9:12, 3:4]中减去df1[1:4, 3:4],除了行必须匹配Sub
(参见Method == C中的Sub顺序)。如何有效地实现这一点有什么帮助吗?
使用dplyr你可以做
library(dplyr)
df1 %>%
group_by(Sub) %>%
mutate(across(Value1:Value2, ~.x-.x[Method=="A"]))
# Method Sub Value1 Value2 Value3
# <chr> <dbl> <dbl> <dbl> <int>
# 1 A 1 0 0 1
# 2 A 2 0 0 2
# 3 A 3 0 0 3
# 4 A 4 0 0 4
# 5 B 1 -1 1 5
# 6 B 2 -2 2 6
# 7 B 3 -3 3 7
# 8 B 4 -4 4 8
# 9 C 1 0 0 9
# 10 C 2 0 0 10
# 11 C 4 -1 1 11
# 12 C 3 1 -1 12
这将为每个Sub创建一个组,然后您可以提取方法的值==" a ">
您必须使用ifelse
函数。它的工作原理就像Excel中的if
函数
library(dplyr)
df2 <- df1 %>%
mutate(Value4 = ifelse(Method == "A", Value1 - Value2 , NA))
作为旁注,您可以更容易地构建您的DataFrame:
df1 <- data.frame(
Method = c("A", "A", "A", "A",
"B", "B", "B", "B",
"C", "C", "C", "C"),
Sub = c(rep(1:4, 2), c(1, 2, 4, 3)),
Value1 = c(1, 2, 3, 4, 0, 0, 0, 0, 1, 2, 3, 4),
Value2 = c(-1, -2, -3, -4, 0, 0, 0, 0, -1, -2, -3, -4),
Value3 = c(1:12)
)