如何在R中按顺序重新编号组ID?

时间:2018-07-03 15:31:30

标签: r dplyr rename tidyverse

我正在尝试使用dplyr中的R重命名分组的唯一ID。 数据框中有五列,如下所示。

## 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)
    )

为每行分配唯一的ID,这些行按以下几列进行分组:tmcthcmdcitc

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

由于它不提供顺序ID,因此我需要重命名。 但是,我找不到解决方案。条件是:

  • 如果tmcthcmdcitc都为0,则id设置为0(我不知道原因,但interaction在我的数据框中给出了1的此类摘要)
  • 其他ID应该顺序重命名,但需要保留其组。 (如果将id设置为4,8,2,2,8,则应将其重命名为1,2,3,3,2

以下脚本显示了我当前正在做什么。 id是从interaction函数获得的临时ID,但我需要获取id.desired列中指示的顺序ID。

## 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字段在当前数据帧中不存在)。 How to renumber result of intersection/group_indices in R?

3 个答案:

答案 0 :(得分:2)

使用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

答案 1 :(得分:0)

不确定如何解释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]

答案 2 :(得分:0)

(根据您在注释中的澄清进行了编辑突变)
这是我尝试做的两件事:

  1. 为了确保当某些变量为0时id = 0,我在mutate函数中使用了if_else并指定了特定条件。
  2. 要获得id.desired,我使用了density_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