我是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}}。
答案 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)