获取特定格式的规则 table

Get rules table in specific format

我设法从数据框中的单个变量 rpart 模型获取输出,其中对于每个叶节点,规则一直应用到行中的根节点:

x <- read.table(header=T, sep="", stringsAsFactors = FALSE,text="
id number operator rule
1     8.5       >=    4
2    14.5       >=    4
3     8.5       >=   10
4    14.5        <   10
5     9.5        <   10
6     8.5       >=   22
7    14.5        <   22
8     9.5       >=   22
9    12.5       >=   22
10    8.5       >=   46
11   14.5        <   46
12    9.5       >=   46
13   12.5        <   46
14   11.5        <   46
15    8.5       >=   47
16   14.5        <   47
17    9.5       >=   47
18   12.5        <   47
19   11.5       >=   47
20    8.5        <    6
21      4        <    6
22    8.5        <    7
23      4       >=    7
")

规则由 rule 标识(例如,具有 rule==22 的所有行构成一个规则)。现在我想以这样一种方式转换这些数据,即每条规则一行:

rule minOperator maxOperator minValue maxValue
 4   >=          NA          14.5     Inf
10   >=          <            8.5     9.5
22   >=          <           12.5     14.5
46   >=          <            9.5     11.5
47   >=          <           11.5     12.5  
 6   NA          <           -Inf      4
 7   >=          <             4      8.5

我看到算法是这样的:

但不知道如何在 R 中轻松地做到这一点。

这有点乱,但似乎可以解决问题

rulecollapse <- function(d, mins=c(">", ">="), maxs=c("<", "<=")) {
    mn<-which(d$operator %in% mins)[which.max(d$number[d$operator %in% mins])]
    mx<-which(d$operator %in% maxs)[which.min(d$number[d$operator %in% maxs])]
    data.frame(list(rule=d$rule[1]),
    if (length(mn)>0) {
        list(minOperator=d$operator[mn], minValue=d$number[mn])
    } else {
        list(minOperator=NA, minValue=-Inf)
    },
    if (length(mx)>0) {
        list(maxOperator=d$operator[mx], maxValue=d$number[mx])
    } else {
        list(maxOperator=NA, maxValue=Inf)
    }
    )
}

do.call(rbind, lapply(split(x, x$rule), rulecollapse))[, c(1,2,4,3,5)]

并产生

   rule minOperator maxOperator minValue maxValue
4     4          >=        <NA>     14.5      Inf
6     6        <NA>           <     -Inf      4.0
7     7          >=           <      4.0      8.5
10   10          >=           <      8.5      9.5
22   22          >=           <     12.5     14.5
46   46          >=           <      9.5     11.5
47   47          >=           <     11.5     12.5

rulecollapse 函数需要一个包含单个规则所有行的数据框。然后根据您的描述查找 min/max 值,如果未找到,则 returns NA/Inf 值。它输出另一个 data.frame。然后我们使用基本的 split() 命令将你原来的 data.frame 分解为每个规则,然后使用 lapply 对每个子集执行 rulecollapse,最后使用do.call(rbind, ..) 将所有内容合并回一个 data.frame。

我的做法:

  • 将数据分成两组,一组使用 > 和 >= 运算符,第二组使用 <, <= 运算符
  • 按规则和编号对数据帧进行排序(<、<= 升序,>、>= 降序)
  • 从已排序的数据框中获取每个规则的第一行
  • 完整的外连接数据帧

代码:

minRules <- x[x$operator %in% c('>','>='),]
maxRules <- x[x$operator %in% c('<','<='),]

merge(
  aggregate(. ~ rule, data = minRules[with(minRules, order(rule, -number)), ], 
            FUN=head, 1),
  aggregate(. ~ rule, data = maxRules[with(maxRules, order(rule, number)), ],
            FUN=head, 1),
  by = 'rule', all = TRUE
)

结果:

  rule id.x number.x operator.x id.y number.y operator.y
1    4    2     14.5         >= <NA>     <NA>       <NA>
2    6 <NA>     <NA>       <NA>   21        4          <
3    7   23        4         >=   22      8.5          <
4   10    3      8.5         >=    5      9.5          <
5   22    9     12.5         >=    7     14.5          <
6   46   12      9.5         >=   14     11.5          <
7   47   19     11.5         >=   18     12.5          <