我有一个数据集,其中包括来自不同患者的多个患者记录。我还有一个函数,我想让它遍历每个独特的患者,并检查在时间点1,治疗1是否等于治疗2。它正在运行,但它只给我结果的病人谁只有一个记录。我希望把它作为一个循环保存在函数中,因为我还有更多的检查需要添加,一旦我通过了这个。所以如果有人能帮我修改这个循环,看看为什么它不能给我每个病人的结果,我会非常感激。
df <- data.frame(
Patient = c('Dave', 'Dave', 'Dave', "Angel", "Angel", "Angel", "Joe", "Joe", "Joe", "Cara"),
V1 = c(1, 150, 375, 1, 150, 375, 1, 150, 375, 1),
V2 = c(150, 375,568,150, 375, 568, 150, 375, 568, 375),
R1 = c("Disease","Response","Response", "Disease","Disease", "Response","Disease", "Response", "Response", "Disease"),
R2 = c("Response", "Response", "Death", "Disease", "Response", "Death", "Response", "Response", "Response", "Disease"),
T1 = c("A","A", "B", "A","B","B", "A","A","C", "A"),
T2 = c("A", "B","B", "B","B","B", "A","C","C" , "A"))
Time <- function(id) {
subset_df <- df[df$Patient == id, ]
start <- NULL
end <- NULL
for (i in 1:nrow(subset_df)) {
if (subset_df$V1[i] == 1 && subset_df$T1[i] == subset_df$T2[i]) {
start <- subset_df$V2[i]
} else {
start <- "Never Responded"
}
}
return(start)
}
ids <- unique(df$Patient)
times <- lapply(ids, Time)
在我的职能中,我已经写了,如果在访视1(V1)时,治疗1(T1)等于治疗2(T2),那么我希望它记录相应的访视2(V2)编号(以天为单位)。如果两种治疗在访视1时不相等(否则),则write从未回复。因此,当我运行这个函数时,它只返回CaraV2,而它还应该返回Dave和Joe,并说Never Responded for Angel。
1条答案
按热度按时间q35jwt9p1#
您犯了一个典型的初学者循环错误-在您的循环中,您每次都重新定义
start
,而没有“记住”最后一次迭代。当i = 1
时,可以设置start <- 150
。但是当i = 2
执行start <- "Never Responded"
时,旧的start <- 150
将永远消失。坏的解决方案是每次都连接,使
start
“增长”:start <- c(start, subset_df$V2[i])
等这很糟糕,因为对象的生长速度非常慢。即使有几百次迭代,这也将开始花费明显的时间。稍微好一点的解决方案是从一开始就将
start
初始化为正确的长度:执行start <- rep(NA, nrow(subset_df))
,而不是start <- NULL
。然后,您可以指定正确的位置start[i] <- ...
。这避免了增长对象的性能缺陷,但它没有利用R的向量化。更好的解决方案是完全跳过循环并向量化:
(Note你不能在同一个向量中混合数字类和字符类,所以使用
NA
比“Never responsed”更好,因为你是在混合数字类。这样做,你也可以意识到,没有什么“按组”-整个事情都是“按行”,所以你根本不需要
lapply
,你可以在整个数据上一次完成这一切: