Как перенумеровать идентификатор группы последовательно в R? - PullRequest
0 голосов
/ 03 июля 2018

Я пытаюсь переименовать сгруппированный уникальный идентификатор последовательно, используя dplyr в R. Во фрейме данных есть пять столбцов, как показано ниже.

## Load package if necessary
library(tidyverse)

## Set data frame
df <- data.frame(
    hid=c(10001,10001,10001,10001,10002,10002,10002,10002,10002,
          10003,10003,10003,10003,10003,10003,10004,10004,10004,10004,10004),
    mid=c(1,2,3,4,1,2,3,4,5,1,2,3,4,5,6,1,2,3,4,5),
    tmc=c(010,01010,0,01020,010,010,010,010,010,010,010,010,0,010,010,010,0,01010,010,01010),
    thc=c(010,01010,0,02030,010,020,020,020,030,010,010,010,0,020,030,010,0,02020,030,04040),
    mdc=c(000,01010,0,02020,000,010,010,010,010,000,000,010,0,010,020,000,0,02020,010,01010),
    itc=c(010,01010,0,02020,020,020,020,020,020,010,010,010,0,020,020,010,0,02020,020,02020)
    )

Уникальные идентификаторы присваиваются каждой строке, сгруппированной по некоторым столбцам: tmc, thc, mdc и itc.

## Add unique id grouped by tmc, thc, mdc and itc
df.id <- df %>% mutate(id=as.numeric(interaction(tmc,thc,mdc,itc)))

Поскольку он не дает последовательных идентификаторов, мне нужно его переименовать. Однако я не мог найти решение для этого. Условия:

  • Если tmc, thc, mdc и itc равны 0, id устанавливается как 0 (причина не известна, но interaction дает 1 для таких записей. в моем фрейме данных)
  • Другие идентификаторы должны быть последовательно переименованы, но должны сохранять свою группу. (если id s установлены как 4,8,2,2,8, его следует переименовать в 1,2,3,3,2)

Следующие сценарии показывают, что я делаю в настоящее время. id - это временный идентификатор, полученный из функции interaction, но мне нужно получить последовательный идентификатор, указанный в столбце id.desired.

## Replace unique id sequentially
## IT DOES NOT GIVE DESIRED OUTPUT
# df.id %>% group_by(id) %>% mutate(id2=seq_along(id))

## Desired id is shown in `id.desired`
## `id` is the ones obtained from `interaction` function, which are not set sequentially
     hid   mid   tmc   thc   mdc   itc    id   id.desired
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
 1 10001     1    10    10     0    10   166     1
 2 10001     2  1010  1010  1010  1010   595     2
 3 10001     3     0     0     0     0     1     0
 4 10001     4  1020  2030  2020  2020   796     3
 5 10002     1    10    10     0    20   326     4
 6 10002     2    10    20    10    20   362     5
 7 10002     3    10    20    10    20   362     5
 8 10002     4    10    20    10    20   362     5
 9 10002     5    10    30    10    20   366     6
10 10003     1    10    10     0    10   166     1
11 10003     2    10    10     0    10   166     1
12 10003     3    10    10    10    10   198     7
13 10003     4     0     0     0     0     1     0
14 10003     5    10    20    10    20   362     5
15 10003     6    10    30    20    20   398     8
16 10004     1    10    10     0    10   166     1
17 10004     2     0     0     0     0     1     0
18  1004     3  1010  2020  2020  2020   791     9
19 10004     4    10    30    10    20   366     6
20 10004     5  1010  4040  1010  2020   767    10

Есть предложения? Я предпочитаю использовать dplyr в этой операции.

Я получил несколько предложений в предыдущем вопросе, однако в данном случае это не та же структура (поле dummy не существует в текущем фрейме данных). Как изменить нумерацию результата пересечения / group_indices в R?

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

