行绑定数据帧并保持唯一 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 获得maxrecord_id 并添加到record_iddf2

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 而不是 rbindcbind【参考方案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 递增的主要内容,如果未能解决你的问题,请参考以下文章

让oracle数据库的表的id自动递增

如何将选定的数据行从json文件绑定到输入字段(文本)?

ComboBox 中 DisplayMember 和 ValueMember有何区别

在用户控件中获取工具提示以显示数据绑定文本并保持打开状态

webform的操作完之后返回主页面的行定位

一文读懂分布式唯一ID生成