首页 > 解决方案 > 我可以编写一个函数来重新评估一个因素的水平吗?

问题描述

我的数据框中有一列“lg_with_children”,它有 5 个级别,“一半”、“普通话”、“上海话”、“其他”、“N/A”和“不重要”。我想将 5 个级别压缩到只有 2 个级别,“上海人”和“其他”。

为了做到这一点,我使用了 plyr 包中的 revalue() 函数来成功地重命名关卡。我使用了下面的代码,它运行良好。

data$lg_with_children <- revalue(data$lg_with_children,
                             c("Mandarin" = "Other"))
data$lg_with_children <- revalue(data$lg_with_children,
                             c("Half and half" = "Other"))
data$lg_with_children <- revalue(data$lg_with_children,
                             c("N/A" = "Other"))
data$lg_with_children <- revalue(data$lg_with_children,
                             c("Not important" = "Other"))

为了稍微压缩代码,我在重新评估关卡并尝试编写函数之前返回了数据。在研究了如何编写自己的函数后,我尝试了以下方法(我对此很陌生)。

revalue_factor_levels <- function(df, col, source, target) {df$col <- revalue(df$col, c("source" = "target"))}

我故意保留了 df、col、source 和 target 泛型,因为我需要以同样的方式重新评估其他一些列。

接下来,我尝试运行填充 args 的代码并收到以下消息:

警告信息

我不太确定问题是什么。我尝试了以下代码调整,但仍然没有。

revalue_factor_levels <- function(df, col, source, target) {df$col <- revalue(df$col, c(source = target))}

任何指导表示赞赏。谢谢。

标签: rfunctionplyr

解决方案


可以编写函数来重新编码级别 - 最简单的方法可能是直接更改级别levels(fac) <- list(new_lvl1 = c(old_lvl1, old_lvl2), new_lvl2 = c(old_lvl3, old_lvl4))

但是已经有几个开箱即用的功能。我通常使用forcats包来操纵因素。

fct_recodeforcats包裹中签出。链接到文档

还有其他功能可以帮助您 - 查看下面的评论。

现在,至于为什么您的代码不起作用:

  • df$col查找字面上名为 的列col。解决方法是改为这样做df[[col]]
  • 不要忘记df在函数结束时返回
  • c(source = target)将创建一个包含一个名为 的元素的向量"source",而不管变量中发生了什么source。解决方案是分两步创建向量c(source = target)
revalue_factor_levels <- function(df, col, source, target) {
  to_rename <- target
  names(to_rename) <- source
  df[[col]] <- revalue(df[[col]], to_rename)
  df
}

返回 df 意味着语法是:

data <- revalue_factor_levels(data, "lg_with_children", "Mandarin", "Other")

我喜欢将数据作为第一个参数并返回修改后的数据的函数,因为它们是可管道的。

library(dplyr)

data <- data %>%
  revalue_factor_levels("lg_with_children", "Mandarin", "Other") %>%
  revalue_factor_levels("lg_with_children", "Half and half", "Other") %>%
  revalue_factor_levels("lg_with_children", "N/A", "Other")

尽管如此,使用forcats起来更容易,并且不太容易在边缘情况下中断。

编辑:

没有什么可以阻止您使用forcats和创建自定义函数。例如,这更接近您想要实现的目标:

revalue_factor_levels <- function(df, col, ref_level) {
  df[[col]] <- forcats::fct_others(df[[col]], keep = ref_level)
  df
}

# Will keep Shanghaisese and revalue other levels to "Other". 
data <- revalue_factor_levels(data, "lg_with_children", "Shanghainese")

推荐阅读