R中的数字比较结果不正确

时间:2013-06-10 22:29:52

标签: r dataframe apply

我希望在R中的数据框上执行这种简单的分类。类别是1,2,3,4和-1。我希望将此计算的结果添加到数据框中的新列。 “oldCol”是数据框中已有的列的名称。

DF$newCol <- apply(DF, 1, function(row) {
    if (row[["oldCol"]] > 10.0)
    {result1 <- 4.0}
    else if (row[["oldCol"]] > 2.0 && row[["oldCol"]] <= 10.0) 
    {result1 <- 3.0}
    else if (row[["oldCol"]] > 0.5 && row[["oldCol"]] <= 2.0) 
    {result1 <- 2.0}
    else if (row[["oldCol"]] > 0.0 && row[["oldCol"]] <= 0.5) 
    {result1 <- 1.0}
    else
    {result1 <- -1.0}
    return(result1)
})

我的问题:代码确实创建了一个新列,但其中的值不正确!使用这个确切的代码,超过10的数字被正确分类为类4,但所有其他行包含-1。为什么?算法非常简单,这真让我烦恼。

另外,有更优雅的方法吗?

2 个答案:

答案 0 :(得分:3)

您的代码适合我:

DF <- data.frame(oldCol=c(-1,0.25,1,5,12))

DF$newCol <- apply(DF, 1, function(row) {
    if (row[["oldCol"]] > 10.0)
    {result1 <- 4.0}
    else if (row[["oldCol"]] > 2.0 && row[["oldCol"]] <= 10.0) 
    {result1 <- 3.0}
    else if (row[["oldCol"]] > 0.5 && row[["oldCol"]] <= 2.0) 
    {result1 <- 2.0}
    else if (row[["oldCol"]] > 0.0 && row[["oldCol"]] <= 0.5) 
    {result1 <- 1.0}
    else
    {result1 <- -1.0}
    return(result1)
})

结果:

##   oldCol newCol
## 1  -1.00     -1
## 2   0.25      1
## 3   1.00      2
## 4   5.00      3
## 5  12.00      4
##

另一种选择:

DF <- transform(DF,
        newCol=as.numeric(as.character(cut(oldCol,
          breaks=c(-Inf,0,0.5,2,10,Inf),
          labels=c(-1,1:4)))))

或:

library("plyr")
DF <- mutate(DF,
        tmpCol=cut(oldCol,
           breaks=c(-Inf,0,0.5,2,10,Inf),labels=FALSE),
        newCol=ifelse(tmpCol=="1",-1,as.numeric(tmpCol)-1))

答案 1 :(得分:2)

这是一个稍微简单的答案,也考虑到你正在处理double,因此会出现精确问题:

cuts = c(0, 0.5, 2, 10) + 1e-8 # example precision, pick appropriately for your problem
                               # (possibly pick a different precision for each cut point)
DF$newCol = findInterval(DF$oldCol, cuts)