【问题标题】:Compare column types between two tables比较两个表之间的列类型
【发布时间】:2018-06-18 10:50:39
【问题描述】:

如果我有两个表 (File1) 和 (File2)

> dput(File1)
structure(list(Column.1 = structure(1:3, .Label = c("Row 1", 
"Row 2", "Row 3"), class = "factor"), Column.2 = c(NA, NA, NA
), Column.3 = c(NA, NA, NA), colNames = c(TRUE, TRUE, TRUE)), class = "data.frame", row.names = c(NA, 
-3L))
> dput(File2)
structure(list(Column.1 = structure(1:3, .Label = c("Row 1", 
"Row 2", "Row 3"), class = "factor"), Column.2 = c(1, 2, 34), 
    Column.3 = c(NA, NA, NA), colNames = c(TRUE, TRUE, TRUE)), class = "data.frame", row.names = c(NA, 
-3L))

我想确认文件 1 和文件 2 之间的列名、列类型以及行数和列数,如果它们都相同则返回 TRUE,否则返回 FALSE,我该如何添加这段代码是我写的?

我尝试了Compare column types between two data frames 中的一些答案,但我只是在寻找正确或错误的答案。这是我当前的代码。

check_file <- function(File1 , File2) {
  if (!nrow(File1) == nrow(File2)) {
    print("Non matching number of rows")
    return(FALSE)

  } else if (!ncol(File1) == ncol(File2)) {
    print("non matching number of columns")
    return(FALSE)
  } else if (length(grep("FALSE", names(File1) == names(File2)))>0){
    print("Non matching names of columns")
    return(FALSE)
  }else if (!class(File1)==class(File2)){
      print("Non matching column types")
    }
  return(TRUE)
}


check <- check_file(File1, File2)


if (check) {
  return(TRUE)
} else{
  return(FALSE)
}

我认为剩下的就是类型。例如,在 dput File 2 Column 2 中有数字,而 File 1 有 NA。它们不必是相同的数字,但它需要返回 false,因为它是 NA。如果文件 1 有 3,2,564,它应该返回 TRUE。

