1

我希望对 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。为什么?算法非常简单,这真的让我很困扰。

另外,有没有更优雅的方法来做到这一点?

4

2 回答 2

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))
于 2013-06-10T22:38:22.753 回答
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)
于 2013-06-10T23:53:34.240 回答