我想使用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中的每个唯一值吗?重复吗?
答案 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.integer
或as.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