Find patient ID at least appears two time and more
本问题已经有最佳答案,请猛点这里访问。
1
|
df<-data.frame(PATIENT_ID=c(1,1,2,3,3,3,4,5,5,5,5,5))
|
我要查找已记录至少 2 次的患者 ID。
输出应该是:
1
|
df_output<-data.frame(PATIENT_ID=c(1,3,5))
|
谢谢。
又一个dplyr解决方案
1
2 3 |
df %>%
group_by(PATIENT_ID) %>% filter(n() > 1 & row_number() == 1) |
和data.table。 (我更喜欢在这里使用 .SD-logic,但是 data.table#3262 仍然是打开的,并且您的示例数据没有其他列。它不会快多少,但如果数据明显更大。)
1
2 3 4 5 6 7 |
library(data.table)
DT <- as.data.table(df) DT[, .(n=.N),by=PATIENT_ID][n>1,][,n:=NULL][] # PATIENT_ID # 1: 1 # 2: 3 # 3: 5 |
如果您的数据比样本大,这些基准会改变,但可能会以相同的比例发生变化:user31264\\ 的答案几乎肯定是最快的,而更复杂的 dplyr 管道可能会保留它们的相对表现。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
microbenchmark::microbenchmark(
user = { a = rle(df$PATIENT_ID) data.frame(PATIENT_ID=a$values[a$lengths>1]) }, user_sort = { a = rle(sort(df$PATIENT_ID)) data.frame(PATIENT_ID=a$values[a$lengths>1]) }, r2a = df %>% group_by(PATIENT_ID) %>% filter(n() > 1 & row_number() == 1) %>% ungroup(), r2b = DT[, .(n=.N),by=PATIENT_ID][n>1,][,n:=NULL], csg = df %>% group_by(PATIENT_ID) %>% summarize(n = n()) %>% filter(n >= 2) %>% select(PATIENT_ID), duck = df %>% group_by(PATIENT_ID) %>% mutate(N=n()) %>% filter(N>=2) %>% select(-N) %>% filter(!duplicated(PATIENT_ID)) ) # Unit: microseconds # expr min lq mean median uq max neval # user 116.2 138.55 168.536 167.30 180.30 366.2 100 # user_sort 160.1 184.55 238.249 224.60 255.60 464.3 100 # r2a 3018.4 3399.60 4020.076 3839.70 4202.95 12193.5 100 # r2b 2094.6 2945.30 3367.188 3277.80 3838.35 5183.8 100 # csg 5382.5 6262.20 6708.582 6670.90 6992.80 9078.2 100 # duck 7538.3 8568.55 9275.720 8928.65 9420.20 16678.5 100 |
另一个 dplyr 解决方案,使用 summarize 而不是 mutate 然后 filter 的组合。首先,我们按变量分组,我们计算每组有多少个观察值,然后仅在有两个或多个观察值时才保留。最后一步只保留感兴趣的变量(删除新的 n 列)
1
2 3 4 5 6 |
library(dplyr)
df %>% group_by(PATIENT_ID) %>% summarize(n = n()) %>% filter(n >= 2) %>% select(PATIENT_ID) |
1
2 |
a = rle(df$PATIENT_ID)
df_output=data.frame(PATIENT_ID=a$val[a$len>1]) |
如果df未排序,第一行应该是a = rle(sort(df$PATIEND_ID))
- 虽然这给出了所需的输出,但有两件事(也许可以解释否决?):(1)属性名称的部分匹配可能会对某些用户产生警告(次要); (2) PATIEND 中的错字。我认为这是最简单的(也是base-R)。
试试这个:
1
2 3 4 5 6 7 8 9 10 11 12 |
library(dplyr)
df %>% group_by(PATIENT_ID) %>% mutate(N=n()) %>% # A tibble: 3 x 1 |
- 如果您使用 tally() 而不是 mutate,则不必使用 filter(!dup…,因为它会自动减少。您可以使用 df %>% group_by(PATIENT_ID) %>% filter(n() > 1 & row_number() == 1) 进一步简化它。
- @r2evans 是的,这是一种非常理想的方式!
来源:https://www.codenong.com/63135296/