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
) (id
)。每个考试都有其唯一标识符(examID
)。只有基线检查包含Examtype的信息。后续考试只包含“fu”信息,而不包含正确的examType。但是,baselineExam
列显示了相应后续的基线检查。我希望在每一行中都有一个具有正确examType的列。(请参阅数据框架中的expected_col
)
我被卡住了。我不能结合使用像if(baselineExam %in% examID)
和any
这样的东西,因为没有一个组可以将这些考试分开。
一种方法是获取相应“fu”行的索引,查找“baselineExam”中的哪个值,然后在“examID”中查找这个数字,以获得该行的examType。
我尝试了一个带有索引号的助手列(肯定也有更好的方法),并且我可以获得此行中基线检查的值--但我不知道如何在examType中有条件地获得值,而此时examID (基线行) == baselineExam (后续行)。
基本R解决方案或dplyr优先,但开放的任何东西
编辑
我更改了给定的数据,因为我以前的示例数据没有完全反映真实数据的复杂性(我对其进行了过度简化)。不幸的是,无论是@www还是@akrun的解决方案都没有奏效--这是我的错,因为我没有提供足够好的示例:(在我的示例中,每个考试ID可以有多行(在我的示例中是长数据,第1行和第2行),在进行后续考试之前,还需要进行多个基线检查。
发布于 2018-08-29 01:17:51
使用dplyr
和tidyr
包的解决方案。关键是将fu
替换为NA
,然后使用fill
函数填充上一行的NA
。mutate_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
对数据框架进行子集,找到id
、examID
和examType
之间唯一组合的行,将表连接到原始数据框架,并使用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)
发布于 2018-08-29 01:19:56
一种选择是按“id”进行分组,并根据“bl”的出现创建一个分组变量,将“type”创建为“examType”,该类型对应于“baselineExam”中的“bl”。
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
https://stackoverflow.com/questions/52068053
复制相似问题