如何创建一个函数,将连续变量仅拆分为相同大小的组

时间:2015-08-06 11:50:21

标签: r dataframe

我想在我的数据框上运行一个函数,它只能找到连续变量,并根据将连续变量划分为2个相等大小的组来添加新的分类变量。我有一个代码,我用它来将一个变量分成组并将其添加为一个新的分类变量,但当我尝试在一个函数中使用它时它不起作用。可能是什么问题?另外,如何避免运行非连续变量? 这是一个玩具数据框:

df <- read.table(text = "         birds    wolfs     
                                    9         7    
                                    8         4    
                                    2         8    
                                    2         3    
                                    8         3    
                                    1         2    
                                    7         1    
                                    1         5    
                                    9         7    
                                    8         7     ",header = TRUE)

我的职责是:

for (i in names(df)) function (x) { as.factor( as.numeric( cut(df$i,2)))  }

1 个答案:

答案 0 :(得分:1)

以下是您的功能中可能存在的一些问题

for (i in names(df)) function (x) { as.factor( as.numeric( cut(df$i,2)))  }
  1. 我会使用df[,i]对列进行子集而不是df$i,因为它未正确评估
  2. 无需匿名函数调用function(x)
  3. 输出未存储在另一个变量中。
  4. 前两个可以轻松修复。我们创建一个空list个对象,length等于'df'(ncol(df))的列数。这可用于存储结果('lst')

    lst <- vector('list', ncol(df))
    

    现在,我们遍历'df'列(假设所有列都是数字)并将cut函数应用于每个列(cut(df[,i],..)。

    for(i in seq_along(df)) {
            lst[[i]] <- as.factor(as.numeric(cut(df[,i], 2)))
     }
    

    我们可以使用'lst'

    的输出分配新列
    df[paste0(names(df), 'new')] <- lst
    

    另一个选项而不是for循环将是lapplylapply的结果可以直接分配给新列。

    df[paste0(names(df), 'new')] <- lapply(df, function(x)
                       factor(cut(x, 2, labels=FALSE)))
    

    根据OP关于过滤numeric列(甚至不包括二进制列)以应用cut的评论。我们使用vapply创建逻辑索引。它循环遍历“df2”列并检查它是否为“数字”(is.numeric(x)),如果它包含0,1(!all(x %in% 0:1))以外的值。

     indx <- vapply(df2, function(x) !all(x %in% 0:1) & is.numeric(x), logical(1L))
    

    使用与上述相同的代码,包括'indx'向量

       lst <- vector('list', ncol(df2[indx]))
       for(i in seq_along(df2[indx])) {
           lst[[i]] <- as.factor(as.numeric(cut(df2[indx][,i], 2)))
        }
      df2[paste0(names(df2)[indx], 'new')] <- lst
    

    lapply

     df2[paste0(names(df2)[indx], 'new')] <- lapply(df2[indx],
                      function(x) factor(cut(x, 2, labels=FALSE)))
    

    数据

    set.seed(24)
    df1 <- data.frame(col1=sample(0:1, 10, replace=TRUE),
               col2=rnorm(10), col3=letters[1:10])
    #df - OP's dataset
    
    df2 <- cbind(df1, df)