首页 文章

将函数应用于数据框中的每个列,观察每个列的现有数据类型

提问于
浏览
42

我正在尝试获取大型数据框中每列的最小值/最大值,作为了解我的数据的一部分 . 我的第一次尝试是:

apply(t,2,max,na.rm=1)

它将所有内容视为字符向量,因为前几列是字符类型 . 因此,一些数字列的最大值将显示为 " -99.5" .

然后我尝试了这个:

sapply(t,max,na.rm=1)

但它抱怨最大因素没有意义 . ( lapply 是一样的 . )让我感到困惑的是 apply 认为 max 对于因素非常有意义,例如:它为第1列返回"ZEBRA" .

顺便说一句,我看了一下Using sapply on vector of POSIXct,其中一个答案说“当你使用sapply时,你的对象被强制为数字,......” . 这是发生在我身上的事吗?如果是这样,是否有一个不强制的替代应用功能?当然这是一个常见的需求,因为数据框类型的一个关键特征是每列可以是不同的类型 .

4 回答

  • 34

    如果它是一个“有序因素”,事情会有所不同 . 这并不是说我喜欢“有序因素”,我不这么说,只是说某些关系是为“因子”定义的“有序因子”定义的 . 因素被认为是普通的分类变量 . 您正在查看因素的自然排序顺序,这些因素是您的语言环境的字母词汇顺序 . 如果你想为每一列,...日期和因素以及所有列自动强制为“数字”,那么尝试:

    sapply(df, function(x) max(as.numeric(x)) )   # not generally a useful result
    

    或者,如果您想先测试因子并按预期返回:

    sapply( df, function(x) if("factor" %in% class(x) ) { 
                max(as.numeric(as.character(x)))
                } else { max(x) } )
    

    @Darrens的评论确实有效:

    sapply(df, function(x) max(as.character(x)) )
    

    max 确实成功使用了字符向量 .

  • 1

    maxapply 一起使用的原因是 apply 首先将数据帧强制转换为矩阵,而矩阵只能容纳一种数据类型 . 所以你最终会得到一个字符矩阵 . sapply 只是 lapply 的包装器,所以两者都产生相同的错误也就不足为奇了 .

    创建数据框时的默认行为是将分类列存储为因子 . 除非您指定它是有序因子,否则 maxmin 等操作将是未定义的,因为R假设您已创建无序因子 .

    您可以通过指定 options(stringsAsFactors = FALSE) 来更改此行为,这将更改整个会话的默认值,或者您可以在 data.frame() 构造调用本身中传递 stringsAsFactors = FALSE . 请注意,这只是意味着默认情况下 minmax 将采用"alphabetical"排序 .

    或者您可以手动指定每个因素的排序,但我怀疑这是您想要做的 .

    无论如何, sapply 通常会产生一个原子向量,这将需要在很多情况下将所有内容转换为字符 . 解决这个问题的方法如下:

    #Some test data
    d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                    v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)
    
    d[4,] <- NA
    
    #Similar function to DWin's answer          
    fun <- function(x){
        if(is.numeric(x)){max(x,na.rm = 1)}
        else{max(as.character(x),na.rm=1)}
    }   
    
    #Use colwise from plyr package
    colwise(fun)(d)
             v1 v2       v3 v4
    1 0.8478983  j 1.999435  J
    
  • 17

    如果你想学习你的数据 summary (df) 提供最小值,第1个分位数,中位数和平均值,第3个分位数和最大数值列以及因子列最高级别的频率 .

  • 7

    Build 在@ltamar的答案上:
    使用摘要并将输出变为有用的东西!

    library(tidyr)
    library(dplyr)
    
    df %>% 
      summary %>% 
      data.frame %>%
      select(-Var1) %>%
      separate(data=.,col=Freq,into = c('metric','value'),sep = ':') %>%
      rename(column_name=Var2) %>%
      mutate(value=as.numeric(value),
             metric = trimws(metric,'both') 
      ) %>%  
      filter(!is.na(value)) -> metrics
    

    它不漂亮,肯定不会很快,但它完成了工作!

相关问题