2 votes

Ajouter un identifiant unique par nom et date dans R

Je suis en train de faire du nettoyage/formatage de données et j'aimerais ajouter un identifiant unique à chaque enregistrement par nom et ensuite par date. Par exemple, "Bob" peut avoir quatre dates d'enregistrement, dont deux sont identiques. Dans ce cas, je souhaite lui attribuer trois numéros d'identification différents (séquentiels).

Voici ce qui se rapproche le plus du résultat souhaité :


Un exemple d'ensemble de données que j'ai créé :

tst <- data_frame(
  name = c("Bob", "Sam", "Roger", "Stacy", "Roger", "Roger", "Sam", "Bob", "Sam", "Stacy", "Bob", "Stacy", "Roger", "Bob"),
  date = as.Date(c("2009-07-03", "2010-08-12", "2009-07-03", "2016-04-01", "2002-01-03", "2019-02-10", "2005-04-17", "2009-07-03", "2010-09-21", "2012-11-12", "2015-12-31", "2014-10-10", "2015-06-02", "2003-08-21")),
  amount = round(runif(14, 0, 100), 2)
)

Générer un check_in_number variable...

tst2 <- tst %>%
  arrange(date) %>%
  group_by(name, date) %>%
  mutate(check_in_number = row_number())

La ligne ci-dessus génère check_in_number pour Bob en tant que 1 , 1 , 2 , 1 dans cet ordre. Je souhaiterais plutôt que le résultat soit 1 , 2 , 2 , 3 . En d'autres termes. J'aimerais que les enregistrements effectués à la même date soient considérés comme un seul enregistrement.

Est-ce possible avec tidyverse ? Ai-je oublié une méthode simple pour cela ?


Il y a une question similaire ici, mais je la laisse ici parce que le problème que j'avais impliquait une variable de date ordonnée sur laquelle j'arrangeais les données. En d'autres termes, mes données exigeaient que ma nouvelle variable soit consécutive.

Comment numéroter/étiqueter un tableau de données par numéro de groupe à partir de group_by ?

5voto

Calum You Points 8082

Vous avez besoin group_indices :

library(tidyverse)

tst <- tibble(
  name = c("Bob", "Sam", "Roger", "Stacy", "Roger", "Roger", "Sam", "Bob", "Sam", "Stacy", "Bob", "Stacy", "Roger", "Bob"),
  date = as.Date(c("2009-07-03", "2010-08-12", "2009-07-03", "2016-04-01", "2002-01-03", "2019-02-10", "2005-04-17", "2009-07-03", "2010-09-21", "2012-11-12", "2015-12-31", "2014-10-10", "2015-06-02", "2003-08-21")),
  amount = round(runif(14, 0, 100), 2)
)

tst %>%
  arrange(name, date) %>%
  mutate(check_in_number = group_indices(., name, date))
#> # A tibble: 14 x 4
#>    name  date       amount check_in_number
#>    <chr> <date>      <dbl>           <int>
#>  1 Bob   2003-08-21  91.1                1
#>  2 Bob   2009-07-03  38.1                2
#>  3 Bob   2009-07-03  28.3                2
#>  4 Bob   2015-12-31  22.3                3
#>  5 Roger 2002-01-03  68.3                4
#>  6 Roger 2009-07-03  83.8                5
#>  7 Roger 2015-06-02  94.2                6
#>  8 Roger 2019-02-10  48.8                7
#>  9 Sam   2005-04-17  16.6                8
#> 10 Sam   2010-08-12  93.2                9
#> 11 Sam   2010-09-21  65.5               10
#> 12 Stacy 2012-11-12  92.6               11
#> 13 Stacy 2014-10-10  84.4               12
#> 14 Stacy 2016-04-01   7.43              13

Si vous souhaitez que la numérotation recommence à chaque nom, vous pouvez modifier l'échelle en fonction de la première valeur de chaque nom :

tst %>%
  arrange(name, date) %>%
  mutate(check_in_number = group_indices(., name, date)) %>%
  group_by(name) %>%
  mutate(check_in_number = check_in_number - first(check_in_number) + 1)
#> # A tibble: 14 x 4
#> # Groups:   name [4]
#>    name  date       amount check_in_number
#>    <chr> <date>      <dbl>           <dbl>
#>  1 Bob   2003-08-21  91.1                1
#>  2 Bob   2009-07-03  38.1                2
#>  3 Bob   2009-07-03  28.3                2
#>  4 Bob   2015-12-31  22.3                3
#>  5 Roger 2002-01-03  68.3                1
#>  6 Roger 2009-07-03  83.8                2
#>  7 Roger 2015-06-02  94.2                3
#>  8 Roger 2019-02-10  48.8                4
#>  9 Sam   2005-04-17  16.6                1
#> 10 Sam   2010-08-12  93.2                2
#> 11 Sam   2010-09-21  65.5                3
#> 12 Stacy 2012-11-12  92.6                1
#> 13 Stacy 2014-10-10  84.4                2
#> 14 Stacy 2016-04-01   7.43               3

Créé le 2019-06-18 par le paquet reprex (v0.3.0)

1voto

akrun Points 148302

Une option avec data.table

library(data.table)
setDT(tst)[order(name, date)][, check_in_number := .GRP, .(name, date)][]
#      name       date amount check_in_number
# 1:   Bob 2003-08-21  66.36               1
# 2:   Bob 2009-07-03  22.18               2
# 3:   Bob 2009-07-03  96.15               2
# 4:   Bob 2015-12-31  31.64               3
# 5: Roger 2002-01-03  92.32               4
# 6: Roger 2009-07-03  41.85               5
# 7: Roger 2015-06-02  15.46               6
# 8: Roger 2019-02-10  80.38               7
# 9:   Sam 2005-04-17  49.18               8
#10:   Sam 2010-08-12  73.57               9
#11:   Sam 2010-09-21  49.37              10
#12: Stacy 2012-11-12  24.82              11
#13: Stacy 2014-10-10  23.31              12
#14: Stacy 2016-04-01  80.12              13

Si nous devons recommencer la numérotation

setDT(tst)[order(name, date)][, check_in_number := .GRP, 
   .(name, date)][,  check_in_number := match(check_in_number, 
          unique(check_in_number)), .(name)][]
#      name       date amount check_in_number
# 1:   Bob 2003-08-21  66.36               1
# 2:   Bob 2009-07-03  22.18               2
# 3:   Bob 2009-07-03  96.15               2
# 4:   Bob 2015-12-31  31.64               3
# 5: Roger 2002-01-03  92.32               1
# 6: Roger 2009-07-03  41.85               2
# 7: Roger 2015-06-02  15.46               3
# 8: Roger 2019-02-10  80.38               4
# 9:   Sam 2005-04-17  49.18               1
#10:   Sam 2010-08-12  73.57               2
#11:   Sam 2010-09-21  49.37               3
#12: Stacy 2012-11-12  24.82               1
#13: Stacy 2014-10-10  23.31               2
#14: Stacy 2016-04-01  80.12               3

données

tst <- data_frame(
  name = c("Bob", "Sam", "Roger", "Stacy", "Roger", "Roger", "Sam", "Bob", "Sam", "Stacy", "Bob", "Stacy", "Roger", "Bob"),
  date = as.Date(c("2009-07-03", "2010-08-12", "2009-07-03", "2016-04-01", "2002-01-03", "2019-02-10", "2005-04-17", "2009-07-03", "2010-09-21", "2012-11-12", "2015-12-31", "2014-10-10", "2015-06-02", 
    "2003-08-21")),
  amount = round(runif(14, 0, 100), 2)
)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X