我正在try 编写一个函数来删除R中某列中的某个级别

iris_df <- iris
iris_df$Species2 <- iris_df$Species

purrr::map(.x=c("Species","Species2"),variable="setosa", .f=function(x, variable){
  levels(iris_df[,x])[levels(iris_df[,x]) == variable] <- NA
})

我可以运行这个,但是当我通过levels(iris_df$Species)来判断级别时,答案是[1] "setosa" "versicolor" "virginica" ,我本以为setosa级别已经被移除了.有人可以更新代码来修复这个问题吗?

推荐答案

在函数中执行的代码是该函数的内部代码,全局环境不变.如果您想像这样编写带有"副作用"的代码,则需要使用for循环,而不是在函数内部.

variable <- "setosa"
for(sp in c("Species","Species2")) {
  levels(iris_df[[sp]])[levels(iris_df[[sp]]) == variable] <- NA
}

如果您想使用purrr::map,那么您需要您的函数返回一些有用的东西,并且您需要将结果赋值为<-=.虽然在修改数据框的列时使用dplyr::mutate可能更容易:

## reset the sample data
iris_df <- iris
iris_df$Species2 <- iris_df$Species

variable <- "setosa"
iris_df <- iris_df |>  ## note that we assign the result, so iris_df is modified
  mutate(across(c("Species","Species2"), \(x) {
      levels(x)[levels(x) == variable] <- NA
      x ## the function returns the modified column
    }
  ))

如果您想要创建一个更通用的"Drop Level(S)from Column(S)"函数,那么我们可以将这两种方法中的任何一种包装到一个函数中,但您需要传入数据框并将结果赋给相同的数据框或新的数据框:

drop_col_levels_for = function(df, cols, levs) {
  for(i in seq_along(cols)) {
    levels(df[[cols[i]]])[levels(df[[cols[i]]]) %in% levs] = NA
  }
  df
}

drop_col_levels_dplyr = function(df, cols, levs) {
  mutate(df, across(all_of(cols), \(x) {
      levels(x)[levels(x) %in% levs] = NA
      x
    }))
}

drop_col_levels_for(iris_df, c("Species","Species2"), "setosa") |>
  summary()
# Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species         Species2 
# Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100   versicolor:50   versicolor:50  
# 1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300   virginica :50   virginica :50  
# Median :5.800   Median :3.000   Median :4.350   Median :1.300   NA's      :50   NA's      :50  
# Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199                                  
# 3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800                                  
# Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500     

drop_col_levels_dplyr(iris_df, c("Species","Species2"), "setosa") |>
  summary()
## same result

R相关问答推荐

如何从其他前面列中减go 特定列的平均值?

使用R中的gt对R中的html rmarkdown文件进行条件格式设置表的单元格

在ggplot Likert条中添加水平线

x[[1]]中的错误:脚注越界

如何使用`ggplot2::geom_segment()`或`ggspatial::geom_spatial_segment()`来处理不在格林威治中心的sf对象?

在垂直轴中包含多个ggplot2图中的平均值

在for循环中转换rabrame

如何在geom_col中反转条

在ggplot中为不同几何体使用不同的 colored颜色 比例

根据元素和前一个值之间的差值过滤矩阵的元素

`lazy_dt`不支持`dplyr/across`?

使用范围和单个数字将数字与字符串进行比较

为左表中的所有行使用值Fill滚动左连接

自定义gggraph,使geom_abline图层仅在沿x轴的特定范围内显示

R:如果为NA,则根据条件,使用列名模式将缺少的值替换为另一列中的值

将多个变量组合成宽格式

我如何使用tidyselect来传递一个符号数组,比如Pivot_Long?

解析嵌套程度极高的地理数据

在具有条件的循环中添加行

通过分析特定列中的字符串在数据框中创建新的行和列