分配数据帧中提供的IF条件的有效方式

时间:2017-01-15 19:08:20

标签: r

我有一组以表格形式提供的IF条件。例如。

  rule_id number          colour                    shape
1       1    200                                         
2       2    100                                 triangle
3       3     NA             red                         
4       4     NA ‘blue’,‘orange’                rectangle
5       5     NA           green Not(‘triangle’,‘square’)
6       6     NA                                         

需要按如下方式读取表格(伪代码):

如果number = 200那么rule_id = 1

IFELSE number = 100 AND shape = triangle然后rule_id = 2

IFELSE colour = red然后rule_id = 3 .....

然后,我有兴趣根据这些规则对数据集中的行进行分类。例如。 (rule_id是分类的结果)

  number colour    shape rule_id
1    100    red triangle       2
2    200 yellow     none       1
3    300   blue     none       6
4    200   none     none       1
5    100    red   square       3
6    500  green   circle       5
7    400  green   square       6
8    600   none     none       6

为了做到这一点,我使用了一个遍历所有规则的FOR循环(我将所有满足条件rule_id = 1的行分类,然后转到rule_id = 2的下一次迭代)。遗憾的是,这似乎是一个非常缓慢的过程(我的规则表和我的数据集的尺寸都要大得多)。

有更好的方法吗? 而且,我如何才能最好地处理规则表中的Not

我使用的代码(可能不是美女......):

rules = data.frame(rule_id = 1:6,
               number = c(200, 100, rep(NA,4)),
               colour = c('', '', 'red', paste(sQuote('blue'), sQuote('orange'), sep = ','), 'green', ''),
               shape = c('', 'triangle','','rectangle', paste(paste('Not(', sQuote('triangle'), sep = ''), 
                                                              paste(sQuote('square'), ')', sep = ''), sep = ','), ''),
               stringsAsFactors = FALSE)

data = data.frame(number = c(100, 200, 300, 200, 100, 500, 400, 600),
              colour = c('red', 'yellow', 'blue', 'none', 'red', 'green', 'green', 'none'),
              shape = c('triangle', 'none', 'none', 'none', 'square', 'circle', 'square', 'none'),
              stringsAsFactors = FALSE)


data$rule_id = NA

nbrRules = nrow(rules)

for (j in 1:nbrRules){

  data$rule_id[is.na(data$rule_id)
          & (data$number == rules$number[j]
             | is.na(rules$number[j]))
          & ((apply(as.data.frame(data$colour), 
                    1, 
                    function(x) grepl(x, rules$colour[j]))
              & (!grepl("Not", rules$colour[j])))
             | (apply(as.data.frame(data$colour), 
                      1, 
                      function(x) !grepl(x, rules$colour[j]))
                & (grepl("Not", rules$colour[j])))
             | (rules$colour[j] == ""))
          & ((apply(as.data.frame(data$shape), 
                    1, 
                    function(x) grepl(x, rules$shape[j]))
              & (!grepl("Not", rules$shape[j])))
             | (apply(as.data.frame(data$shape), 
                      1, 
                      function(x) !grepl(x, rules$shape[j]))
                & (grepl("Not", rules$shape[j])))
             | (rules$shape[j] == ""))] = rules$rule_id[j]
}

更新

我没有时间实施@alexis_laz他的建议,但他让我意识到,通过反向for (j in nbrRules:1)而不是for (j in 1:nbrRules)循环规则可能会获得一些时间。这允许我从

中删除is.na(data$rule_id)过滤器
data$rule_id[is.na(data$rule_id)
          & (data$number == rules$number[j]
             | is.na(rules$number[j]))
          ....

在我应用它的实际数据集上,它导致了一个小的增益(从3.978148分钟到3.972381分钟)。

我也意识到我的评论是错误的,@ Oliver Frost他的ifelse建议不会导致更多的条件。然而,将代码更改为此导致程序更慢(在我的实际数据集上为4.079141分钟)

for (j in 1:nbrRules){

  data$rule_id = ifelse(is.na(data$rule_id)
                        & (data$number == rules$number[j]
                           | is.na(rules$number[j]))
                        & ((apply(as.data.frame(data$colour), 
                                  1, 
                                  function(x) grepl(x, rules$colour[j]))
                            & (!grepl("Not", rules$colour[j])))
                           | (apply(as.data.frame(data$colour), 
                                    1, 
                                    function(x) !grepl(x, rules$colour[j]))
                              & (grepl("Not", rules$colour[j])))
                           | (rules$colour[j] == ""))
                        & ((apply(as.data.frame(data$shape), 
                                  1, 
                                  function(x) grepl(x, rules$shape[j]))
                            & (!grepl("Not", rules$shape[j])))
                           | (apply(as.data.frame(data$shape), 
                                    1, 
                                    function(x) !grepl(x, rules$shape[j]))
                              & (grepl("Not", rules$shape[j])))
                           | (rules$shape[j] == ""))
                        ,rules$rule_id[j],
                        data$rule_id)
}

0 个答案:

没有答案