首页 文章

如何制作UDF,以便对数据框中的所有变量进行描述性分析

提问于
浏览
0

我有一个包含数百个不同类变量的数据库:int,factor,logi,date,chr和num,但基本上它们是因子,一个小例子是这样的:

set.seed(123)
dat <- data.frame(
        A = sample(1:10),
        B = rnorm(10, 25, 12),
        C = rnorm(10, 0, 2),
        H = sample(seq(as.Date('1999/01/01'), as.Date('2000/01/01'), by="day"), 10),
        f1 = sample(letters[1:3], 10, replace = TRUE),
        f2 = sample(letters[4:6], 10, replace = TRUE),
        Y = sample(c("yes", "no"), 10, replace = TRUE),
        W = sample(c("Male", "Female"), 10, replace = TRUE),
        Z = sample(c("true", "false"), 10, replace = TRUE))

我想根据两个变量的因素对数据库中的每个变量进行描述性分析,但由于逻辑上一个接一个地制作代码是不切实际的 . 我想创建一个函数,根据我想要的因素的水平选择数据,然后我会根据每个变量的类对它们进行一些描述,如果它是一个因素或字符,将应用一个函数,如果它是数字或集成另一种类型的描述函数 .

我想过做这样的事情:

MyFunction <-function(df, factor1, factor2, ...){
  # Descriptive analysis of the data frame, according to factor 1 level and factor 2
  #
  # Args:
  #    df: name of the data frame
  #    factor1: group (a, b, c)
  #    factor2: subgroup (d, e, f)
  #
  # Returns: 
  #  
  dat <- filter(df, f1 == factor1 & f2 == factor2) 
    apply(dat, 2, ifelse(is.factor == TRUE | is.character == TRUE, describe,
                      ifelse(is.integer == TRUE | is.numeric == TRUE, 
     summary, "other")))
}

但是我在变量的类歧视中得到了一个错误,我无法解决它 .

Error in is.factor == TRUE : comparison (1) is possible only for atomic and list types

这是我解决此任务的最佳方式,但正如有人可以想得更好或者可以提供解决方案,建议或想法 .

非常感谢您的宝贵时间 .

1 回答

  • 0

    使用 apply 可能有点棘手 . 第三个参数需要是一个函数,它接受一个列并对其进行一些处理 . 但是,你给出的表达方式:

    ifelse(is.factor == TRUE | is.character == TRUE, describe,
        ifelse(is.integer == TRUE | is.numeric == TRUE, summary,
          "other")))
    

    isn 't a function. It'只是一个包含多个错误的表达式,因为例如 is.factor 无法与 TRUE 进行比较 . 它需要首先应用于某些东西(即列)以获得一个可以比较的布尔值 .

    相反,你会想写这样的东西:

    MyFunction <-function(df, factor1, factor2, ...){
      dat <- filter(df, f1 == factor1 & f2 == factor2)
      apply(dat, 2, function(x) {
        if (is.factor(x) | is.character(x))
          describe(x)
        else if (is.numeric(x))
          summary(x)
        else "other"
      })
    }
    

    在调用时:

    > MyFunction(dat, "b", "d")
    

    更接近你想要的东西 .

    不幸的是,还有另一个问题 . apply 是's used for matrices. When it'与数据框一起使用的遗留函数,它有将其转换为矩阵(具有相同类型的所有元素)的恶习 . 在这种情况下,它将整个事物转换为字符矩阵,甚至数字值也被视为字符/因子 .

    幸运的是,还有另一个遗留函数,称为 lapply ,适用于数据帧,不会将列转换为不同的类型 . 所以,如果你写:

    MyFunction <-function(df, factor1, factor2, ...){
      dat <- filter(df, f1 == factor1 & f2 == factor2)
      lapply(dat, function(x) {
        if (is.factor(x) || is.character(x))
          describe(x)
        else if (is.numeric(x)) {
          summary(x)
        } else "other"
      })
    }
    

    你最终会得到你想要的输出:

    > MyFunction(dat, "b", "d")
    $A
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
          1       2       3       3       4       5 
    ...
    
    $H
    [1] "other"
    
    $f1
    x 
           n  missing distinct    value 
           2        0        1        b 
    
    Value      b
    Frequency  2
    Proportion 1
    ...
    

    如果你正在使用 library(tidyverse) ,那么你可以用 map 替换 lapply - 它们在这里做同样的事情,但 map 是更现代的功能 .

相关问题