Генерация уникальных / случайных серийных номеров с использованием group_by в R с использованием dplyr - PullRequest
0 голосов
/ 06 февраля 2019

Я хотел бы сгенерировать уникальные числа (последовательные или случайные), сгруппированные по определенным столбцам, используя R.

Пример набора данных приведен ниже

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

Используя данные выше, я хотел бынапример, создать переменную style_serial, которая выглядит следующим образом:

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

То есть создать переменную, которая принимает уникальное значение, сгруппированное по столбцам fact_code, style_, item и customer.Я пробовал следующий код R, используя пакет dplyr:

df <- df %>%
dplyr::group_by(fact_code, style_, buyer) %>%
dplyr::mutate(style_serial = 1:n())

, где df - имя вышеприведенного примера фрейма данных.Но это дает мне неожиданный вывод:

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

Я бы не возражал, если бы style_serial был рандомизированным набором целых чисел, чтобы данные выглядели так:

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

Toсгенерировав таблицу выше, я запускаю следующий R код:

df <- df %>%
dplyr::group_by(fact_code, style_, buyer) %>%
dplyr::mutate(style_serial = sample(1:6000, n(), replace = FALSE))

Однако я не могу получить желаемый результат.

Основная цель - создать в этом случае переменную style_serial, которая принимает уникальные значения, сгруппированные по определенному количеству столбцов, т.е. в этом случае fact_code, style_, item и покупатель.

Любая помощь будет оценена.

Ответы [ 4 ]

0 голосов
/ 06 февраля 2019

Полностью dplyr решение, создание справочной таблицы и присоединение ее к базовой таблице.

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

Если вы хотите использовать ее как «одну строку»:

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

Создано в 2019-02-06 пакетом представ (v0.2.1)

0 голосов
/ 06 февраля 2019

Вы можете использовать rleid из data.table, т.е.

library(dplyr)
df %>% 
 mutate(style = data.table::rleid(fact_code, style_, item))
0 голосов
/ 06 февраля 2019

Способ с dplyr без дополнительных пакетов:

df %>%
  mutate(
    style_serial = cumsum(
      coalesce(as.numeric(paste0(fact_code, style_, buyer) != lag(paste0(fact_code, style_, buyer))), 1)
      )
  )

Только с data.table:

library(data.table)

setDT(df)[, style_serial := .GRP, by = .(fact_code, style_, buyer)]

Вывод в обоих случаях:

   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
0 голосов
/ 06 февраля 2019

Мы можем использовать group_indices из dplyr

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

ПРИМЕЧАНИЕ: числа random помечены sample, если нам это не нужно, то удалите sampleчасть

df %>%
  mutate(style_serial = group_indices(.,fact_code, style_, buyer))

или с использованием base R

v1 <- with(df, do.call(paste, df[1:3]))
df$style_serial <-  match(v1, unique(v1))

data

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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...