【问题标题】:SQL: perform undersampling to select a subset of majority classSQL:执行欠采样以选择多数类的子集
【发布时间】:2021-09-09 15:47:47
【问题描述】:

我有一个如下所示的表格:

user_id target
1278 1
9809 0
3345 0
9800 0
1298 1
1223 0

我的目标是执行欠采样,这意味着我想随机选择目标值为 0 的用户子集,同时保留目标值为 1 的所有用户。我已经尝试了以下代码,但是,由于 user_ids 都是唯一的,它不会随机删除目标为 0 的行。知道我需要做什么吗?

select *
from (select user_id, target, row_number() over (partition by user_id, target order by rand()) as seq
from dataset.mytable
) a
where target = 1 or seq = 1


【问题讨论】:

    标签: sql google-bigquery sampling


    【解决方案1】:

    一种方法使用窗口函数:

    select t.* except (seqnum, cnt1)
    from (select t.*,
                 row_number() over (partition by target order by rand()) as seqnum,
                 countif(target = 1) over () as cnt1
          from t
         ) t
    where seqnum <= cnt1;
    

    以上可能存在性能问题——甚至由于大量数据正在排序而超出资源。近似方法也可能适用于您的目的:

    select t.* except (cnt, cnt1)
    from (select t.*,
                 count(*) over (partition by target) as cnt,
                 countif(target = 1) over () as cnt1
          from t
         ) t
    where rand() < cnt * 1.0 / cnt1;
    

    这不能保证产生完全相同数量的01,但数量会非常接近。

    【讨论】:

    • 感谢您的帮助。我尝试了第二个代码,第一个提到我应该使用 group by,一旦我按 all 分组,我运行它,它给了我除以 0 错误。
    【解决方案2】:

    考虑以下方法 - 它保留所有目标 = 1 行和约 50% 的目标 = 0 行

    select * 
    from `dataset.mytable`
    where if(target = 1, true, rand() < 0.5)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-06
      • 2019-09-03
      • 2020-06-25
      • 2023-01-29
      • 1970-01-01
      • 1970-01-01
      • 2020-09-19
      • 2018-06-21
      相关资源
      最近更新 更多