按其他列值获取列中每个唯一值的前 x% 行

Posted

技术标签:

【中文标题】按其他列值获取列中每个唯一值的前 x% 行【英文标题】:Get top x% rows for every unique value in column by other column value 【发布时间】:2020-03-23 00:18:03 【问题描述】:

表格“标签”:

Source  Target      Weight
#003    blitzkrank  0.83
#003    deutsch     0.7
#003    brammen     0.57
#003    butzfrauen  0.55
#003    solaaaa     0.5
#003    moments     0.3
college scandal     1.15
college prosecutors 0.82
college students    0.41
college usc         0.33
college full house  0.17
college friends     0.08
college house       0.5
college friend      0.01

该表在“源”列中有 5.600.000 行和约 91.000 个唯一条目。

对于“源”和“目标”中的每个唯一值,我需要按权重排序的前 x% 行(例如前 20%、前 30%,需要可变)(表格按“源”排序(升序)和“重量”(降序)。

如果行具有相同的“权重”,则按字母顺序排列行。 如果 x% == 0 至少占用一行。

由于会有重复项(例如,“Source = "college" 将产生至少一个重复行作为 "Target" = "scandal"),因此应尽可能删除重复条目。否则没什么大不了的。

“来源”的计算:

6 rows where Source = "#003", 6 * 0.2 = 1.2 = take 1 row
8 rows where Source = "college", 8 * 0.2 = 1.6 = take 2 rows

“来源”所需的结果表:

Source  Target      Weight
#003    blitzkrank  0.83
college scandal     1.15
college prosecutors 0.82

如何在 SQLite 数据库的 SQL 中做到这一点?

【问题讨论】:

“对于“源”和“目标”中的每个唯一值,我需要前 x% 行“我不明白你的意思。您的意思是“一对”值吗?一行是否可以重复,一次用于源,一次用于目标? 一行可以对源重复一次,对目标重复一次,是的。 【参考方案1】:

如果您想要source 的样品:

select t.*
from (select t.*,
             row_number() over (partition by source order by weight desc, target) as seqnum,
             count(*) over (partition by source) as cnt
      from t
     ) t
where seqnum = 1 or  -- always at least one row
      seqnum <= round(cnt * 0.2);

根据您的示例,我认为这就是您想要的。您可以为target 构造一个类似的查询。

【讨论】:

这给出了需要的结果,非常感谢。有没有办法在同一个 SQL 查询中对“目标”列进行相同的处理,以便在一次运行中获取两者的行? @Vega 您可以使用两个查询的UNION(也可以删除重复项)。 很高兴知道,与我在 Python/Pandas 中的解决方案相比,UNION 需要 5.71 分钟,大大加快(需要 1-2 天)。再次感谢! @Vega 在源列和目标列上添加索引(如果它们尚不存在)如果您需要经常运行它应该有助于加快速度。或查看sqlite3 shell's .expert command 了解详细的索引建议。

以上是关于按其他列值获取列中每个唯一值的前 x% 行的主要内容,如果未能解决你的问题,请参考以下文章

宏以获取列中每个唯一值的范围

火花数据集:如何从列中获取唯一值的出现次数

在其中一列中具有多个空值的复合唯一键约束

SQL - 以列值作为列名的聚合

在唯一列值的熊猫上应用计数器[重复]

Python:从数据框的列中获取唯一值的组合