使用dplyr为组内的不同值分配唯一ID
问题:我需要为具有两级分组的数据创建一个唯一的ID字段。在这里的示例代码中,它是使用dplyr为组内的不同值分配唯一ID,r,dplyr,R,Dplyr,问题:我需要为具有两级分组的数据创建一个唯一的ID字段。在这里的示例代码中,它是Emp和Color。ID的结构需要如下所示: Emp+每个颜色的唯一编号+重复颜色的序列号 这些值由句点分隔。 示例数据: dat <- data.frame(Emp = c("A","A","A","B","B","C"), Color = c("Red","Green","Green","Orange","Yellow","Brown"), stri
Emp
和Color
。ID的结构需要如下所示:
Emp
+每个颜色的唯一编号
+重复颜色的序列号
这些值由句点分隔。示例数据:
dat <- data.frame(Emp = c("A","A","A","B","B","C"),
Color = c("Red","Green","Green","Orange","Yellow","Brown"),
stringsAsFactors = FALSE)
但我无法为每个Emp
组中唯一出现的Color
分配序列号
我更喜欢dplyr解决方案,但任何方法都将不胜感激。我们可以试试
dat %>%
group_by(Emp) %>%
mutate(temp = match(Color, unique(Color)),
temp2 = duplicated(Color)+1,
ID = sprintf("%s.%02d.%03d", Emp, temp, temp2))%>%
select(-temp, -temp2)
# Emp Color ID
# <chr> <chr> <chr>
#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%>%
分组依据(Emp)%>%
变异(温度=匹配(颜色、唯一(颜色)),
temp2=复制(颜色)+1,
ID=sprintf(“%s.%02d.%03d”,Emp,temp,temp2))%>%
选择(-temp,-temp2)
#Emp颜色ID
#
#1 A红色A.01.001
#2 A绿色A.02.001
#3 A绿色A.02.002
#4 B橙色B.01.001
#5B黄色B.02.001
#6 C棕色C.01.001
使用数据。表
和sprintf
:
library(data.table)
setDT(dat)[, ID := sprintf('%s.%02d.%03d',
Emp, rleid(Color), rowid(rleid(Color))),
by = Emp]
你会得到:
> 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
工作原理:
- 使用
setDT()
- 分组依据
Emp
- 并使用
-函数创建sprintf
-变量。使用ID
可以根据指定的格式轻松地将多个向量粘贴在一起sprintf
- 使用
意味着:=
通过引用更新数据表
表示字符串将用于第一部分(即%s
)<代码>%02d&Emp
表示一个数字在需要时需要有两个或三个带前导零的数字。中间的点将被照字面理解,从而包含在结果字符串中%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]
这也将保持颜色
列的显示顺序。您也可以使用match(Color,unique(Color))
来代替.integer(factor(Color,levels=unique(Color)),如akrun所示
在更大的数据集上实现上述功能,以说明:
dat2 <- rbindlist(list(dat,dat))
dat2[, r := match(Color, unique(Color)), by = Emp
][, ID := sprintf('%s.%02d.%03d',
Emp, r, rowid(r)),
by = Emp]
如果“绿色”行不是连续的,这会失败吗?也许可以在那里的某个地方添加一个排序?谢谢Jaap和akrun的回答。我最终使用了data.table方法,但这两种方法都很有用,因为akrun的回答中提到了更正。谢谢你们两位!例如,当A组中有3个“绿色”时,第三个ID也将以
002
结尾。使用dat%%>%groupby(Emp)%%>%mutate(temp=match(Color,unique(Color))%%>%groupby(Color)%%>%mutate(temp2=row_number(),ID=sprintf(“%s.%02d.%03d”,Emp,temp,temp2))%%>%select(-temp,-temp2)
也考虑到了这一点。
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]
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