【问题标题】:Sampling from a secondary datatable to the main datatable based on a condition根据条件从辅助数据表采样到主数据表
【发布时间】:2026-02-16 14:30:01
【问题描述】:

我有两个数据表 dt_maindt_unit

set.seed(1)
dt_main<-data.table(ID=sample(1:20,size=10),Group=sample(1:3,size=10,replace=TRUE),Unit=0)
dt_unit<-data.table(Group=sample(1:3,size=10,replace=TRUE),Unit_id=sample(1000:3000,size=10,replace=TRUE))

dt_main 看起来像这样:

> dt_main
    ID Group Unit
 1:  4     1    0
 2:  7     1    0
 3:  1     1    0
 4:  2     2    0
 5: 13     2    0
 6: 19     2    0
 7: 11     2    0
 8: 17     3    0
 9: 14     1    0
10:  3     3    0

dt_unit 看起来像这样:

> dt_unit
    Group Unit_id
 1:     1    2624
 2:     1    2963
 3:     1    1974
 4:     1    1800
 5:     2    1851
 6:     1    1930
 7:     1    1325
 8:     2    1329
 9:     2    1553
10:     2    2445

我想填写dt_main 中的Unit 列,方法是从dt_unitdt_main 中抽取一个Unit_id 与相同的Group

例如对于dt_main 中的第一行(所以Group=1),代码应查找dt_unit 并找到Group 为1 的行(见下文),然后选择@987654338 @ 并将其插入Unit

> dt_unit[Group==1]
   Group Unit_id
1:     1    2624
2:     1    2963
3:     1    1974
4:     1    1800
5:     1    1930
6:     1    1325

我尝试了这样的方法,它为每一行分配了相同的数字:

dt_main[,Unit:=sample(dt_unit[Group==Group]$Unit_id,size=1)]

我也尝试过sapply,但效果不佳。

【问题讨论】:

  • 对于Group 的所有值,您想要相同的Unit_id 吗?所以Group = 1dt_unit 的值相同?
  • 不,我每次都想要随机值。

标签: r datatable sample


【解决方案1】:

这是一个基本的 R 解决方案,我们每次匹配组并采样 1 个值,

dt_main$Unit <- sapply(dt_main$Group, function(i) {
                                  v1 <- dt_unit$Unit_id[dt_unit$Group %in% i]; 
                                  if (length(v1) > 0) {sample(v1, 1) } else {NA}
                                  })


#    ID Group Unit
# 1:  4     1 1930
# 2:  7     1 1325
# 3:  1     1 1325
# 4:  2     2 1329
# 5: 13     2 2445
# 6: 19     2 2445
# 7: 11     2 1851
# 8: 17     3   NA
# 9: 14     1 1930
#10:  3     3   NA

【讨论】:

  • 我知道这会改变问题,但是否可以轻松解决以下问题:我想在查找值时添加第二个条件。例如,假设每个表中还有一个Size 列,并且在查看第二个数据表时,我想从以下行中进行采样:Group 列匹配和dt_main$Size&gt;dt_unit$Size
  • 应该很容易解决。想到一种方法,您可以在sapply() 函数中的v1 下添加v2,它只会获取满足您条件的那些的unit_ids。然后intersect v1 和 v2 并照常采样
【解决方案2】:

您可以通过Group 加入dt_maindt_unit,并为每个ID 选择一个随机行。

使用dplyr,您可以这样做:

library(dplyr)
left_join(dt_main, dt_unit, by = 'Group') %>% group_by(ID) %>% sample_n(1)


#     ID Group Unit_id
#   <int> <int>   <int>
# 1     1     1    1800
# 2     2     2    2445
# 3     3     3      NA
# 4     4     1    2963
# 5     7     1    1800
# 6    11     2    1851
# 7    13     2    1553
# 8    14     1    1325
# 9    17     3      NA
#10    19     2    2445

我从data.table 创建中删除了Unit 列。

【讨论】:

    【解决方案3】:

    mapply 的另一个答案,我将其用于具有多个条件的情况。在这种情况下,在查找时,我检查 Group 列是否匹配并且 dt_main 中的新列 (Size) 大于 dt_unit 的列。作为 OP,我必须在原始帖子中添加另一个条件,因此添加此解决方案以帮助未来的用户。

    my_fun<-function(var1,var2)
    {
      d<-dt_unit[(Group%in%var1)&(Size>=var2)]
      if(nrow(d)>=2){
      sample(x=d$Unit_id,size=1,replace=T)
      }else
      {d$Unit_id}
    }
    vars1<-dt_main$Group
    vars2<-dt_main$Size
    dt_main$Unit<-mapply(my_fun,vars1,vars2)
    

    【讨论】: