代码之家  ›  专栏  ›  技术社区  ›  Nikita Vlasenko

Neo4j按浮点数分组

  •  2
  • Nikita Vlasenko  · 技术社区  · 8 年前

    我有一些项目(单元格)与它们相关联的浮点数(基因表达值),我需要 Neo4j 来回报我 counts 这些浮点数的指定范围内的项。我想得到这样的东西:

    cell count: 20
    expression: [0, 0.1)
    
    cell count: 25
    expression: [0.1, 0.2)
    
    cell count: 10
    expression: [0.2, 0.3)
    

    以以下方式将数据存储在数据库中:

    (c:Cell)-[ex:EXPRESSES]->(g.Gene)
    ex.expr - expression value; g.geneName - gene name that is set for this query
    

    现在,我陷入了以下问题:

    MATCH (c:Cell)-[ex:EXPRESSES]->(g:Gene {geneName:"Ifnar1"})
    RETURN ex.expr, count(c) as cellcount
    

    我需要以某种方式指定 range 对于每个 ex.expr 单个值。

    如有任何建议,将不胜感激。

    使现代化

    示例数据集:

    g.geneName = "Ifnar1"
    
    c.cellId = 1, ex.expr = 0.05
    c.cellId = 2, ex.expr = 0.07
    c.cellId = 3, ex.expr = 1.50
    c.cellId = 4, ex.expr = 1.21
    c.cellId = 5, ex.expr = 2.11
    c.cellId = 6, ex.expr = 0.85
    c.cellId = 7, ex.expr = 0.96
    c.cellId = 8, ex.expr = 0.15
    
    Answer:
    [0, 0.5], 3
    [0.5, 1.0], 2
    [1.0, 1.5], 2
    [1.5, 2.0], 0
    [2.0, 2.5], 1
    

    更新:澄清

    是的,它们的长度相同。我希望能够指定间隔步长,例如0.02,并使用该步长生成间隔,然后从0.02,到最大值,即2.5。我只知道min是 0 ,但实际上我事先不知道最大值。不,对于我正在执行的特定任务,返回零计数的间隔是不必要的,但如果可以在一般情况下执行,那还是很好的。我想如何通过间隔列表?类似于 范围 然而,我不知道最大值是多少,所以最大值应该随时确定 OR 我只能猜测数字,那也行。我希望计数的分布是正态分布,因此如果表达式太高,计数将为零。

    2 回复  |  直到 8 年前
        1
  •  2
  •   stdob--    8 年前

    假设输入参数是间隔 $step 。第一个区间的左边界为零。然后对于 ex.expr 我们可以计算它的间隔:

    floor(ex.expr / $step)
    

    因此,我们需要:

    • 浏览所有关系
    • 计算它们所属的时间间隔
    • 计算每个间隔的数量
    • 按间隔顺序分离
    • 并返回结果(并计算区间边界)

    查询的概念( $步 是输入参数):

    MATCH (c:Cell)-[ex:EXPRESSES]->(g:Gene {geneName:"Ifnar1"})
    WITH floor(ex.expr / $step) AS intervalIndex, 
         count(c) AS cellCount 
         ORDER BY intervalIndex ASC
    RETURN intervalIndex, 
           cellCount
    

    如果我们不仅要返回区间数,还要返回其边界,该怎么办

    MATCH (c:Cell)-[ex:EXPRESSES]->(g:Gene {geneName:"Ifnar1"})
    WITH floor(ex.expr / $step) AS intervalIndex, 
         count(c) AS cellCount 
         ORDER BY intervalIndex ASC
    WITH intervalIndex, cellCount,
         $step * intervalIndex AS leftBoundary,
         $step * (intervalIndex + 1) AS rightBoundary
    RETURN intervalIndex, 
           [leftBoundary, rightBoundary] AS intervalBoundaries, 
           cellCount
    

    对于某些步骤值,返回的间隔值将不准确,例如在步骤0.2,intervalIndex为2- [0.4, 0.6000000000000001] 而不是 [0.4, 0.6] 。因此,根据小数点后一步中的位数,我们需要计算计算精度因数,并四舍五入到所需位数(基于Mark Needham post http://markhneedham.com/blog/2014/05/25/neo4j-cypher-rounding-a-float-value-to-decimal-places/ ):

    WITH toInteger(split(toString($step - floor($step)), '.')[1]) AS precision
    WITH CASE WHEN precision IS NULL THEN 0 ELSE precision END AS precision
    WITH 10 ^ precision AS factor
    
    MATCH (c:Cell)-[ex:EXPRESSES]->(g:Gene {geneName:"Ifnar1"})
    WITH factor,
         floor(ex.expr / $step) AS intervalIndex, 
         count(c) AS cellCount 
         ORDER BY intervalIndex ASC
    WITH intervalIndex, cellCount,
         round(factor * $step * intervalIndex) / factor AS leftBoundary,
         round(factor * $step * (intervalIndex + 1)) / factor AS rightBoundary
    RETURN intervalIndex, 
           [leftBoundary, rightBoundary] AS intervalBoundaries, 
           cellCount
    
        2
  •  1
  •   Scofflaw    8 年前

    始终可以通过使用参数以编程方式运行连续查询:

    MATCH (c:Cell)-[ex:EXPRESSES]->(g:Gene {geneName:"Ifnar1"})
    WHERE $lower <= ex.expr < $upper
    RETURN COUNT(c)
    

    然后只需编写一个脚本来生成 $更低 $上限 参数随您的意愿而定。

    编辑

    或者,如果知道间隔边界,可以这样做:

    MATCH (c:Cell)-[ex:EXPRESSES]->(g:Gene {geneName:"Ifnar1"})
    WITH c, (CASE
    WHEN 0<=ex.expr<0.5 THEN 0
    WHEN 0.5<=ex.expr<1 THEN 1
    WHEN 1<=ex.expr<1.5 THEN 2
    WHEN 1.5<=ex.expr<2 THEN 3
    WHEN 2<=ex.expr<2.5 THEN 4 END) AS interval
    RETURN interval, COUNT(c), ORDER BY interval