R 从id组中的非唯一名称创建唯一名称

R 从id组中的非唯一名称创建唯一名称,r,dplyr,R,Dplyr,在id中,我的数据有多个非唯一的名称标签。我想创建第三列,这样非唯一名称的末尾就可以粘贴一个字母来创建唯一的名称 dat <- structure(list(id = c("172262", "172262", "172262", "172262", "172504", "172504", "172504", "172507", "172507", "172507"), name = c("Fam", "Fam", "Fam", "CM_fam", "CBT_Fam", "CB

在id中,我的数据有多个非唯一的名称标签。我想创建第三列,这样非唯一名称的末尾就可以粘贴一个字母来创建唯一的名称

dat <- structure(list(id = c("172262", "172262", "172262", "172262", 
"172504", "172504", "172504", "172507", "172507", "172507"), 
    name = c("Fam", "Fam", "Fam", "CM_fam", "CBT_Fam", "CBT_Fam", 
    "CBT_Fam", "TAU", "CBT_Educ", "CBT_MI")), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -10L))

您可以将
粘贴
sprintf
字母
一起使用

dat %>% group_by(id, name) %>% mutate(uname = 
  if (n() > 1) sprintf("%s_%s", name, letters[row_number()]) 
  else name
)

# A tibble: 10 x 3
# Groups:   id, name [6]
   id     name     uname    
   <chr>  <chr>    <chr>    
 1 172262 Fam      Fam_a    
 2 172262 Fam      Fam_b    
 3 172262 Fam      Fam_c    
 4 172262 CM_fam   CM_fam   
 5 172504 CBT_Fam  CBT_Fam_a
 6 172504 CBT_Fam  CBT_Fam_b
 7 172504 CBT_Fam  CBT_Fam_c
 8 172507 TAU      TAU      
 9 172507 CBT_Educ CBT_Educ 
10 172507 CBT_MI   CBT_MI   
dat%>%group\u by(id,name)%>%mutate(uname=
如果(n()>1)sprintf(“%s\u%s”,名称,字母[行号())
别称
)
#一个tibble:10x3
#组:id,名称[6]
id名称uname
1172262个家庭
2172262法姆法姆布
3172262家庭委员会
4172262公分/公分/公分/公分
5172504家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用
6 172504 CBT_Fam CBT_Fam_b
7 172504 CBT_Fam CBT_Fam_c
8172507头
9 172507 CBT_教育CBT_教育
10172507立方英尺/平方米立方英尺/平方米

对于tidyverse(dplyr所属)中的其他字符串操作,请参见stringr和glue。

另一种可能性是:

 dat %>%
 group_by(id, name) %>%
 mutate(unique_name = if(n() > 1) paste(name, letters[1:length(name)], sep = "_") else name)

   id     name     unique_name
   <chr>  <chr>    <chr>      
 1 172262 Fam      Fam_a      
 2 172262 Fam      Fam_b      
 3 172262 Fam      Fam_c      
 4 172262 CM_fam   CM_fam     
 5 172504 CBT_Fam  CBT_Fam_a  
 6 172504 CBT_Fam  CBT_Fam_b  
 7 172504 CBT_Fam  CBT_Fam_c  
 8 172507 TAU      TAU        
 9 172507 CBT_Educ CBT_Educ   
10 172507 CBT_MI   CBT_MI 
或者使用
seq_along()
代替
n()

或者使用
gl()
生成字母的稍微不同的方法:

dat %>%
 group_by(id, name) %>%
 mutate(unique_name = if(n() > 1) paste(name, gl(length(name), 1, n(), letters), sep = "_") else name) 

   id     name     unique_name
   <chr>  <chr>    <chr>      
 1 172262 Fam      Fam_a      
 2 172262 Fam      Fam_b      
 3 172262 Fam      Fam_c      
 4 172262 CM_fam   CM_fam     
 5 172504 CBT_Fam  CBT_Fam_a  
 6 172504 CBT_Fam  CBT_Fam_b  
 7 172504 CBT_Fam  CBT_Fam_c  
 8 172507 TAU      TAU        
 9 172507 CBT_Educ CBT_Educ   
10 172507 CBT_MI   CBT_MI 
或:


您可以使用
ave
(基本
R

转换(dat,唯一名称=
ave(名称,名称,乐趣=功能(x){

如果((l)只是为了带来一些数据。这里的表格风格:

library(data.table)
DT <- as.data.table(dat)
DT[, unique_name := if (.N > 1) paste(name, letters[1:.N], sep = "_") 
                    else name, 
   by = .(id, name)]
库(data.table)
DT 1)粘贴(名称,字母[1:.N],sep=“389;”)
其他名称,
by=(id,name)]

但是,正如其他人指出的,您可能需要替换
字母[1:.N]
只需
1:.N
以防您有26个以上的重复名称。

这里有很多选项可供选择,但如果您正在寻找一个相当简单的管道,并且可以使用不同格式的输出,您可以使用基本R:

library(dplyr)

dat %>% 
  group_by(id, name) %>% 
  mutate(unique_name = make.unique(name))
这将产生:

   id     name     unique_name
   <chr>  <chr>    <chr>      
 1 172262 Fam      Fam        
 2 172262 Fam      Fam.1      
 3 172262 Fam      Fam.2      
 4 172262 CM_fam   CM_fam     
 5 172504 CBT_Fam  CBT_Fam    
 6 172504 CBT_Fam  CBT_Fam.1  
 7 172504 CBT_Fam  CBT_Fam.2  
 8 172507 TAU      TAU        
 9 172507 CBT_Educ CBT_Educ   
10 172507 CBT_MI   CBT_MI 
id名称唯一\u名称
1172262家
2 172262家庭1
3172262家庭2
4172262公分/公分/公分/公分
5172504家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用家庭用
6 172504 CBT_Fam CBT_Fam.1
7 172504 CBT_Fam CBT_Fam.2
8172507头
9 172507 CBT_教育CBT_教育
10172507立方英尺/平方米立方英尺/平方米
dat %>%
 group_by(id, name) %>%
 mutate(unique_name = if(length(name) > 1) paste(name, gl(length(name), 1, n(), letters), sep = "_") else name)
dat %>%
 group_by(id, name) %>%
 mutate(unique_name = if(any(seq_along(name) != 1)) paste(name, gl(length(name), 1, n(), letters), sep = "_") else name)
transform(dat, unique_name = 
            ave(name,name, FUN = function(x) {
              if((l <- length(x)) == 1) x
              else paste0(x,"_",letters[seq(l)])
            }))
#        id     name unique_name
# 1  172262      Fam       Fam_a
# 2  172262      Fam       Fam_b
# 3  172262      Fam       Fam_c
# 4  172262   CM_fam      CM_fam
# 5  172504  CBT_Fam   CBT_Fam_a
# 6  172504  CBT_Fam   CBT_Fam_b
# 7  172504  CBT_Fam   CBT_Fam_c
# 8  172507      TAU         TAU
# 9  172507 CBT_Educ    CBT_Educ
# 10 172507   CBT_MI      CBT_MI
dat$unique_name <- chartr(
  make.unique(dat$name,sep="_"),old="123456789",new="abcdefghi")
dat
# # A tibble: 10 x 3
#        id     name unique_name
#     <chr>    <chr>       <chr>
#  1 172262      Fam         Fam
#  2 172262      Fam       Fam_a
#  3 172262      Fam       Fam_b
#  4 172262   CM_fam      CM_fam
#  5 172504  CBT_Fam     CBT_Fam
#  6 172504  CBT_Fam   CBT_Fam_a
#  7 172504  CBT_Fam   CBT_Fam_b
#  8 172507      TAU         TAU
#  9 172507 CBT_Educ    CBT_Educ
# 10 172507   CBT_MI      CBT_MI
library(data.table)
DT <- as.data.table(dat)
DT[, unique_name := if (.N > 1) paste(name, letters[1:.N], sep = "_") 
                    else name, 
   by = .(id, name)]
library(dplyr)

dat %>% 
  group_by(id, name) %>% 
  mutate(unique_name = make.unique(name))
   id     name     unique_name
   <chr>  <chr>    <chr>      
 1 172262 Fam      Fam        
 2 172262 Fam      Fam.1      
 3 172262 Fam      Fam.2      
 4 172262 CM_fam   CM_fam     
 5 172504 CBT_Fam  CBT_Fam    
 6 172504 CBT_Fam  CBT_Fam.1  
 7 172504 CBT_Fam  CBT_Fam.2  
 8 172507 TAU      TAU        
 9 172507 CBT_Educ CBT_Educ   
10 172507 CBT_MI   CBT_MI