代码之家  ›  专栏  ›  技术社区  ›  Ben

如何基于一组不等式约束对data.table进行排序?

  •  4
  • Ben  · 技术社区  · 7 年前

    我有一套“x<不等式约束,我想根据这些对data.table的行进行排序。

    例如,

    library(data.table)
    set.seed(0)
    ineqs <- unique(data.table(
      X = sample(letters, 10, replace = T),
      Rel = "<",
      Y = sample(letters, 10, replace = T)
    ))
    ineqs
        X Rel Y
     1: x   < b
     2: g   < f
     3: j   < e
     4: o   < r
     5: x   < j
     6: f   < u
     7: x   < m
     8: y   < s
     9: r   < z
    10: q   < j
    

    所以,如果我从一个排序字母表开始,

    dt <- data.table(Foo = letters)
        Foo
     1:   a
     2:   b
     3:   c
    ---    
    24:   x
    25:   y
    26:   z
    

    有效的

    2 回复  |  直到 7 年前
        1
  •  7
  •   Frank    7 年前
    library(igraph)
    g = ineqs[, graph_from_edgelist(cbind(X,Y), directed=TRUE)]
    o = names(topo_sort(g))
    
    dt[, v := factor(Foo, levels = o, ordered=TRUE)]
    dt[order(v)]
    
    
        Foo    v
     1:   x    x
     2:   g    g
     3:   o    o
     4:   y    y
     5:   q    q
     6:   b    b
     7:   m    m
     8:   f    f
     9:   r    r
    10:   s    s
    11:   j    j
    12:   u    u
    13:   z    z
    14:   e    e
    15:   a <NA>
    16:   c <NA>
    17:   d <NA>
    18:   h <NA>
    19:   i <NA>
    20:   k <NA>
    21:   l <NA>
    22:   n <NA>
    23:   p <NA>
    24:   t <NA>
    25:   v <NA>
    26:   w <NA>
        Foo    v
    

    所有不在 ineqs 被分类到最后。

    topo_sort . 这就告诉你你的任务没有很好的定义 .

        2
  •  4
  •   Maurits Evers    7 年前

    我举个例子。考虑条件

        X Rel Y
    1: x   < b
    2: g   < f
    

    各种命令是可以想象的

            x < g < f < b
    g     < x     <     b   <   f
    g     < x     < f < b
    g < f < x         < b
            x < g <     b     < f
            x <         b < g < f
    

    所有这些都满足前两条线所列的条件。


    以下是我的结果:

    1. 首先,我们定义四个字母并使用 gtools::permutations .

      char <- c("b", "f", "g", "x")
      
      library(gtools)
      perm <- as.data.frame(permutations(length(char), length(char), char))
      

      有24种可能的排列。

    2. df <- read.table(text =
          "X Rel Y
      x   < b
      g   < f", header = T)
      
      # Convert factors to character vectors
      df[] <- sapply(df, as.character)
      
    3. 我们现在循环抛出置换和成对条件,并标记置换数据中不满足任何成对条件的行。

      rmv <- c()
      for (i in 1:nrow(perm)) {
          # Here we loop throw all possible permutations and eliminate those that
          # do not fulfil the pairwise conditions
          for (j in 1:nrow(df)) {
              # Here we loop throw the pairwise conditions
              cond <- eval(parse(text = sprintf("`%s`", df[j, "Rel"])))(
                  which(perm[i, ] == df[j, "X"]),
                  which(perm[i, ] == df[j, "Y"]))
              if (cond == FALSE) {
                  rmv <- c(rmv, i)
                  break
              }
          }
      }
      
    4. 剩下的满足条件的排列是

      perm[-rmv, ]
      #   V1 V2 V3 V4
      #16  g  f  x  b
      #17  g  x  b  f
      #18  g  x  f  b
      #20  x  b  g  f
      #23  x  g  b  f
      #24  x  g  f  b