有条件地用不同行的值填充单元格
Conditionally fill cells with values from different row
假设我有以下数据框:
df <- data.frame(cbind("Method" = rep(c("A","B"), each = 3),
"Sub" = rep(c("A1", "A2", "A3"), times = 2),
"Value1" = c(2, 3, NA, 4, 2, 3),
"Value2" = c(1, 2, NA, 2, 3, 3),
"Value3" = c(2, 2, 3, 1, 2, 2)))
# Method Sub Value1 Value2 Value3
# 1 A A1 2 1 2
# 2 A A2 3 2 2
# 3 A A3 <NA> <NA> 3
# 4 B A1 4 2 1
# 5 B A2 2 3 2
# 6 B A3 3 3 2
Value1
和 Value2
的值将在 Method == A
和 Sub == A3
时系统地显示缺失值。我希望这些值被出现在 Method == A
和 Sub == A2
处的值替换。在这种情况下,所需的输出是
# Method Sub Value1 Value2 Value3
# 1 A A1 2 1 2
# 2 A A2 3 2 2
# 3 A A3 3 2 3
# 4 B A1 4 2 1
# 5 B A2 2 3 2
# 6 B A3 3 3 2
我怎样才能做到这一点?请注意,实际上,我的 df 要复杂得多,有更多的列和行以及更多可能的方法和值。我尝试使用 for 循环,但也许有更有效的方法(例如,使用 dplyr)。
提前致谢!
这个怎么样:
library(tidyverse)
df <- data.frame(cbind("Method" = rep(c("A","B"), each = 3),
"Sub" = rep(c("A1", "A2", "A3"), times = 2),
"Value1" = c(2, 3, NA, 4, 2, 3),
"Value2" = c(1, 2, NA, 2, 3, 3),
"Value3" = c(2, 2, 3, 1, 2, 2)))
df %>%
group_by(Method) %>%
mutate(across(c(Value1, Value2),
~case_when(is.na(.x) & Method == "A" & Sub == "A3" ~ .x[which(Sub == "A2")],
TRUE ~ .x)))
#> # A tibble: 6 × 5
#> # Groups: Method [2]
#> Method Sub Value1 Value2 Value3
#> <chr> <chr> <chr> <chr> <chr>
#> 1 A A1 2 1 2
#> 2 A A2 3 2 2
#> 3 A A3 3 2 3
#> 4 B A1 4 2 1
#> 5 B A2 2 3 2
#> 6 B A3 3 3 2
由 reprex package (v2.0.1)
于 2022-05-20 创建
使用coalesce
的另一个解决方案:
library(dplyr)
df <- data.frame(cbind("Method" = rep(c("A","B"), each = 3),
"Sub" = rep(c("A1", "A2", "A3"), times = 2),
"Value1" = c(2, 3, NA, 4, 2, 3),
"Value2" = c(1, 2, NA, 2, 3, 3),
"Value3" = c(2, 2, 3, 1, 2, 2)))
df <- df %>%
dplyr::mutate(dplyr::across(Value1:Value2, ~dplyr::coalesce(.x, .x[Method == "A" & Sub == "A2"])))
df
#> Method Sub Value1 Value2 Value3
#> 1 A A1 2 1 2
#> 2 A A2 3 2 2
#> 3 A A3 3 2 3
#> 4 B A1 4 2 1
#> 5 B A2 2 3 2
#> 6 B A3 3 3 2
Created on 2022-05-20 by the reprex package (v2.0.1)
假设我有以下数据框:
df <- data.frame(cbind("Method" = rep(c("A","B"), each = 3),
"Sub" = rep(c("A1", "A2", "A3"), times = 2),
"Value1" = c(2, 3, NA, 4, 2, 3),
"Value2" = c(1, 2, NA, 2, 3, 3),
"Value3" = c(2, 2, 3, 1, 2, 2)))
# Method Sub Value1 Value2 Value3
# 1 A A1 2 1 2
# 2 A A2 3 2 2
# 3 A A3 <NA> <NA> 3
# 4 B A1 4 2 1
# 5 B A2 2 3 2
# 6 B A3 3 3 2
Value1
和 Value2
的值将在 Method == A
和 Sub == A3
时系统地显示缺失值。我希望这些值被出现在 Method == A
和 Sub == A2
处的值替换。在这种情况下,所需的输出是
# Method Sub Value1 Value2 Value3
# 1 A A1 2 1 2
# 2 A A2 3 2 2
# 3 A A3 3 2 3
# 4 B A1 4 2 1
# 5 B A2 2 3 2
# 6 B A3 3 3 2
我怎样才能做到这一点?请注意,实际上,我的 df 要复杂得多,有更多的列和行以及更多可能的方法和值。我尝试使用 for 循环,但也许有更有效的方法(例如,使用 dplyr)。
提前致谢!
这个怎么样:
library(tidyverse)
df <- data.frame(cbind("Method" = rep(c("A","B"), each = 3),
"Sub" = rep(c("A1", "A2", "A3"), times = 2),
"Value1" = c(2, 3, NA, 4, 2, 3),
"Value2" = c(1, 2, NA, 2, 3, 3),
"Value3" = c(2, 2, 3, 1, 2, 2)))
df %>%
group_by(Method) %>%
mutate(across(c(Value1, Value2),
~case_when(is.na(.x) & Method == "A" & Sub == "A3" ~ .x[which(Sub == "A2")],
TRUE ~ .x)))
#> # A tibble: 6 × 5
#> # Groups: Method [2]
#> Method Sub Value1 Value2 Value3
#> <chr> <chr> <chr> <chr> <chr>
#> 1 A A1 2 1 2
#> 2 A A2 3 2 2
#> 3 A A3 3 2 3
#> 4 B A1 4 2 1
#> 5 B A2 2 3 2
#> 6 B A3 3 3 2
由 reprex package (v2.0.1)
于 2022-05-20 创建使用coalesce
的另一个解决方案:
library(dplyr)
df <- data.frame(cbind("Method" = rep(c("A","B"), each = 3),
"Sub" = rep(c("A1", "A2", "A3"), times = 2),
"Value1" = c(2, 3, NA, 4, 2, 3),
"Value2" = c(1, 2, NA, 2, 3, 3),
"Value3" = c(2, 2, 3, 1, 2, 2)))
df <- df %>%
dplyr::mutate(dplyr::across(Value1:Value2, ~dplyr::coalesce(.x, .x[Method == "A" & Sub == "A2"])))
df
#> Method Sub Value1 Value2 Value3
#> 1 A A1 2 1 2
#> 2 A A2 3 2 2
#> 3 A A3 3 2 3
#> 4 B A1 4 2 1
#> 5 B A2 2 3 2
#> 6 B A3 3 3 2
Created on 2022-05-20 by the reprex package (v2.0.1)