如何使用mutate函数将唯一值替换为索引号?

时间:2019-04-22 18:15:27

标签: r dataframe dplyr mutate

我想使用dplyr :: mutate用索引号替换唯一值。

我正在按几个不同的变量分组,以访问数据框的适当子集。

  head(df)
       group start_time end_time
  1    group1       0   0.4
  2    group1       0   0.4
  3    group1      0   0.4
  4    group1     0.4   0.8
  5    group1     0.4   0.8
  6    group2     0.0   0.4
  7    group2     0.4   0.8
  8    group2     0.8   1.02

我先按“ group”分组,再按“ start_time”分组。有时,给定的组只有一个start_time,有时是两个start_time,或者有时是三个。我需要为每个唯一的start_time创建一个新变量'idx'。但是我不知道该怎么做。

  new_df <- df %>% 
    group_by(group, start_time) %>% 
    mutate(idx = row_number()) %>%
    as.data.frame

使用row_number()创建新变量是不正确的。它给了我

  idx
  1
  2
  3
  1
  2
  1
  1
  1

但是我想要

  idx
  1
  1
  1
  2
  2
  1
  2
  3

我想用数字替换group_by中的每个唯一值吗?重复吗?

3 个答案:

答案 0 :(得分:4)

按“组”分组后,我们可以使用match

library(tidyverse)
df %>% 
   group_by(group) %>%
   mutate(idx = match(start_time, unique(start_time)))
# A tibble: 8 x 4
# Groups:   group [2]
#  group  start_time end_time   idx
#  <chr>       <dbl>    <dbl> <int>
#1 group1        0       0.4      1
#2 group1        0       0.4      1
#3 group1        0       0.4      1
#4 group1        0.4     0.8      2
#5 group1        0.4     0.8      2
#6 group2        0       0.4      1
#7 group2        0.4     0.8      2
#8 group2        0.8     1.02     3

或者另一个选择是group_indices

df %>% 
   group_split(group) %>%
   map_df(~ .x %>% 
                mutate(idx = group_indices(., start_time)))

注意:如果需要在“组”之外创建“ idx”,则删除group_by步骤

注意2:在OP的示例中,两个(带/不带group_by)给出的输出都相同

答案 1 :(得分:2)

实际上,我们可以使用R的因子类型轻松地做到这一点。 factor变量以整数形式存储,该整数表示保存实际值的级别表。然后,我们可以使用as.integeras.numeric将因数转换回数字。当执行此操作时,级别表将丢失,并且只剩下将引用它的整数。通常这是不希望的(您需要您的实际值,而不是编码值),但是在这种情况下,这是理想的,因为相同的值将使用相同的数字进行编码:

df <- structure(list(group = c("group1", "group1", "group1", "group1", 
"group1", "group2", "group2", "group2"), start_time = c(0, 0, 
0, 0.4, 0.4, 0, 0.4, 0.8), end_time = c(0.4, 0.4, 0.4, 0.8, 0.8, 
0.4, 0.8, 1.02)), class = "data.frame", row.names = c(NA, -8L
))

df %>%
    mutate(idx = as.integer(factor(start_time)))

   group start_time end_time idx
1 group1        0.0     0.40   1
2 group1        0.0     0.40   1
3 group1        0.0     0.40   1
4 group1        0.4     0.80   2
5 group1        0.4     0.80   2
6 group2        0.0     0.40   1
7 group2        0.4     0.80   2
8 group2        0.8     1.02   3

作为一个额外的好处,这在基本R中同样有效:

df$idx <- as.integer(factor(df$start_time))
df
   group start_time end_time idx
1 group1        0.0     0.40   1
2 group1        0.0     0.40   1
3 group1        0.0     0.40   1
4 group1        0.4     0.80   2
5 group1        0.4     0.80   2
6 group2        0.0     0.40   1
7 group2        0.4     0.80   2
8 group2        0.8     1.02   3

答案 2 :(得分:1)

另一个选择是data.table::frank(快速排名的缩写)

df %>% 
   group_by(group) %>%
   mutate(idx = data.table::frank(start_time, ties.method = 'dense'))

# # A tibble: 8 x 4
# # Groups:   group [2]
#   group  start_time end_time   idx
#   <chr>       <dbl>    <dbl> <int>
# 1 group1        0       0.4      1
# 2 group1        0       0.4      1
# 3 group1        0       0.4      1
# 4 group1        0.4     0.8      2
# 5 group1        0.4     0.8      2
# 6 group2        0       0.4      1
# 7 group2        0.4     0.8      2
# 8 group2        0.8     1.02     3