简体   繁体   English

有条件地用不同行的值填充单元格

[英]Conditionally fill cells with values from different row

Suppose I have the following data frame:假设我有以下数据框:

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

Values for Value1 and Value2 will systematically show a missing value whenever Method == A and Sub == A3 .每当Method == ASub == A3时, Value1Value2的值将系统地显示缺失值。 I want these values to be replaced by those that appear at Method == A and Sub == A2 .我希望这些值被出现在Method == ASub == A2的值替换。 In this case, the desired output is在这种情况下,所需的 output 是

#   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

How can I achieve this?我怎样才能做到这一点? Note that in reality, my df is much more complex, with more columns and rows and more possible methods and values.请注意,实际上,我的 df 要复杂得多,有更多的列和行以及更多可能的方法和值。 I tried playing around with for loops, but perhaps there is a more efficient way (eg, using dplyr).我尝试使用 for 循环,但也许有更有效的方法(例如,使用 dplyr)。

Thank you in advance!先感谢您!

How about this:这个怎么样:

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

Created on 2022-05-20 by the reprex package (v2.0.1)reprex package (v2.0.1) 创建于 2022-05-20

Another solution using coalesce :另一个使用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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM