我有一个如下数据框:
> df
pat_id disease
[1,] "pat1" "dis1"
[2,] "pat1" "dis1"
[3,] "pat2" "dis0"
[4,] "pat2" "dis5"
[5,] "pat3" "dis2"
[6,] "pat3" "dis2"
如何编写一个函数来获取第三个变量,该变量指示同一个pat_id,疾病变量是否相同,如下所示?
> df
pat_id disease var3
[1,] "pat1" "dis1" "1"
[2,] "pat1" "dis1" "1"
[3,] "pat2" "dis0" "0"
[4,] "pat2" "dis5" "0"
[5,] "pat3" "dis2" "1"
[6,] "pat3" "dis2" "1"
答案 0 :(得分:5)
尝试any(duplicated())
进行分组,并使用as.integer()
将cbind()
的结果换行。然后与cbind(
df,
var3 = ave(df[,2], df[,1], FUN = function(x) as.integer(any(duplicated(x)))
)
# pat_id disease var3
# [1,] "pat1" "dis1" "1"
# [2,] "pat1" "dis1" "1"
# [3,] "pat2" "dis0" "0"
# [4,] "pat2" "dis5" "0"
# [5,] "pat3" "dis2" "1"
# [6,] "pat3" "dis2" "1"
绑定。虽然我可能会建议你在这里使用数据框而不是矩阵。
library(data.table)
dt <- as.data.table(df)
dt[, var3 := if(any(duplicated(disease))) 1 else 0, by = pat_id]
对于较大的数据,我建议转换为数据表。语法实际上也更好一些,而且可能会更快。
pat_id disease var3
1: pat1 dis1 1
2: pat1 dis1 1
3: pat2 dis0 0
4: pat2 dis5 0
5: pat3 dis2 1
6: pat3 dis2 1
给出了
as.integer(any(duplicated(disease)))
其中列类更合适(char,char,int)。或者您可以使用if
代替else
/ {{1}}。
答案 1 :(得分:0)
稍微啰嗦,但是给你一个布尔第三个变量,它更容易测试。它也不关心数据类型
> df <- data.frame(pat_id=c("pat1","pat1", "pat2", "pat2", "pat3", "pat3"),
+ disease=c("dis1","dis1","dis0","dis5","dis2","dis2"),
+ stringsAsFactors = F)
> counts<-apply(table(df), 1, function(x) sum(x!=0))
> df2<-data.frame(pat_id=names(counts), all_the_same=(counts==1))
> df3<-merge(df,df2)
> df3
pat_id disease all_the_same
1 pat1 dis1 TRUE
2 pat1 dis1 TRUE
3 pat2 dis0 FALSE
4 pat2 dis5 FALSE
5 pat3 dis2 TRUE
6 pat3 dis2 TRUE
> sapply(df3, class)
pat_id disease all_the_same
"character" "character" "logical"
这并不关心你拥有的每种组合中有多少,应该把你的字符串留作字符串 - 而不是因素。
将新列作为逻辑使您可以更轻松地进行查询,例如查找所有患者的查询
> unique(df3$pat_id[df3$all_the_same])
[1] "pat1" "pat3"
答案 2 :(得分:0)
使用dplyr
library(dplyr)
as.data.frame(df) %>%
group_by(pat_id) %>%
mutate(var3 = as.integer(n_distinct(disease)==1))
# pat_id disease var3
# (chr) (chr) (int)
#1 pat1 dis1 1
#2 pat1 dis1 1
#3 pat2 dis0 0
#4 pat2 dis5 0
#5 pat3 dis2 1
#6 pat3 dis2 1