在一个群组内创建ID的R语言实现方案

12

我有以下数据集:

df<-structure(list(IDFAM = c("2010 7599 2996 1", "2010 7599 3071 1", 
"2010 7599 3071 1", "2010 7599 3660 1", "2010 7599 4736 1", "2010 7599 6235 1", 
"2010 7599 6299 1", "2010 7599 9903 1", "2010 7599 11013 1", 
"2010 7599 11778 1", "2010 7599 11778 1", "2010 7599 12248 1", 
"2010 7599 13127 1", "2010 7599 14261 1", "2010 7599 16280 1", 
"2010 7599 16280 1", "2010 7599 16280 1", "2010 7599 16280 1", 
"2010 7599 16280 1", "2010 7599 17382 1"), AGED = c(45L, 47L, 
24L, 46L, 46L, 44L, 43L, 43L, 43L, 16L, 43L, 46L, 44L, 47L, 43L, 
16L, 20L, 18L, 18L, 43L)), .Names = c("IDFAM", "AGED"), row.names = c("5614", 
"5748", "5753", "6864", "8894", "11761", "11884", "18738", "20896", 
"22351", "22353", "23267", "24939", "27072", "30946", "30947", 
"30949", "30950", "30952", "33034"), class = "data.frame")

我希望为每个具有相同 IDFAM 值的观测分配一个从1到n的ID,其中n是具有相同 IDFAM 值的观测数量。这将导致以下表格:

IDFAM              AGED     ID
2010 7599 2996 1    45       1
2010 7599 3071 1    47       1
2010 7599 3071 1    24       2
2010 7599 3660 1    46       1
2010 7599 4736 1    46       1
2010 7599 6235 1    44       1
2010 7599 6299 1    43       1
2010 7599 9903 1    43       1
2010 7599 11013 1   43       1
2010 7599 11778 1   16       1
2010 7599 11778 1   43       2
2010 7599 12248 1   46       1
2010 7599 13127 1   44       1
2010 7599 14261 1   47       1
2010 7599 16280 1   43       1
2010 7599 16280 1   16       2
2010 7599 16280 1   20       3
2010 7599 16280 1   18       4
2010 7599 16280 1   18       5
2010 7599 17382 1   43       1

我该怎么做?谢谢。

2个回答

25

有几种方法。

在基本的 R 中,可以使用 ave

with(df, ave(rep(1, nrow(df)), IDFAM, FUN = seq_along))
#  [1] 1 1 2 1 1 1 1 1 1 1 2 1 1 1 1 2 3 4 5 1

使用 "data.table" 包,使用 sequence(.N)
library(data.table)
DT <- as.data.table(df)
DT[, ID := sequence(.N), by = IDFAM]

使用 "dplyr" 软件包,尝试:

df %>% group_by(IDFAM) %>% mutate(count = sequence(n()))

或者(如哈德利在评论中建议的):
df %>% group_by(IDFAM) %>% mutate(count = row_number(IDFAM))

更新

鉴于这似乎是一个比较常见的需求,该功能已被添加到我的 "splitstackshape" 包中作为一个函数 (getanID)。它基于上面介绍的 "data.table" 方法。

library(splitstackshape)
getanID(df, id.vars = "IDFAM")
#                 IDFAM AGED .id
#  1:  2010 7599 2996 1   45   1
#  2:  2010 7599 3071 1   47   1
#  3:  2010 7599 3071 1   24   2
#  4:  2010 7599 3660 1   46   1
#  5:  2010 7599 4736 1   46   1
#  6:  2010 7599 6235 1   44   1
#  7:  2010 7599 6299 1   43   1
#  8:  2010 7599 9903 1   43   1
#  9: 2010 7599 11013 1   43   1
# 10: 2010 7599 11778 1   16   1
# 11: 2010 7599 11778 1   43   2
# 12: 2010 7599 12248 1   46   1
# 13: 2010 7599 13127 1   44   1
# 14: 2010 7599 14261 1   47   1
# 15: 2010 7599 16280 1   43   1
# 16: 2010 7599 16280 1   16   2
# 17: 2010 7599 16280 1   20   3
# 18: 2010 7599 16280 1   18   4
# 19: 2010 7599 16280 1   18   5
# 20: 2010 7599 17382 1   43   1

谢谢,我特别喜欢with/ave方法。简单而高效。 - user2568648
2
最好在dplyr中使用row_number() - hadley
1
是的,没错。在 dplyr 0.2 版本中,你可以直接使用它 count = row_number() - hadley
@hadley,谢谢您的信息。 - A5C1D2H2I1M1N2O1R2T1
使用 seq_len(.N) 和 sequence(.N) 有什么区别? - skan
显示剩余3条评论

4

使用dplyr 0.5,您可以使用group_indices函数。虽然它不支持mutate,但以下方法很简单:

df$id <- df %>% group_indices(IDFAM)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接