(отредактировано с учетом вашего уточнения в комментариях)
Вот две вещи, которые я пытался сделать:

  1. Чтобы гарантировать, что id = 0, когда определенные переменные равны 0, я использовал if_else в функции mutate с указанными вами конкретными условиями.
  2. Чтобы получить id.desired, я использовал функцию dens_rank ().

Вот код, основанный на наборе данных, которым вы поделились:

df %>% 
   mutate(id = if_else(tmc == 0 & thc == 0  & mdc == 0 & itc == 0, 0,
                       as.numeric(interaction(tmc, thc, mdc, itc, lex.order = TRUE)))) %>% 
   mutate(id.desired = dense_rank(id) - 1)

Вывод выглядит так

    hid   mid  tmc  thc  mdc  itc id   id.desired
1  10001   1   10   10    0   10 227          1
2  10001   2 1010 1010 1010 1010 519          7
3  10001   3    0    0    0    0   0          0
4  10001   4 1020 2030 2020 2020 775         10
5  10002   1   10   10    0   20 228          2
6  10002   2   10   20   10   20 258          4
7  10002   3   10   20   10   20 258          4
8  10002   4   10   20   10   20 258          4
9  10002   5   10   30   10   20 283          5
10 10003   1   10   10    0   10 227          1
11 10003   2   10   10    0   10 227          1
12 10003   3   10   10   10   10 232          3
13 10003   4    0    0    0    0   0          0
14 10003   5   10   20   10   20 258          4
15 10003   6   10   30   20   20 288          6
16 10004   1   10   10    0   10 227          1
17 10004   2    0    0    0    0   0          0
18 10004   3 1010 2020 2020 2020 550          8
19 10004   4   10   30   10   20 283          5
20 10004   5 1010 4040 1010 2020 595          9
0 голосов
/ 03 июля 2018

Решение с использованием tidyverse. Обратите внимание, что я не использовал функцию interaction. Вместо этого я использовал функцию group_indices из dplyr, чтобы создать групповой индекс, а затем преобразовать в коэффициент и изменить уровни в зависимости от порядка вхождения в столбце. df2 - конечный результат.

library(tidyverse)

df2 <- df %>%
  filter_at(vars(tmc, thc, mdc, itc), any_vars(. != 0)) %>%
  mutate(id = group_indices(., tmc, thc, mdc, itc)) %>%
  mutate(id = as.numeric(factor(id, levels = unique(id)))) %>%
  left_join(df, ., by = names(df)) %>%
  replace_na(list(id = 0))
df2
#      hid mid  tmc  thc  mdc  itc id
# 1  10001   1   10   10    0   10  1
# 2  10001   2 1010 1010 1010 1010  2
# 3  10001   3    0    0    0    0  0
# 4  10001   4 1020 2030 2020 2020  3
# 5  10002   1   10   10    0   20  4
# 6  10002   2   10   20   10   20  5
# 7  10002   3   10   20   10   20  5
# 8  10002   4   10   20   10   20  5
# 9  10002   5   10   30   10   20  6
# 10 10003   1   10   10    0   10  1
# 11 10003   2   10   10    0   10  1
# 12 10003   3   10   10   10   10  7
# 13 10003   4    0    0    0    0  0
# 14 10003   5   10   20   10   20  5
# 15 10003   6   10   30   20   20  8
# 16 10004   1   10   10    0   10  1
# 17 10004   2    0    0    0    0  0
# 18 10004   3 1010 2020 2020 2020  9
# 19 10004   4   10   30   10   20  6
# 20 10004   5 1010 4040 1010 2020 10
0 голосов
/ 03 июля 2018

Не уверен, как интерпретировать столбец id.desired, но вот пример, основанный на двух условиях и использующий data.table:

 require(data.table)   
 df = data.table(df)   
 df[tmc != 0 & thc != 0 & mdc != 0 & itc != 0, ID := 1:.N, by = .(tmc, thc, mdc, itc)]
 df[is.na(ID), ID := 0]
...