对于问题和错误的措辞,我深表歉意。 OS和R中的新手。
问题:找到效率的方式,用唯一填充另一列中具有相同值的观测值的数字填充列。 结果如下:
patient_number id
1 46 1
2 47 2
3 15 3
4 42 4
5 33 5
6 26 6
7 37 7
8 7 8
9 33 5
10 36 9
示例数据框
set.seed(42)
df <- data.frame(
patient_number = sample(seq(1, 50, 1), 100, replace = TRUE)
)
我能想到的
df$id <- NA ## create id and fill with NA make if statement easier
n_unique <- length(unique(df$patient_number)) ## how many unique obs
for (i in 1:nrow(df)) {
index_identical <- which(df$patient_number == df$patient_number[i])
## get index of obs with same patient_number
if (any(is.na(df$id[index_identical]))) {
## if any of the ids of obs with same patient number not filled in,
df$id[index_identical] <- setdiff(seq(1, n_unique, 1), df$id)[1]
## get a integer between 1 and the number of unique obs that is not used
}
else {
df$id <- df$id
}
}
它可以完成工作,但是要成千上万行,这需要时间。
感谢您的支持。
答案 0 :(得分:6)
如果您愿意接受其他软件包,则可以使用group_indices
软件包中的dplyr
函数:
library(dplyr)
df %>%
mutate(id = group_indices(., patient_number))
patient_number id
1 46 40
2 47 41
3 15 14
4 42 37
5 33 28
6 26 23
7 37 32
8 7 6
9 33 28
10 36 31
11 23 21
12 36 31
13 47 41
...
答案 1 :(得分:5)
我们可以使用.GRP
中的data.table
library(data.table)
setDT(df)[, id := .GRP, patient_number]
或者使用base R
match
和factor
选项也很快
df$id <- with(df, match(patient_number, unique(patient_number)))
df$id <- with(df, as.integer(factor(patient_number,
levels = unique(patient_number))))