【问题讨论】:

    标签: r validation difference


    【解决方案1】:

    第一个解决方案:

    all(                                                 # check if all ar T
      sapply(                                            # 
        c(colnames, dim, function(x){sapply(x, class)}), # functions to apply
        function(f) all(f(File1) == f(File2))            # check 4 equality  
        )                                                #
      )                                                  #
    [1] FALSE                                            # numeric != logical
    #all(              
    #  sapply(
    #    c(colnames, dim, function(x){sapply(x, class)}), 
    #    function(f) all(f(File1) == f(File1))
    #    )
    #  )
    #[1] TRUE
    

    [编辑 0] dim 而不是 nrow。 [编辑 1]

    第二种解决方案

    如果两列有不同的类,但一列是空的 - 返回TRUE

    数据集

    df1 <- data.frame(Column1 = paste("Row", 1:3), Column2 = 1:3,
                      Column3 = NA, colNames = TRUE)
    
    df2 <- df1; df2[, 2] <- c(1, 2, 34)
    
    df3 <- data.frame(Column1 = paste("Row", 1:3), Column2 = NA, Column3 = NA)
    
    df4 <- df3
    
    df4[, 2] <- "ddd"
    df4[, 3] <- c(3, 4, 2)
    
    df1
    #  Column1 Column2 Column3 colNames
    #1   Row 1       1      NA     TRUE
    #2   Row 2       2      NA     TRUE
    #3   Row 3       3      NA     TRUE
    
    df2
    #  Column1 Column2 Column3 colNames
    #1   Row 1       1      NA     TRUE
    #2   Row 2       2      NA     TRUE
    #3   Row 3      34      NA     TRUE
    

    注意class(df1[,2]) == "integer"class(df2[,2]) == "numeric"

    df3
    #  Column1 Column2 Column3
    #1   Row 1      NA      NA
    #2   Row 2      NA      NA
    #3   Row 3      NA      NA
    
    df4
    #  Column1 Column2 Column3
    #1   Row 1     ddd       3
    #2   Row 2     ddd       4
    #3   Row 3     ddd       2
    

    函数定义

    identical_df <- function(x, y){
        ifelse(!identical(colnames(x), colnames(y)), FALSE,
               ifelse(!identical(dim(x), dim(y)), FALSE,
                      all((sapply(x, class) == sapply(y, class)) |
                          (apply(is.na(x), 2, prod) | apply(is.na(y), 2, prod))
                         )
                      )
               )
    }
    

    df1,df2上测试函数; df1df3df3, df4

    identical_df(df1, df1) # identical 
    #[1] TRUE              #
    identical_df(df1, df2) # class(df1[,2]) != class(df2[,2])
    #[1] FALSE
    identical_df(df1, df3) # dim(df1) != dim(df3)
    #[1] FALSE
    identical_df(df3, df4) # different classes for cols 2, 3
    #[1] TRUE              # however both cols 2, 3 in df3 are empty (NAs)
    # ==============================================================================
    # Evaluation of 
    # all((sapply(x, class) == sapply(y, class)) |
    #     (apply(is.na(x), 2, prod) | apply(is.na(y), 2, prod))
    # )
    # for x = df3, y = df4
    #
    # +-------------------------------------------------+--------+--------+--------+
    # |Expression                                       |Column1 |Column2 |Column3 |
    # +-------------------------------------------------+--------+--------+--------+
    # |sapply(x, class) == sapply(y, class)   +--------<|TRUE    |FALSE   |FALSE   |
    # +                                       |         +--------+--------+--------+
    # |apply(is.na(x), 2, prod)               |     +--<|0       |1       |1       |
    # +                                       OR-+<OR   |        |        |        |
    # |apply(is.na(y), 2, prod)               |  |  +--<|0       |0       |0       |
    # |                                       |  |      |        |        |        |
    # |                                       |  +----->|FALSE   |TRUE    |TRUE    |
    # |                                       |         |        |        |        |
    # |                                       |         +--------+--------+--------+
    # |                                       +-------->|TRUE    |TRUE    |TRUE    |
    # +-------------------------------------------------+--------+--------+--------+ 
    

    【讨论】:

    • 感谢 ubuntun。如何添加一条语句,如果没有要尝试的值(但有列名),则运行 'TRUE' 而不是 FALSE
    • 您的意思是“有两列,其中第一列包含一些值,而第二列是空的(填充有NAs,这是任何data.frame 最可能出现的情况)”?
    • 可能有一个标题行,列标题,第 1 行和 A 列可能会被填充,但其他所有内容都是 NA。 (在文件 1 中)
    • 好的,我更新了我的答案,但它与@DJV 回答的逻辑很相似。
    【解决方案2】:

    您可以使用identical 函数。

    用你的功能:

    check_file <- function(File1 , File2) {
      if (identical(summary.default(File1)[,3],
                    summary.default(File2)[,3]) == FALSE) {
        print("Not Same Str")
        return(FALSE)}
    
      if (identical(class(File1), class(File2)) == FALSE) {
        print("Not Same Class")
        return(FALSE)}
    
      if (identical(names(File1), names(File2)) == FALSE) {
        print("Non matching number of rows")
        return(FALSE)}
    
      if (identical(dim(File1), dim(File2)) == FALSE) {
        print("non matching number of columns")
        return(FALSE)
      } else if (length(grep("FALSE", names(File1) == names(File2)))>0){
        print("Non matching names of columns")
        return(FALSE)
      }else if (!class(File1)==class(File2)){
        print("Non matching column types")
      }
      return(TRUE)
    }
    

    在您的 data.frames 上进行测试:

    File1 <- structure(list(Column.1 = structure(1:3, .Label = c("Row 1", 
                                                        "Row 2", "Row 3"), class = "factor"), Column.2 = c(NA, NA, NA
                                                        ), Column.3 = c(NA, NA, NA), colNames = c(TRUE, TRUE, TRUE)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                          -3L))
    File2 <-
    structure(list(Column.1 = structure(1:3, .Label = c("Row 1", 
                                                        "Row 2", "Row 3"), class = "factor"), Column.2 = c(1, 2, 34), 
                   Column.3 = c(NA, NA, NA), colNames = c(TRUE, TRUE, TRUE)), class = "data.frame", row.names = c(NA, 
                                                                                                                  -3L))
    
    check <- check_file(File1, File2)
    check
    
    [1] TRUE
    

    或者行数不匹配:

    df1 <- data.frame(x = 1:20)
    df2 <- data.frame(x = 1:10)
    check <- check_file(df1, df2)
    [1] "non matching number of columns"
    check 
    [1] FALSE
    

    【讨论】:

    • 但是,在我的示例中,工作表 2 中的第 2 列有数字,而工作表 1 没有。那应该返回 FALSE
    • 我正在编辑我的答案。但是,无论如何,我认为可能一系列ifs 会比else if 更准确。
    • 你会有数字和 NA 的情况吗?在同一列中
    • 是的。这个想法是这两个文件应该完全匹配类型
    • 所以如果它是日期和数字,那是错误的。日期和日期为真
    猜你喜欢
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 2012-11-05
    • 1970-01-01
    相关资源
    最近更新 更多