【问题标题】:R how to keep top levels and change all the other levelsR如何保持顶级并更改所有其他级别
【发布时间】:2016-07-26 06:42:34
【问题描述】:

我不是 R 专家...

在我的训练数据中,有一个名为 Source 的字段有 30 个级别,我只想保留前 2 个级别,因为它们占多数,并且需要将所有其他 28 个级别更改为“其他” .这样我以后应用 One-Hot Encoding 会更方便。

我在这里检查了解决方案:Solution 1Solution 2

我还是被卡住了……

以下是我尝试过的主要解决方案:

train 是原始训练数据,x_train 只是一个副本。 Source 是一个因子变量。 前 2 个级别是 'S122' 级别 1 和 'S133' 级别 8

试试 1

这里我使用which,所以我不需要先将因子转换为字符。事实上,在使用which之前,我尝试过将因子转换为字符。结果是一样的,没用....在这里运行代码后,没有任何改变,只是增加了1个级别,称为'Other'...

x_train <- train
levels(x_train$Source) <- c(levels(x_train$Source), "Other")
x_train$Source[which((x_train$Source != 'S122') && (x_train$Source != 'S133'))] <- 'Other'
str(x_train$Source)

同时,在这种情况下,我没有使用像revalue()这样的方法,因为有28个级别需要更改,我不想在一个方法中写入28个值......

试试 2

然后,我改用一种非常简单的方式,迭代……我也尝试了while循环,也没有用。

x_train <- train
for (i in 1:30) {
  if (i == 1 || i == 8) {
    next
  }
  levels(x_train$Source)[i] <- 'Other'
}

使用此方法后,并不是所有的28个级别都会改变,我意识到,虽然这些级别的值已经改变,但总级别的长度也在改变,索引也会改变。这就是为什么我改为 while 循环但它仍然没有工作....

因此,我有什么办法只保留前 2 个级别并将所有其他级别更改为“其他”?

【问题讨论】:

  • 您解决了这个问题吗?如果有,请分享,如果没有,请加reproducible example
  • 是的,我解决的方法很简单,但是看起来很傻,我今天下班后分享~

标签: r r-factor


【解决方案1】:

这不是一个可重复的示例,因为您没有提供数据,但假设您的因子是火车的一部分,您可以使用。

levels(train$source) <-c("S122", "S133", rep("Other",3))

例如,想象一下泰坦尼克号的数据。

titanic <- reshape2::melt(Titanic)
head(titanic)
  Class    Sex   Age Survived value
1   1st   Male Child       No     0
2   2nd   Male Child       No     0
3   3rd   Male Child       No    35
4  Crew   Male Child       No     0
5   1st Female Child       No     0
6   2nd Female Child       No     0

现在,假设我想重新标记因子,使最高的两个因子在一个类中,而其他因子在另一个类中。我不需要任何 for 循环。我只是写

 levels(titanic$Class) <-c("High", "High", "Low", "Low")

现在当我查看我得到的级别时

titanic
   Class    Sex   Age Survived value
1   High   Male Child       No     0
2   High   Male Child       No     0
3    Low   Male Child       No    35
4    Low   Male Child       No     0
5   High Female Child       No     0
6   High Female Child       No     0

【讨论】:

  • 这是一个很好的灵感。虽然我会选择这个作为解决方案,但需要纠正一件事,levels(train$source) &lt;-c("S122", rep("Other",6), "S133", rep("Other",22))。因为在我的情况下,“S133”是 8 级,但它有前 2 个计数,“S122”是 1 级,它有前 1 个计数,我需要将“S122”和“S133”之间的那些级别更改为“其他” ,并将S133之后的也改为“Other”。
  • 是的,看起来不错。下次,您可以通过分享minimal dataset which resembles your problem 来帮助想要帮助您的人。这样,我就会知道你的因素水平的顺序。
【解决方案2】:

最后,我解决了这个问题,但解决方案不是很聪明。所以,如果这个问题有更好的解决方案,请随时在此处发布

让我们回忆一下我在问题中提到的主要部分:

x_traintrain 的副本。

x_train$Source 有 30 个级别,level1 是 'S122' 而 level8 是 'S133',我只想保留这 2 个级别并设置其他 28 个级别作为“其他”。

如果您仍然不清楚这个描述,这里是示例:

原始 x_train$Source 30 个关卡

S122, S123, S124.., S133, S134,....

最终的 x_train$Source 级别

S122、其他、S133

我的问题是如何得到最终结果,如何将30个级别变成3个级别

解决办法如下:

x_train <- train
summary(x_train$Source)
levels(x_train$Source)[2] <- 'Other'
for (i in 3:7) {
  levels(x_train$Source)[3] <- 'Other'
}
summary(x_train$Source)
for (j in 1:22) {
  levels(x_train$Source)[4] <- 'Other'
}
summary(x_train$Source)

如你所见,在代码中,有硬编码部分,不好。

所以,如果有更好的解决方案,非常欢迎在这里发布!

【讨论】:

  • Cherry,请查看我对这个问题的编辑,阐明为什么最好使用我的解决方案。
  • 嗨Shayaa,非常感谢您耐心修改您的解决方案,现在我明白您的意思了。刚刚在您的解决方案下添加了一条评论,以使其适合我的情况。但是您的解决方案是一个很好的灵感,对我来说是一次很好的学习经历。非常感谢!
猜你喜欢
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-25
  • 2019-12-09
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
相关资源
最近更新 更多