【问题标题】:Conditionally impute values in a group based on existing values in R根据 R 中的现有值有条件地估算组中的值
【发布时间】:2020-11-19 14:12:50
【问题描述】:

对我的数据进行分组后,我想根据一个或多个现有值在两个方向上估算一列的值。我有以下数据:

id   inw    test    found
001    0       1     <NA>
001    1       2     <NA>
001    1       3       No
001    1       4       No
002    1       1       No
002    0       2     <NA>
002    1       3      Yes
002    1       4       No
003    1       1      Yes
003    1       2      Yes
003    1       3       No
003    0       4     <NA>

数据按 id 分组,而 found 列在此处存在问题。本质上,如果组中出现“否”值,则所有先前的值都应更改为“否”。如果出现“是”,则所有后续值都应更改为“是”。

因此,最终的结果应该是这样的:

id   inw    test    found
001    0       1       No
001    1       2       No
001    1       3       No
001    1       4       No
002    1       1       No
002    0       2     <NA>
002    1       3      Yes
002    1       4      Yes
003    1       1      Yes
003    1       2      Yes
003    1       3      Yes
003    0       4      Yes

至关重要的是,如果在它之后的任何地方都没有“否”值,或者在组内它之前的任何地方都没有“是”值,则 NA 可以保留(在上面的组 id == 002 中突出显示)。

任何帮助将不胜感激!

谢谢, 迪伦

【问题讨论】:

  • 虽然已经解决了,但是请告诉我yes, no, yes, no应该转换成什么序列?是的,是的,是的,是的,或者是的,不是的,是的,是的。我的意思是问规则的优先级。

标签: r dplyr


【解决方案1】:

这样的?

library(dplyr)

fill_na <- function(x) {
  if (length(first_yes <- head(which(x == "Yes"), 1L)) > 0L)
    x[seq.int(first_yes, length(x), 1L)] <- "Yes"
  if (length(last_no <- tail(which(x == "No"), 1L)) > 0L)
    x[seq.int(1L, last_no, 1L)] <- "No"
  x
}

df %>% group_by(id) %>% mutate(found = fill_na(found))

输出

# A tibble: 12 x 4
# Groups:   id [3]
   id      inw  test found
   <chr> <dbl> <dbl> <chr>
 1 001       0     1 No   
 2 001       1     2 No   
 3 001       1     3 No   
 4 001       1     4 No   
 5 002       1     1 No   
 6 002       0     2 NA   
 7 002       1     3 Yes  
 8 002       1     4 Yes  
 9 003       1     1 Yes  
10 003       1     2 Yes  
11 003       1     3 Yes  
12 003       0     4 Yes 

【讨论】:

  • 非常感谢ekoam!这正是我所需要的!完美的解决方案,非常感谢!
【解决方案2】:

我提出的解决方案不需要创建任何用户定义的函数

library(tidyverse)

df %>% group_by(id) %>%
  mutate(dummy_id = row_number(), #Not sure that there are gaps between test column, thus created one
         coln = ifelse(is.na(first(which(found == 'No'))), 0, first(which(found == 'No'))),
         coly = ifelse(is.na(first(which(found == 'Yes'))), n()+1, first(which(found == 'Yes'))),
         found2 = ifelse(dummy_id >= coly, 'Yes', 
                         ifelse(dummy_id <= coln, 'No', found))) %>%
  select(-dummy_id, -coln, -coly) %>%
  ungroup()

# A tibble: 12 x 5
      id   inw  test found found2
   <int> <int> <int> <chr> <chr> 
 1     1     0     1 NA    No    
 2     1     1     2 NA    No    
 3     1     1     3 No    No    
 4     1     1     4 No    No    
 5     2     1     1 No    No    
 6     2     0     2 NA    NA    
 7     2     1     3 Yes   Yes   
 8     2     1     4 No    Yes   
 9     3     1     1 Yes   Yes   
10     3     1     2 Yes   Yes   
11     3     1     3 No    Yes   
12     3     0     4 NA    Yes 

【讨论】:

    猜你喜欢
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 2023-02-09
    • 1970-01-01
    相关资源
    最近更新 更多