仅当列尊重条件时才应用函数

时间:2016-10-31 15:07:14

标签: r function class loops if-statement

我是R的新手,我正在努力学习基础知识。我正面临一个小问题,我无法在网上找到解决方案。

我想做什么:如果data.frame尊重条件(class = factor)

,请为lower = function(x) { data.frame(tolower(as.matrix(x))) } 中的所有列写一个小写的函数

此代码有效,但对于我的所有列:

lower = function (x) { 
  for (i in 1:length(x)) {
    if (class(i)=="factor") {
         data.frame(tolower(as.matrix(x))) 
    }
  }
}

我需要更多这样的东西,但它不起作用:

x

data.frame是我的{{1}}。

2 个答案:

答案 0 :(得分:1)

你的尝试很接近,但回归是棘手的部分。由于没有样本数据,以下是使用iris并改为大写的示例:

as.data.frame(lapply(head(iris), function(x){
  if(class(x) == "factor"){
    return(toupper(x))
  } else{
    return(x)
  }
}))

lapply是循环列表数据的有效方式(而data.frame本身就是一个列表)。转换回data.frame需要as.data.frame

但是,有更好的工具可以避免自己编写,包括来自mutate_if的{​​{1}}:

dplyr

这两个都回归:

head(iris) %>%
  mutate_if(is.factor, toupper)

答案 1 :(得分:1)

请注意,以下问题的解决方案会将因子列作为因子返回,并且不会重新排序因子级别。

  

问题中的方法可以重新排序因子水平,因为那样   代码将因子列更改为字符,然后返回到因子   使用默认排序(可能不是初始排序)。   例如,这表示如果应用tolower会发生什么   直接到一个因素:

fac <- factor(c("One", "None", "Two"), levels = c("One", "Two", "None"))

fac
## [1] One  None Two 
## Levels: One Two None

factor(tolower(fac)) # order of levels has changed!
## [1] one  none two 
## Levels: none one two
     

特别是,这意味着sort(fac)不对应   sort(factor(tolower(fac)))中的顺序。

我们现在讨论一些没有重新排序问题的替代解决方案。

1)创建一个函数lc_lev,它可以降低因子的个案水平,并通过不变的因子传递输入。然后将其放在输入的列上 - 这里我们使用内置的CO2 - 并将其更改回相同形状的data.frame:

lc_lev <- function(x) {
  if (is.factor(x)) levels(x) <- tolower(levels(x))
  x
}

replace(CO2, TRUE, lapply(CO2, lc_lev))

1a)这也有效:

CO2[] <- lapply(CO2, lc_lev)

2)另一种方法是使用S3。如果输入是因子,则通用(第一行)调度到因子方法,否则调度到默认方法:

lc_lev2 <- function(x, ...) UseMethod("lc_lev2")
lc_lev2.factor <- function(x) { levels(x) <- tolower(levels(x)); x }
lc_lev2.default <- identity

CO2[] <- lapply(CO2, lc_lev2)