条件语句引用单独的行

时间:2018-08-29 00:55:42

标签: r dplyr

<?xml version="1.0" encoding="UTF-8"?><test>helloWorld</test>

每个科目(substring-after(/soap:Envelope/soap:Body/BusinessResponse/BusinessResult,'?>') )都有不同类型的纵向考试(data.frame(id = rep(letters[1:2], each = 8), examID = as.character(c(11,11:17, 21:28)), baselineExam = c(rep(c(rbind('bl',c(11,14))), each = 2), c(rep('bl', 4), 21, 21, 24, 24)), examType = c("x", "x", "fu", "fu", "y", "z", "fu", "fu", "x", "x", "y", "z", "fu", "fu", "fu", "fu"), expected_col = c("x", "x", "x", "x", "y", "z", "y", "y", "x", "x", "y", "z", "x", "x", "z", "z")) # the first four columns are my original data frame # the last column shows the expected output. id examID baselineExam examType expected_col 1 a 11 bl x x 2 a 11 bl x x 3 a 12 11 fu x 4 a 13 11 fu x 5 a 14 bl y y 6 a 15 bl z z 7 a 16 14 fu y 8 a 17 14 fu y 9 b 21 bl x x 10 b 22 bl x x 11 b 23 bl y y 12 b 24 bl z z 13 b 25 21 fu x 14 b 26 21 fu x 15 b 27 24 fu z 16 b 28 24 fu z )。每次检查都有其唯一的标识符(examType)。仅基准考试包含考试类型的信息。 后续检查仅包含信息“ fu”,而不包含正确的examType。但是,id列显示了哪些是相应随访的基线检查。我想在每一行中有一列带有正确的examType。 (请参见数据框中的examID

我被困住了。我不能将baselineExam之类的东西与expected_col结合使用,因为没有可以用来区分这些考试的分组。

一种方法是获取相应“ fu”行的索引,在“ baselineExam”中查找该值,然后在“ examID”中查找该数字,以获取该行的examType

我尝试了一个带有索引号的辅助列(也必须有更好的方法),我可以在此行中获取基线检查的值-但我不知道如何有条件地在当(基线行的)examID ==(后续行的)extraExlineExam时的expressionType。

最好使用base R解决方案或dplyr,但可以开放使用


编辑

我更改了给定的数据,因为我以前的样本数据不能完全反映真实数据的复杂性(我简化了)。不幸的是,@www或@akrun的解决方案均无法正常工作-太糟糕了,因为我没有提供足够好的示例:( 每个考试ID可以有多行(长数据,在我的示例中为第1和2行),并且在进行后续考试之前,还要进行多次基础考试。

2 个答案:

答案 0 :(得分:4)

使用dplyrtidyr软件包的解决方案。关键是将fu替换为NA,然后使用fill函数用上一行填充NAmutate_if只是将因子列转换为字符列。 dat2是最终输出。

library(dplyr)
library(tidyr)

dat2 <- dat %>%
  mutate_if(is.factor, as.character) %>%
  mutate(type = ifelse(examType %in% "fu", NA, examType)) %>%
  fill(type)
dat2
#   id examID baselineExam examType type
# 1  a     11           bl        x    x
# 2  a     12           11       fu    x
# 3  a     13           bl        y    y
# 4  a     14           13       fu    y
# 5  b     21           bl        x    x
# 6  b     22           21       fu    x
# 7  b     23           bl        z    z
# 8  b     24           23       fu    z

更新

我们可以使用dplyr软件包来实现这一目标。首先,用已知的examType子集数据帧,找到idexamIDexamType之间具有唯一组合的行,将表连接到原始数据帧,并使用coalesce合并信息。

library(dplyr)

dat2 <- dat %>%
  filter(!examType %in% "fu") %>%
  distinct(id, examID, examType) %>%
  rename(Type = examType) %>%
  left_join(dat, ., by = c("id", "baselineExam" = "examID")) %>%
  mutate(Type = coalesce(Type, examType))

dat2
#    id examID baselineExam examType Type
# 1   a     11           bl        x    x
# 2   a     11           bl        x    x
# 3   a     12           11       fu    x
# 4   a     13           11       fu    x
# 5   a     14           bl        y    y
# 6   a     15           bl        z    z
# 7   a     16           14       fu    y
# 8   a     17           14       fu    y
# 9   b     21           bl        x    x
# 10  b     22           bl        x    x
# 11  b     23           bl        y    y
# 12  b     24           bl        z    z
# 13  b     25           21       fu    x
# 14  b     26           21       fu    x
# 15  b     27           24       fu    z
# 16  b     28           24       fu    z

更新示例的数据

dat <- data.frame(id = rep(letters[1:2], each  = 8), 
                  examID = as.character(c(11,11:17, 21:28)), 
                  baselineExam = c(rep(c(rbind('bl',c(11,14))), each = 2), c(rep('bl', 4), 21, 21, 24, 24)), 
                  examType = c("x", "x", "fu", "fu", "y", "z", "fu", "fu", "x", "x", "y", "z", "fu", "fu", "fu", "fu"),
                  stringsAsFactors = FALSE)

答案 1 :(得分:2)

一个选项是按'id'分组,并根据'bl'的出现创建分组变量,在'baselineExam'中将'type'创建为与'bl'相对应的'examType'

library(dplyr)
df1 %>% 
    group_by(id, grp = cumsum(baselineExam == 'bl')) %>% 
    mutate(type = examType[baselineExam == 'bl']) %>% 
    ungroup %>% 
    select(-grp)
# A tibble: 8 x 5
#  id    examID baselineExam examType type 
#  <fct> <fct>  <fct>        <fct>    <fct>
#1 a     11     bl           x        x    
#2 a     12     11           fu       x    
#3 a     13     bl           y        y    
#4 a     14     13           fu       y    
#5 b     21     bl           x        x    
#6 b     22     21           fu       x    
#7 b     23     bl           z        z    
#8 b     24     23           fu       z