Je voudrais générer des numéros uniques (en série ou aléatoires) regroupés par certaines colonnes en utilisant R.
Un exemple de jeu de données est fourni ci-dessous
df <- df %>% dplyr::group_by(fact_code, style_, buyer) %>% dplyr::mutate(style_serial = sample(1:6000, n(), replace = FALSE))
En utilisant les données ci-dessus , Je voudrais créer une variable, par exemple, style_serial qui ressemble à ceci:
fact_code style_ item buyer style_serial 1206 -23 LADIES TANK TOP 652 10 1206 -23 LADIES TANK TOP 652 10 1206 -23 LADIES TANK TOP 652 10 1214 593935_592435 SS T-SHIRT 254 2 1214 593935_592435 SS T-SHIRT 254 2 1214 593935_592435 SS T-SHIRT 254 2 7022 1572472 T-SHIRT 338 100 7022 1572472 T-SHIRT 338 100 7022 1572472 T-SHIRT 338 100
Autrement dit, créer une variable qui suppose une valeur unique regroupée par les colonnes fact_code, style_ , article et acheteur. J'ai essayé le code R suivant en utilisant le package dplyr :
fact_code style_ item buyer style_serial 1206 -23 LADIES TANK TOP 652 1 1206 -23 LADIES TANK TOP 652 2 1206 -23 LADIES TANK TOP 652 3 1214 593935_592435 SS T-SHIRT 254 1 1214 593935_592435 SS T-SHIRT 254 2 1214 593935_592435 SS T-SHIRT 254 3 7022 1572472 T-SHIRT 338 1 7022 1572472 T-SHIRT 338 2 7022 1572472 T-SHIRT 338 3
où df est le nom de l'exemple ci-dessus trame de données. Mais cela me donne une sortie inattendue:
df <- df %>% dplyr::group_by(fact_code, style_, buyer) %>% dplyr::mutate(style_serial = 1:n())
Cela ne me dérangerait pas si le style_serial est un ensemble aléatoire d'entiers, de sorte que les données ressemblent à ceci:
fact_code style_ item buyer style_serial 1206 -23 LADIES TANK TOP 652 1 1206 -23 LADIES TANK TOP 652 1 1206 -23 LADIES TANK TOP 652 1 1214 593935_592435 SS T-SHIRT 254 2 1214 593935_592435 SS T-SHIRT 254 2 1214 593935_592435 SS T-SHIRT 254 2 7022 1572472 T-SHIRT 338 3 7022 1572472 T-SHIRT 338 3 7022 1572472 T-SHIRT 338 3
Pour générer le tableau ci-dessus, j'exécute le code R suivant:
fact_code style_ item buyer 1206 -23 LADIES TANK TOP 652 1206 -23 LADIES TANK TOP 652 1206 -23 LADIES TANK TOP 652 1214 593935_592435 SS T-SHIRT 254 1214 593935_592435 SS T-SHIRT 254 1214 593935_592435 SS T-SHIRT 254 7022 1572472 T-SHIRT 338 7022 1572472 T-SHIRT 338 7022 1572472 T-SHIRT 338
Cependant, je suis pas en mesure d'obtenir la sortie souhaitée.
L'objectif principal est de créer une variable dans ce cas, style_serial, qui suppose des valeurs uniques regroupées par un certain nombre de colonnes, c'est-à-dire dans ce cas fact_code, style_, item et acheteur.
Toute aide serait appréciée.
4 Réponses :
Nous pouvons utiliser group_indices de dplyr
df <- structure(list(fact_code = c(1206L, 1206L, 1206L, 1214L, 1214L,
1214L, 7022L, 7022L, 7022L), style_ = c("-23", "-23", "-23",
"593935_592435", "593935_592435", "593935_592435", "1572472",
"1572472", "1572472"), item = c("LADIES TANK TOP", "LADIES TANK TOP",
"LADIES TANK TOP", "SS T-SHIRT", "SS T-SHIRT", "SS T-SHIRT",
"T-SHIRT", "T-SHIRT", "T-SHIRT"), buyer = c(652L, 652L, 652L,
254L, 254L, 254L, 338L, 338L, 338L)), class = "data.frame", row.names = c(NA,
-9L))
REMARQUE: les nombres sont aléatoires avec sample , si nous n'en avons pas besoin, supprimez la partie sample
v1 <- with(df, do.call(paste, df[1:3])) df$style_serial <- match(v1, unique(v1))
Ou en utilisant base R
df %>% mutate(style_serial = group_indices(.,fact_code, style_, buyer))
library(dplyr) df %>% mutate(style_serial = sample(6000)[group_indices(.,fact_code, style_, buyer)]) # fact_code style_ item buyer style_serial #1 1206 -23 LADIES TANK TOP 652 5778 #2 1206 -23 LADIES TANK TOP 652 5778 #3 1206 -23 LADIES TANK TOP 652 5778 #4 1214 593935_592435 SS T-SHIRT 254 998 #5 1214 593935_592435 SS T-SHIRT 254 998 #6 1214 593935_592435 SS T-SHIRT 254 998 #7 7022 1572472 T-SHIRT 338 3018 #8 7022 1572472 T-SHIRT 338 3018 #9 7022 1572472 T-SHIRT 338 3018
Ajout de group_indices à ma liste de "fonctions extrêmement situationnelles". Je n'avais aucune idée que cela existait, très élégant.
Vous pouvez utiliser rleid depuis data.table , c'est-à-dire
library(dplyr) df %>% mutate(style = data.table::rleid(fact_code, style_, item))
Un moyen avec dplyr sans packages supplémentaires:
fact_code style_ item buyer style_serial 1: 1206 -23 LADIESTANKTOP 652 1 2: 1206 -23 LADIESTANKTOP 652 1 3: 1206 -23 LADIESTANKTOP 652 1 4: 1214 593935_592435 SST-SHIRT 254 2 5: 1214 593935_592435 SST-SHIRT 254 2 6: 1214 593935_592435 SST-SHIRT 254 2 7: 7022 1572472 T-SHIRT 338 3 8: 7022 1572472 T-SHIRT 338 3 9: 7022 1572472 T-SHIRT 338 3
Avec data.table uniquement:
library(data.table) setDT(df)[, style_serial := .GRP, by = .(fact_code, style_, buyer)]
Résultat dans les deux cas:
df %>%
mutate(
style_serial = cumsum(
coalesce(as.numeric(paste0(fact_code, style_, buyer) != lag(paste0(fact_code, style_, buyer))), 1)
)
)
Solution entièrement dplyr , en créant une table de recherche et en la joignant à la table de base.
df <- df %>% dplyr::left_join(
df %>%
dplyr::group_by(fact_code, style_, buyer) %>%
dplyr::summarise() %>%
dplyr::ungroup() %>%
dplyr::mutate(style_serial = row_number())
)
#> Joining, by = c("fact_code", "style_", "buyer")
#> fact_code style_ item buyer style_serial
#> 1 1206 -23 LADIES TANK TOP 652 1
#> 2 1206 -23 LADIES TANK TOP 652 1
#> 3 1206 -23 LADIES TANK TOP 652 1
#> 4 1214 593935_592435 SS T-SHIRT 254 2
#> 5 1214 593935_592435 SS T-SHIRT 254 2
#> 6 1214 593935_592435 SS T-SHIRT 254 2
#> 7 7022 1572472 T-SHIRT 338 3
#> 8 7022 1572472 T-SHIRT 338 3
#> 9 7022 1572472 T-SHIRT 338 3
Si vous la voulez en tant que "one-liner":
serial_df <- df %>%
dplyr::group_by(fact_code, style_, buyer) %>%
dplyr::summarise() %>%
dplyr::ungroup() %>%
dplyr::mutate(style_serial = row_number())
dplyr::left_join(df, serial_df)
#> Joining, by = c("fact_code", "style_", "buyer")
#> fact_code style_ item buyer style_serial
#> 1 1206 -23 LADIES TANK TOP 652 1
#> 2 1206 -23 LADIES TANK TOP 652 1
#> 3 1206 -23 LADIES TANK TOP 652 1
#> 4 1214 593935_592435 SS T-SHIRT 254 2
#> 5 1214 593935_592435 SS T-SHIRT 254 2
#> 6 1214 593935_592435 SS T-SHIRT 254 2
#> 7 7022 1572472 T-SHIRT 338 3
#> 8 7022 1572472 T-SHIRT 338 3
#> 9 7022 1572472 T-SHIRT 338 3
Créé le 2019-02-06 par le package reprex (v0.2.1)