簡體   English   中英

使用dplyr將唯一ID分配給Group中的不同值

[英]Assign unique ID to distinct values within Group with dplyr

問題:我需要為具有兩個分組級別的數據創建唯一的ID字段。 在此處的示例代碼中,它是EmpColor 該ID的結構應為:

Emp +每個Color唯一編號+重復Colors序號。

這些值由句點分隔。
示例數據:

dat <- data.frame(Emp = c("A","A","A","B","B","C"), 
              Color = c("Red","Green","Green","Orange","Yellow","Brown"),
              stringsAsFactors = FALSE)

該ID應該顯示為:

ID <- c("A.01.001", "A.02.001", "A.02.002", "B.01.001", "B.02.001", "C.01.001")

ID [1]“ A.01.001”“ A.02.001”“ A.02.002”“ B.01.001”“ B.02.001”“ C.01.001”

ID的三個字符后綴來記錄重復項,可以這樣完成:

 group_by(dat, Emp, Color) %>%
         mutate(suffix = str_pad(row_number(), width=3, side="left", pad="0"))

但是我無法為每個Emp組分配連續編號給Color的唯一出現。

我更喜歡dplyr解決方案,但是任何方法都將不勝感激。

使用data.tablesprintf

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()dat轉換為data.table
  • Emp分組。
  • 並使用sprintf函數創建ID變量。 使用sprintf您可以根據指定的格式輕松地將多個矢量粘貼在一起。
  • :=的使用意味着data.table通過引用進行更新。
  • %s指示在第一部分(即Emp )中使用字符串。 %02d%03d表示數字需要在需要時由兩位或三位數字和前導零組成。 中間的點將按字面意義使用,因此包含在結果字符串中。

處理@jsta的注釋,如果Color -column中的值不是連續的,則可以使用:

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)) ,如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]

讓您:

> 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

我們可以試試

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM