【问题标题】:change name of specific levels in factor更改因子中特定级别的名称
【发布时间】:2015-03-05 11:55:31
【问题描述】:

我正在处理的数据框包含许多因素。从 mtcars (cyl, vs, am, gear, carb) 中获取分类变量。

head(mtcars[c("cyl","vs","am","gear","carb")])
                  cyl vs am gear carb
Mazda RX4           6  0  1    4    4
Mazda RX4 Wag       6  0  1    4    4
Datsun 710          4  1  1    4    1
Hornet 4 Drive      6  1  0    3    1
Hornet Sportabout   8  0  0    3    2
Valiant             6  1  0    3    1

目前我有两个嵌套的 for 循环来提取在特定因素中出现的时间少于 10% 的级别,并将其分配给新的级别名称。所以我想将因子中的那些 levsl 分配给一个名为 guz 的新级别。有没有优雅的 wqy 来做到这一点?

输出将是一个数据框,其中对于everz 因子(假设数据集中的上述列是因子),属于发生少于10 次的级别的那些行被归于新级别guz。以碳水化合物中的第 2 级为例……它只发生一次(好吧,超过 10%,但想象一下它会是这种情况),然后在这个 fdactor 中分​​类这个级别(以及在这个因素中为真的所有其他级别)进入一个新的关卡名称guz。新的碳水化合物列将是 4,4,1,1,guz,1。

50% 阈值的输出将是

head(mtcars[c("cyl","vs","am","gear","carb")])
                  cyl vs am gear carb
Mazda RX4           6  0  1    4    guz
Mazda RX4 Wag       6  0  1    4    guz
Datsun 710          guz  1  1    4    1
Hornet 4 Drive      6  1  0    3    1
Hornet Sportabout   guz  0  0    3    guz
Valiant             6  1  0    3    1

【问题讨论】:

  • 你可能需要使用table,假设df1data.framelapply(df1, function(x) {x1 <- 100*prop.table(table(x)); names(x1)[x1 <10]})
  • 您的问题需要澄清一下。所以在有 32 行的 mtcars 中,你想将其中一列变成一个因子,然后重新分类,以便将任何低于数据 10%(本例中为 3.2)的级别重命名为“guz”?跨度>
  • 我想将所有这些行变成...sry 列变成因子,然后将那些出现少于 10 次的级别排除到称为 guz 的新级别中。所以不要将它们完全删除,只需更改关卡的名称即可。
  • 您的预期结果是?对于mtcars
  • 我不明白你的输出。马自达 RX4 的 cyl=6,有 7 行 cyl=6,不到 50% 的行,那么肯定也应该是“guz”吗?还是该示例输出仅用于 head(mtcars) 作为输入?

标签: r dataframe categorical-data


【解决方案1】:

首先让mtcars 中的列变成明确的因子:

cols = c("vs","am","gear","cyl", "carb")
for(col in cols){mtcars[,col]=factor(paste0(col,mtcars[,col]))}

现在编写一个函数,该函数接受一个因子并返回一个因子,该因子具有根据需要重新分类的级别。使用标签和阈值使其灵活:

thresh_factor = function(F, thresh=0.1, label="guz"){
         n=length(F)
         t=table(F)
         under=t<(n*thresh)
         levels(F)[under]=label
         F}

现在可以测试了:

> thresh_factor(factor(1:20))
 [1] guz guz guz guz guz guz guz guz guz guz guz guz guz guz guz guz guz guz guz
[20] guz
Levels: guz

它们都变成了guz,因为每一个 1:20 都是独一无二的。更多测试:

> thresh_factor(mtcars$carb)
 [1] carb4 carb4 carb1 carb1 carb2 carb1 carb4 carb2 carb2 carb4 carb4 guz  
[13] guz   guz   carb4 carb4 carb4 carb1 carb2 carb1 carb1 carb2 carb2 carb4
[25] carb2 carb1 carb2 carb2 carb4 guz   guz   carb2
Levels: carb1 carb2 guz carb4

那里的一些关卡已被替换。另一个测试:

> thresh_factor(mtcars$cyl)
 [1] cyl6 cyl6 cyl4 cyl6 cyl8 cyl6 cyl8 cyl4 cyl4 cyl6 cyl6 cyl8 cyl8 cyl8 cyl8
[16] cyl8 cyl8 cyl4 cyl4 cyl4 cyl4 cyl8 cyl8 cyl8 cyl8 cyl4 cyl4 cyl4 cyl8 cyl6
[31] cyl8 cyl4
Levels: cyl4 cyl6 cyl8

而且它们都没有被替换。看起来不错。现在遍历所有列:

> for(col in cols){mtcars[,col]=thresh_factor(mtcars[,col])}

只是为了再次使用您的样本输出进行测试,使用数字因子水平和 50% 阈值:

> rm(mtcars) # start fresh
> mtcars=head(mtcars) # first 6 rows for test
> for(col in cols){mtcars[,col]=factor(mtcars[,col])} # convert columns to factors

现在运行我的代码:

> for(col in cols){mtcars[,col]=thresh_factor(mtcars[,col],thresh=0.5)}
> head(mtcars[c("cyl","vs","am","gear","carb")])
                  cyl vs am gear carb
Mazda RX4           6  0  1    4  guz
Mazda RX4 Wag       6  0  1    4  guz
Datsun 710        guz  1  1    4    1
Hornet 4 Drive      6  1  0    3    1
Hornet Sportabout guz  0  0    3  guz
Valiant             6  1  0    3    1

这看起来像您的预期输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2020-03-15
    相关资源
    最近更新 更多