R中用户定义函数的问题

问题描述 投票:0回答:1

我试图将数据框中变量的数据类型更改为'factor',如果它们是'character'。我试图使用如下的示例数据来复制问题

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循环和条件完美配合。当我试图通过围绕它编写一个函数来概括它时,就会出现问题。

请帮忙。我错过了什么?

r function
1个回答
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,其中每个(列表)元素需要具有相同的长度,您可以方便地循环数据帧的所有列并将函数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语法也许是值得的

library(tidyverse)
df2 %>% 
  mutate_if(is.character, as.factor) %>% 
  str()
© www.soinside.com 2019 - 2024. All rights reserved.