在 dplyr 中创建新索引/重新索引
Create new index / re-index in dplyr
我在 R 中使用 dplyr table。典型的字段是主键、标识组的 ID 号、日期字段和一些值。有一些数字我做了一些操作,在一些初步步骤中抛出了一堆数据。
为了进行下一步的分析(在 MC Stan 中),如果日期和组 ID 字段都是整数索引,会更容易。所以基本上,我需要将它们重新索引为 1 和不同元素总数之间的整数(group_id 大约 750,date_id 大约 250,group_id 已经整数,但日期不是)。将其导出到数据框后,这样做相对简单,但我很好奇在 dplyr 中是否可行。
我尝试创建一个新的 date_val(称为 date_val_new)如下。根据评论中的讨论,我有一些虚假数据。我故意使组和日期值不为 1 到任何值,但我没有将日期设为实际日期。我使数据不平衡,删除了一些值来说明问题。 dplyr 命令为每个新组从 1 处重新启动索引,无论 date_val 是什么。所以每个组都从 1 开始,即使日期不同。
df1 <- data.frame(id = 1:40,
group_id = (10 + rep(1:10, each = 4)),
date_val = (20 + rep(rep(1:4), 10)),
val = runif(40))
for (i in c(5, 17, 33))
{
df1 <- df1[!df1$id == i, ]
}
df_new <- df1 %>%
group_by(group_id) %>%
arrange(date_val) %>%
mutate(date_val_new=row_number(group_id)) %>%
ungroup()
这是基本的 R 方法:
df1 %>% mutate(date_val_new = match(date_val, unique(date_val)))
或者用 data.table, df1[, date_val_new := .GRP, by=date_val]
.
使用group_indices_()
为每个组生成一个唯一的id:
df1 %>% mutate(date_val_new = group_indices_(., .dots = "date_val"))
更新
由于 group_indices()
无法处理 class tbl_postgres
,您可以尝试 dense_rank()
copy_to(my_db, df1, name = "df1")
tbl(my_db, "df1") %>%
mutate(date_val_new = dense_rank(date_val))
或使用 sql()
构建自定义查询
tbl(my_db, sql("SELECT *,
DENSE_RANK() OVER (ORDER BY date_val) AS DATE_VAL_NEW
FROM df1"))
或者,我认为您可以尝试 splitstackshape
包中的 getanID()
。
library(splitstackshape)
getanID(df1, "group_id")[]
# id group_id date_val val .id
# 1: 1 11 21 0.01857242 1
# 2: 2 11 22 0.57124557 2
# 3: 3 11 23 0.54318903 3
# 4: 4 11 24 0.59555088 4
# 5: 6 12 22 0.63045007 1
# 6: 7 12 23 0.74571297 2
# 7: 8 12 24 0.88215668 3
我在 R 中使用 dplyr table。典型的字段是主键、标识组的 ID 号、日期字段和一些值。有一些数字我做了一些操作,在一些初步步骤中抛出了一堆数据。
为了进行下一步的分析(在 MC Stan 中),如果日期和组 ID 字段都是整数索引,会更容易。所以基本上,我需要将它们重新索引为 1 和不同元素总数之间的整数(group_id 大约 750,date_id 大约 250,group_id 已经整数,但日期不是)。将其导出到数据框后,这样做相对简单,但我很好奇在 dplyr 中是否可行。
我尝试创建一个新的 date_val(称为 date_val_new)如下。根据评论中的讨论,我有一些虚假数据。我故意使组和日期值不为 1 到任何值,但我没有将日期设为实际日期。我使数据不平衡,删除了一些值来说明问题。 dplyr 命令为每个新组从 1 处重新启动索引,无论 date_val 是什么。所以每个组都从 1 开始,即使日期不同。
df1 <- data.frame(id = 1:40,
group_id = (10 + rep(1:10, each = 4)),
date_val = (20 + rep(rep(1:4), 10)),
val = runif(40))
for (i in c(5, 17, 33))
{
df1 <- df1[!df1$id == i, ]
}
df_new <- df1 %>%
group_by(group_id) %>%
arrange(date_val) %>%
mutate(date_val_new=row_number(group_id)) %>%
ungroup()
这是基本的 R 方法:
df1 %>% mutate(date_val_new = match(date_val, unique(date_val)))
或者用 data.table, df1[, date_val_new := .GRP, by=date_val]
.
使用group_indices_()
为每个组生成一个唯一的id:
df1 %>% mutate(date_val_new = group_indices_(., .dots = "date_val"))
更新
由于 group_indices()
无法处理 class tbl_postgres
,您可以尝试 dense_rank()
copy_to(my_db, df1, name = "df1")
tbl(my_db, "df1") %>%
mutate(date_val_new = dense_rank(date_val))
或使用 sql()
tbl(my_db, sql("SELECT *,
DENSE_RANK() OVER (ORDER BY date_val) AS DATE_VAL_NEW
FROM df1"))
或者,我认为您可以尝试 splitstackshape
包中的 getanID()
。
library(splitstackshape)
getanID(df1, "group_id")[]
# id group_id date_val val .id
# 1: 1 11 21 0.01857242 1
# 2: 2 11 22 0.57124557 2
# 3: 3 11 23 0.54318903 3
# 4: 4 11 24 0.59555088 4
# 5: 6 12 22 0.63045007 1
# 6: 7 12 23 0.74571297 2
# 7: 8 12 24 0.88215668 3