Using data.table
and sprintf
:
library(data.table)
setDT(dat)[, ID := sprintf('%s.%02d.%03d',
Emp, rleid(Color), rowid(rleid(Color))),
by = Emp]
you get:
> dat
Emp Color ID
1: A Red A.01.001
2: A Green A.02.001
3: A Green A.02.002
4: B Orange B.01.001
5: B Yellow B.02.001
6: C Brown C.01.001
这是如何运作的:
- 你转换
dat
to a data.table
with setDT()
- 通过...分组
Emp
.
- 并创建
ID
- 变量与sprintf
-功能。和sprintf
您可以根据指定的格式轻松地将多个矢量粘贴在一起。
- 指某东西的用途
:=
意味着data.table
通过引用更新。
-
%s
表示在第一部分中使用一个字符串(即Emp
). %02d
& %03d
表示数字需要有两位或三位数字,并在需要时带前导零。之间的点将按字面意思理解,因此包含在结果字符串中。
解决@jsta的评论,如果Color
-列不是连续的,您可以使用:
setDT(dat)[, r := as.integer(factor(Color, levels = unique(Color))), by = Emp
][, ID := sprintf('%s.%02d.%03d',
Emp, r, rowid(r)),
by = Emp][, r:= NULL]
这也将保持顺序Color
列提出。代替as.integer(factor(Color, levels = unique(Color)))
你也可以使用match(Color, unique(Color))
如阿克伦所示。
在更大一点的数据集上实现上述内容来说明:
dat2 <- rbindlist(list(dat,dat))
dat2[, r := match(Color, unique(Color)), by = Emp
][, ID := sprintf('%s.%02d.%03d',
Emp, r, rowid(r)),
by = Emp]
让你:
> dat2
Emp Color r ID
1: A Red 1 A.01.001
2: A Green 2 A.02.001
3: A Green 2 A.02.002
4: B Orange 1 B.01.001
5: B Yellow 2 B.02.001
6: C Brown 1 C.01.001
7: A Red 1 A.01.002
8: A Green 2 A.02.003
9: A Green 2 A.02.004
10: B Orange 1 B.01.002
11: B Yellow 2 B.02.002
12: C Brown 1 C.01.002