给出以下数据框:
df <- data.frame(patientID = rep(c(1:4), 3),
condition = c(rep("A", 4), rep("B",4), rep("C",4)),
weight = round(rnorm(12, 70, 7), 1),
height = round(c(rnorm(4, 170, 10), rep(0, 8)), 1))
> head(df)
patientID condition weight height
1 1 A 71.43 168.5
2 2 A 59.89 177.3
3 3 A 72.15 163.4
4 4 A 70.14 166.1
5 1 B 66.21 0.0
6 2 B 66.62 0.0
如何将每个患者的身高从条件A复制到另外两个条件?我尝试使用for循环,data.table和dplyr但没有成功。
如何使用这两种方法实现这一目标?
答案 0 :(得分:2)
如果您的数据看起来如此 - 按condition, patientID
排序,并且每个条件的患者相同,那么您可以按照以下方式使用回收:
require(data.table)
setDT(df)[, height := height[condition == "A"]]
但我明白那里有很多 ifs 。
因此,在没有假设数据的情况下,condition,patientID
对是唯一的一个例外,您可以这样做:
require(data.table)
setDT(df)[, height := height[condition == "A"], by=patientID]
再次,这使用回收,但在每个组内 - 因为它不假设数据是有序的。
以上两种方法对样本数据给出:
# patientID condition weight height
# 1: 1 A 73.3 169.5
# 2: 2 A 76.3 173.4
# 3: 3 A 63.6 145.5
# 4: 4 A 56.2 164.7
# 5: 1 B 67.7 169.5
# 6: 2 B 77.3 173.4
# 7: 3 B 76.8 145.5
# 8: 4 B 70.9 164.7
# 9: 1 C 76.6 169.5
# 10: 2 C 73.0 173.4
# 11: 3 C 66.7 145.5
# 12: 4 C 71.6 164.7
同样的想法也可以翻译为dplyr
,我会留给你试试。提示:它只需要group_by
和mutate
。
答案 1 :(得分:1)
这里不需要花哨的东西。只需使用$
运算符和[
子集。
> df$height <- df$height[df$patientID]
> df
patientID condition weight height
1 1 A 67.4 175.1
2 2 A 66.8 179.0
3 3 A 49.7 159.7
4 4 A 64.5 165.3
5 1 B 66.0 175.1
6 2 B 70.8 179.0
7 3 B 58.7 159.7
8 4 B 74.3 165.3
9 1 C 70.9 175.1
10 2 C 75.6 179.0
11 3 C 61.3 159.7
12 4 C 74.5 165.3
答案 2 :(得分:1)
这应该可以解决问题。它假设条件因子的第一级始终是具有真实数据的级别。
idx <- tapply(rownames(df), list(df$patientID, df$condition), identity)
idx<-na.omit(cbind(as.vector(idx[,-1]),as.vector(idx[,1])))
df[as.vector(idx[,1]),"height"] <- df[as.vector(idx[,2]), "height"]
来自@ Arun的建议
df$height<-with(df, ave(ifelse(condition=="A",height,-1),
factor(patientID), FUN=max))
您可以明确指出从
中提取值的条件级别