行绑定数据帧并保持唯一 ID 递增
Posted
技术标签:
【中文标题】行绑定数据帧并保持唯一 ID 递增【英文标题】:Row bind dataframes and keep unique IDs incrementing 【发布时间】:2021-01-30 15:51:55 【问题描述】:我有 2 个数据集要堆叠在一起。请注意,第一个数据集的 record_ids 也从 1 开始
record_id any_column
591 a
591 b
591 c
592 d
592 e
592 f
592 g
593 h
593 i
593 j
第二个数据集
record_id any_column
1 a
1 b
1 c
2 d
2 e
2 f
2 g
3 h
3 i
3 j
堆叠时,我希望第二个数据集的 record_ids 从第一个数据集的 recod_ids 立即结束的位置开始,在这种情况下,593
,我想将第二个数据集的 ids 转换为从 @987654324 开始的东西@等等。我怎样才能最好地解决这个问题?谢谢
对未来数据集的期望如下:
record_id any_column grand_id
591 a 591
591 b 591
591 c 591
592 d 592
592 e 592
592 f 592
592 g 592
593 h 593
593 i 593
593 j 593
1 a 594
1 b 594
1 c 594
2 d 595
2 e 595
2 f 595
2 g 595
3 h 596
3 i 596
3 j 596
【问题讨论】:
@Ronak Shah,下面的 2 个答案满足了我的需要和工作流程,所以我接受了它们。这里有很多有用的。 :) 【参考方案1】:您可以从df1
获得max
的record_id
并添加到record_id
的df2
。
rbind(transform(df1, grand_id = record_id),
transform(df2, grand_id = record_id + max(df1$record_id)))
如果你喜欢dplyr
:
library(dplyr)
df1 %>%
mutate(grand_id = record_id) %>%
bind_rows(df2 %>% mutate(grand_id = record_id + max(df1$record_id)))
# record_id any_column grand_id
#1 591 a 591
#2 591 b 591
#3 591 c 591
#4 592 d 592
#5 592 e 592
#6 592 f 592
#7 592 g 592
#8 593 h 593
#9 593 i 593
#10 593 j 593
#11 1 a 594
#12 1 b 594
#13 1 c 594
#14 2 d 595
#15 2 e 595
#16 2 f 595
#17 2 g 595
#18 3 h 596
#19 3 i 596
#20 3 j 596
【讨论】:
【参考方案2】:顶部数据集的 id 值可以改变吗?如果是这样,另一种选择是使用dplyr::dense_rank()
。这可能更容易推广到两个以上的数据集。它将保留输入数据集内和输入数据集之间的相对顺序
ds_stack <-
ds_top %>%
# dplyr::union_all(ds_middle) %>% # Add more datasets in here if necessary
dplyr::union_all(ds_bottom) %>%
dplyr::mutate(
grand_id = dplyr::dense_rank(paste0(source, "-", record_id))
)
# # A tibble: 20 x 4
# record_id any_column source grand_id
# <int> <chr> <int> <int>
# 1 591 a 1 1
# 2 591 b 1 1
# 3 591 c 1 1
# 4 592 d 1 2
# 5 592 e 1 2
# 6 592 f 1 2
# 7 592 g 1 2
# 8 593 h 1 3
# 9 593 i 1 3
# 10 593 j 1 3
# 11 1 a 2 4
# 12 1 b 2 4
# 13 1 c 2 4
# 14 2 d 2 5
# 15 2 e 2 5
# 16 2 f 2 5
# 17 2 g 2 5
# 18 3 h 2 6
# 19 3 i 2 6
# 20 3 j 2 6
输入数据集:
library("magrittr")
ds_top <-
tibble::tribble(
~record_id, ~any_column,
591L,"a",
591L,"b",
591L,"c",
592L,"d",
592L,"e",
592L,"f",
592L,"g",
593L,"h",
593L,"i",
593L,"j"
) %>%
dplyr::mutate(
source = 1L
)
ds_bottom <-
tibble::tribble(
~record_id, ~any_column,
1L, "a",
1L, "b",
1L, "c",
2L, "d",
2L, "e",
2L, "f",
2L, "g",
3L, "h",
3L, "i",
3L, "j"
) %>%
dplyr::mutate(
source = 2L
)
【讨论】:
谢谢,首先我喜欢创建source
列的想法,所以在联合之后我会知道哪一行来自哪个数据集。您已经解释了为什么您更喜欢 union 而不是 rbind
和 cbind
。【参考方案3】:
这是previous answer 的一个细微变化,它可以泛化到任意数量的输入数据集。而且由于您不计算输入数据集的数量,因此您将无法硬编码固定数量的 dplyr::union_all()
调用。
如果输入数据集是名为l
的列表中的元素,则purrr::map_dfr()
会隐式处理union
。
l %>%
purrr::map_df(~.) %>%
dplyr::mutate(
grand_id = dplyr::dense_rank(paste0(source, "-", record_id))
)
# # A tibble: 15 x 4
# source record_id any_column grand_id
# <int> <int> <chr> <int>
# 1 1 591 a 1
# 2 1 591 b 1
# 3 1 592 c 2
# 4 1 592 d 2
# 5 1 593 e 3
# 6 2 1 a 4
# 7 2 1 b 4
# 8 2 2 c 5
# 9 2 2 d 5
# 10 2 3 e 6
# 11 3 1 f 7
# 12 3 1 g 7
# 13 3 2 h 8
# 14 3 3 i 9
# 15 3 3 j 9
在这种情况下,数据集可能来自各种结构相似的数据库,这些数据库本质上会产生
library("magrittr")
ds_top <-
tibble::tribble(
~source, ~record_id, ~any_column,
1L, 591L,"a",
1L, 591L,"b",
1L, 592L,"c",
1L, 592L,"d",
1L, 593L,"e"
)
ds_middle <-
tibble::tribble(
~source, ~record_id, ~any_column,
2L, 1L, "a",
2L, 1L, "b",
2L, 2L, "c",
2L, 2L, "d",
2L, 3L, "e"
)
ds_bottom <-
tibble::tribble(
~source, ~record_id, ~any_column,
3L, 1L, "f",
3L, 1L, "g",
3L, 2L, "h",
3L, 3L, "i",
3L, 3L, "j"
)
l <- list(ds_top, ds_middle, ds_bottom)
但是,如果您从结构相同的 csv 文件中提取数据,则可以像这样组合一些操作
ds_stack <-
vector_of_file_paths %>%
purrr::map_dfr(~readr:read_csv(.), .id = "source") %>%
dplyr::mutate(
grand_id = dplyr::dense_rank(paste0(source, "-", record_id))
)
【讨论】:
【参考方案4】:我认为您应该在第一个数据集结束时使用 if 语句,只需保存最后一个值索引并递增它,不要忘记检查第二个数据集记录 id 是否相似
【讨论】:
它们很相似。我知道该怎么做,我在问我该怎么做。谢谢 @Ronak,请看上面的grand_id一栏以上是关于行绑定数据帧并保持唯一 ID 递增的主要内容,如果未能解决你的问题,请参考以下文章