我试图将数据框中变量的数据类型更改为“ factor”(如果它们是“字符”)。我尝试使用以下示例数据来复制问题
a <- c("AB","BC","AB","BC","AB","BC")
b <- c(12,23,34,45,54,65)
df <- data.frame(a,b)
str(df)
'data.frame': 6 obs. of 2 variables:
$ a: chr "AB" "BC" "AB" "BC" ...
$ b: num 12 23 34 45 54 65
我写了下面的函数来实现这一目标
abc <- function(x) {
for(i in names(x)){
if(is.character(x[[i]])) {
x[[i]] <- as.factor(x[[i]])
}
}
}
如果我通过数据帧(df),该函数将正确执行,但仍不会将'character'更改为'factor'。
abc(df)
str(df)
'data.frame': 6 obs. of 2 variables:
$ a: chr "AB" "BC" "AB" "BC" ...
$ b: num 12 23 34 45 54 65
注意:它与for循环和if条件完美配合。当我尝试通过围绕它编写一个函数来概括它时,出现了问题。
请帮助。我想念什么?
答案 0 :(得分:2)
除了@Roland的评论外,您还应该利用R的不错的索引功能,并了解*apply
系列。这样,您可以将代码重写为
change_to_factor <- function(df_in) {
chr_ind <- vapply(df_in, is.character, logical(1))
df_in[, chr_ind] <- lapply(df_in[, chr_ind, drop = FALSE], as.factor)
df_in
}
说明
vapply
遍历列表的所有元素,将函数应用于每个元素并返回给定类型的值(此处为布尔值logical(1)
)。由于R
中的数据帧实际上是lists
,其中每个(列表)元素都必须具有相同的长度,因此您可以方便地在数据帧的所有列上循环并应用函数{{ 1}}。然后is.character
返回带有vapply
值的布尔(逻辑)向量,具体取决于该列是否是字符列。TRUE/FALSE
是lapply
系列的另一个成员,它遍历列表元素并返回一个列表。现在,我们遍历字符列,将*apply
应用于它们,并返回它们的列表,以方便地存储在数据框中的原始位置顺便说一句,如果您查看as.factor
,您会发现str(df)
列已经成为一个因素。这是因为b
自动将字符列转换为字符。为避免这种情况,您需要将data.frame
传递给stringsAsFactors = FALSE
:
data.frame
学习a <- c("AB", "BC", "AB", "BC", "AB", "BC")
b <- c(12, 23, 34, 45, 54, 65)
df <- data.frame(a, b)
str(df) # column b is factor
# 'data.frame': 6 obs. of 2 variables:
# $ a: Factor w/ 2 levels "AB","BC": 1 2 1 2 1 2
# $ b: num 12 23 34 45 54 65
str(df2 <- data.frame(a, b, stringsAsFactors = FALSE))
# 'data.frame': 6 obs. of 2 variables:
# $ a: chr "AB" "BC" "AB" "BC" ...
# $ b: num 12 23 34 45 54 65
str(change_to_factor(df2))
# 'data.frame': 6 obs. of 2 variables:
# $ a: Factor w/ 2 levels "AB","BC": 1 2 1 2 1 2
# $ b: num 12 23 34 45 54 65
语法也很值得
tidyverse