首页 > 解决方案 > R - order() 每隔一次运行就会弄乱顺序

问题描述

我正在处理学校的强制性作业,并尝试根据其中一列的顺序对我的数据框进行排序(请参阅代码)。它第一次运行得很好,但是下次我运行代码时,顺序就搞砸了。现在,每隔一次我运行代码时,它就被正确地订购了一次,而下一次就搞砸了。可能只是一些小错误,或者对 R 中变量如何工作的一些误解,有人可以帮忙吗?

如果你运行代码,你可以很容易地看到绘图从一条漂亮的红色曲线变为蜘蛛网混乱,从一个运行到另一个运行。

dataset <- read.table("https://www.uio.no/studier/emner/matnat/math/STK2100/v19/mandatoryassignments-exam/data.dat")

set.seed(1)
samplesize <- round(nrow(dataset)/2)
samp <- sample(seq_len(nrow(dataset)), size = samplesize)
training <- dataset[samp, ]
test <- dataset[-samp, ]
training <- training[order(x),]
test <- test[order(x),]

attach(training)
library(caret)
ctrl <- trainControl(method="cv",number = 5)
knn <- train(y ~ x, data = training, metric = "Rsquared", method = "knn", trControl = ctrl)

knn
y.pred = predict(knn,newdata = x)
plot(training)
lines(x, y.pred, col='red')

我通过交换解决了问题

training <- training[order(x),]
#with
training <- training[order(training$x),]

标签: rsorting

解决方案


您遇到的情况可能是由多个attach语句引起的。让我们举个例子来尝试找出问题所在。

set.seed(1)
n <- 6
DT <- data.frame(letters = LETTERS[1:6], numbers = 6:1, x = sample(1:6))
head(DT)

  letters numbers x
1       A       6 2
2       B       5 6
3       C       4 3
4       D       3 4
5       E       2 1
6       F       1 5

现在我假设 x 包含在您的数据中,但更有可能您在某处存储了一个变量。它不包含在您的代码中,所以我只是猜测,无论如何它都是length <= nrow(DT).

问题1:attach(x)

现在你说你的问题每隔一段时间就会发生一次,所以这似乎是最可能的原因。从您的代码中,如果 x 包含在 中DT,则您在运行代码之前附加了 data.frame:

attach(DT)
DT <- DT[order(x),]
head(DT)

  letters numbers x
5       E       2 1
1       A       6 2
3       C       4 3
4       D       3 4
6       F       1 5
2       B       5 6

这正确地订购了我们的 data.frame。

现在,如果您再次运行代码,通常人们会通过运行来清除内存rm(list=ls()),以清除所有变量。如果您进行订购应该可以正常工作,但大多数 R 用户建议不要使用attach,让我们快速说明一个原因:

rm(list=ls()) #remove everything we can see
x
print(x)

[1] 2 6 3 4 1 5

令大多数新 R 用户感到惊讶的是,“x”“字母”和“数字”仍然作为变量存在。为了删除这些,detach(DT)即使在运行之后也必须运行rm(list=ls())attach只要记住这一点就可以使用,并且数据不会太大。

现在考虑重新运行代码的可能性。您attach的声明在您的order声明之后,因此每次运行都会发生以下事情:

  1. 第一次运行:你得到一个错误,因为没有附加x.
  2. 没有错误,因为x已经附加DT了,现在要排序,然后再附加
  3. 在第三次运行时,如果您没有 detached DT,则 sortedx将附加在pos = 2,因此将用于对您的数据进行排序(但x已经排序,所以什么也没有发生)

对于 (1) 请注意,在您的代码中

training <- training[order(x),]
test <- test[order(x),]

attach(training)

因此,附加在订单之后,这可能会在您第一次运行时导致错误。

对于 (2 - 3),更容易可视化:再次运行代码 2 次(在第一次运行之后),将类似于运行下面的代码。这可视化了“每秒钟的问题”。在代码中,我删除了不太相关的错误和警告,以提高可读性(但有多个)

for(i in 1:3){ 
    try(
        {
            #Create dataset
            set.seed(1)
            n <- 6
            DT <- data.frame(letters = LETTERS[1:6], numbers = 6:1, x = sample(1:6))
            print(x)
            DT <- DT[order(x),] #order data (note the first time it is not attached, eg. produces an error)
            print(DT)
        }
    )
    attach(DT) #attach the current data
}

顺序错误(x):找不到对象“x”

第二次打印:(第一次失败)

>x
2 6 3 4 1 5
>DT
  letters numbers x
5       E       2 1
1       A       6 2
3       C       4 3
4       D       3 4
6       F       1 5
2       B       5 6

第三次打印:

>x
1 2 3 4 5 6
>DT
  letters numbers x
1       A       6 2
2       B       5 6
3       C       4 3
4       D       3 4
5       E       2 1
6       F       1 5

我们第一次得到一个错误,因为x不存在(未找到)。下一次从 附加 x 时DT,一切正常。第三次,从排序中附加了 x DT,没有发生任何事情。

请注意,在第三次打印中对输出进行了x排序,因为它是x从第二次打印中附加的。因此对它进行排序不会改变它的顺序。这很可能是你的问题。

现在我已经多次附加数据,重要的一点是,许多有经验的 R 用户避免使用attach它产生的所有警告的原因。让我们尝试再次运行附加:

>attach(DT)

The following objects are masked from DT (pos = 3):

    letters, numbers, x

The following objects are masked from DT (pos = 4):

    letters, numbers, x

The following objects are masked from DT (pos = 5):

    letters, numbers, x

The following object is masked from package:base:

    letters

此警告告诉您,已运行多个附加,并且多个变量以相同的名称存在(当前保存相同的数据)。它甚至告诉我们有多少:pos = 5,基本上有4层变量和全局环境:

  1. 全球环境(pos = 1)
  2. 第四个附件,我们刚刚运行的(pos = 2)
  3. 循环中的第三个附件(pos = 3)
  4. 循环中的第二个附件(pos = 2)
  5. 循环中的第一个附件(pos = 3)

detach这是在您完成使用附加数据后要记住的另一个原因(如果您附加了多次,则可以detach重复使用)。pos - 1

replicate(4, detach(DT))

原则上,如果您有足够的内存,并且记住了detach您的数据,那么一切都会正常进行。但是应该记住,使用rm(list = ls())不会分离的框架,如下图所示:

attach(DT)
rm(list=ls())
x

>2 6 3 4 1 5

因此,分离是任何使用attach.

对于您的特定问题,向上移动并在底部attach(training)添加向下应该可以解决问题。detach(training)


推荐阅读