检查变量是否在一对一映射中

时间:2018-09-19 06:28:58

标签: r

假设我在R中有一个数据帧,其中有两个变量,我将分别称为AB。我想检查这两个变量是否在一对一映射中。例如,考虑以下数据帧:

DF <- data.frame(A = c(0,2,0,1,2,1,0,1,1,1),
                 B = c('H','M','H','W','M','W','H','W','W','W'));

DF;
   A B
1  0 H
2  2 M
3  0 H
4  1 W
5  2 M
6  1 W
7  0 H
8  1 W
9  1 W
10 1 W

在此数据框中,通过检查我们可以看到AB之间(与0 = H1 = W和{{ 1}})。我想找到一种方法来使用不需要我检查每个元素的适当2 = M代码对较大的数据帧执行此操作。代码应生成简单明了的声明,以说明指定变量之间是否存在一对一的关系;一个简单的R / TRUE输出应该是理想的。

更新:一些现有的答案在某种程度上给了我一个答案,但是输出比原本应该的要复杂得多。该代码应产生一个简单而清晰的输出,以回答问题。

7 个答案:

答案 0 :(得分:3)

我们可以使用ave编写一个函数,该函数将检查每个组(A)仅存在一个唯一的B值,从而确保一对一的映射。

is_one_to_one_mapping <- function(DF) {
   all(ave(DF$A, DF$B, FUN = function(x) length(unique(x))) == 1)
}

is_one_to_one_mapping(DF)
#[1] TRUE

现在,我们更改一个要检查的元素

DF$A[9] <- 2
is_one_to_one_mapping(DF)
#[1] FALSE

答案 1 :(得分:2)

如果我们要检查'A','B'是否重复,请使用duplicated中的base R

i1 <- duplicated(DF)|duplicated(DF, fromLast = TRUE)

如果需要一个all

,则用TRUE/FALSE包装
all(i1)
#[1] TRUE

可以包装成一个函数

f1 <- function(dat) all(duplicated(dat)|duplicated(dat, fromLast = TRUE))
f1(DF)
#[1] TRUE

答案 2 :(得分:2)

这是使用table函数的相对简单的方法

table(DF)
#output
   B
A   H M W
  0 3 0 0
  1 0 0 5
  2 0 2 0

从这里您可以看到0中的所有A对应于H等中的B

要对此进行正式检查,可以检查列的总和是否匹配列的最大值:

all.equal(colSums(table(DF)), apply(table(DF), 2,  max))
#output
TRUE

答案 3 :(得分:1)

使用tidyverse

DF%>%
   group_by(A,B)%>%
   mutate(result=n(),
          isDubl=ifelse(n()>1,T,F))
# A tibble: 10 x 4
# Groups:   A, B [3]
       A B     result isDubl
   <dbl> <fct>  <int> <lgl> 
 1    0. H          3 TRUE  
 2    2. M          2 TRUE  
 3    0. H          3 TRUE  
 4    1. W          5 TRUE  
 5    2. M          2 TRUE  
 6    1. W          5 TRUE  
 7    0. H          3 TRUE  
 8    1. W          5 TRUE  
 9    1. W          5 TRUE  
10    1. W          5 TRUE  

DF%>%
   group_by(A,B)%>%
   summarise(result=n(),
          isDubl=ifelse(n()>1,T,F))
# A tibble: 3 x 4
# Groups:   A [?]
      A B     result isDubl
  <dbl> <fct>  <int> <lgl> 
1    0. H          3 TRUE  
2    1. W          5 TRUE  
3    2. M          2 TRUE 

答案 4 :(得分:1)

我想知道一个单独的项目是否存在一对一的映射。处理您的示例有助于我发现一些错误,因此感谢您提出问题。

基本思想是创建一个表(x,y)并检查它是否可以是对角线。显然,如果变量“正好如此”布置,则表将是对角线且易于辨别,但在您的情况下,对齐方式有点锯齿:

 table(DF$A, DF$B)

    H M W
  0 3 0 0
  1 0 0 5
  2 0 2 0

为我改正的策略就是按照这些方针

> dfu <- unique(DF)

> table(dfu[ , 1], dfu[ ,2])

   H M W
 0 1 0 0
 1 0 0 1
 2 0 1 0

然后计算行和列的总和。

如果行总和或列总和大于1,则这不是一对一的关系。如果行总和或列总和都不超过1,则映射是一对一的。我最初的错误不是检查双向映射的唯一性。我知道我可以计算特征值来找出相同的东西,但这并不是那么明显,并且在初步测试中要慢得多。

这是我的职责。传递2列或2列的矩阵,则返回TRUE或FALSE

onetoone <- function(w, z){
    if (is.matrix(w)){
        if(dim(w)[2] != 2) stop("need 2 column matrix")
        dfu <- unique(w)
    } else {
        dfu <- unique(cbind(w,z))
    }
    return( !any(rowSums(table(dfu[ , 1], dfu[ , 2])) > 1) &&
            !any(colSums(table(dfu[ , 1], dfu[ , 2])) > 1) )
}  

使用您的数据:

> DF <- data.frame(A = c(0,2,0,1,2,1,0,1,1,1),
+                  B = c('H','M','H','W','M','W','H','W','W','W'));
> onetoone(DF$A, DF$B)
[1] TRUE
> onetoone(as.matrix(DF))
[1] TRUE
> DF$C <- rnorm(10)
> onetoone(DF$A, DF$C)
[1] FALSE

这对于只有几千行的小问题很好用。

在我的实际应用程序中,这些列的行长为10000s,我最终将它们分成几部分,一旦其中一部分没有通过测试,我就返回了false。

答案 5 :(得分:1)

我一直在寻找类似的功能,但也找不到。这就是我想出的。它返回任何不匹配的表。

test121 <- function(mydat, col1, col2) {
  tab <- table(mydat[[col1]], mydat[[col2]])
  sumrows <- apply(tab>0, 1, sum)
  sumcols <- apply(tab>0, 2, sum)
  probrows <- sumrows>1
  extracols <- apply(tab[probrows, , drop=FALSE], 2, sum) >0
  probcols <- sumcols>1
  extrarows <- apply(tab[, probcols, drop=FALSE], 1, sum) >0
  out <- tab[probrows | extrarows, probcols | extracols]
  if(sum(dim(out))<1) {
    return("Columns match one-to-one")
  } else {
    return(out)
  }
}

使用您的数据:

> test121(DF, "A", "B")
[1] "Columns match one-to-one"

在您的数据中引入了一个不匹配:

> DF2 <- data.frame(
+     A = c(0, 2, 0, 1, 2, 1, 0, 1, 2, 1),
+     B = c("H", "M", "H", "W", "M", "W", "H", "W", "W", "W")
+   )
> test121(DF2, "A", "B")
   
    M W
  1 0 4
  2 2 1

答案 6 :(得分:0)

使用mappings包中的utilities函数

(注意:这是一个 answer 的副本,基本上是关于 CV.SE 的相同问题。)

您可以使用 mappingsutilities package 中的 R 函数检查数据框中变量之间的函数映射。此函数采用输入数据框并检查变量之间是否存在映射。默认情况下,该函数仅检查因子变量,但您可以通过设置 all.vars = TRUE 来检查数据中的所有变量。 (请记住,应谨慎解释非因子变量之间的映射;连续变量几乎总是处于一对一映射中,因为它们没有重复值。)这是一个包含五个因子的模拟数据集的示例变量,它们之间有许多映射。

#Create data frame 
VAR1 <- c(0,1,2,2,0,1,2,0,0,1)
VAR2 <- c('A','B','B','B','A','B','B','A','A','B')
VAR3 <- c(1:10)
VAR4 <- c('A','B','C','D','A','B','D','A','A','B')
VAR5 <- c(1:5,1:5)
DATA <- data.frame(VAR1 = factor(VAR1),
                   VAR2 = factor(VAR2),
                   VAR3 = factor(VAR3),
                   VAR4 = factor(VAR4),
                   VAR5 = factor(VAR5))
DATA

   VAR1 VAR2 VAR3 VAR4 VAR5
1     0    A    1    A    1
2     1    B    2    B    2
3     2    B    3    C    3
4     2    B    4    D    4
5     0    A    5    A    5
6     1    B    6    B    1
7     2    B    7    D    2
8     0    A    8    A    3
9     0    A    9    A    4
10    1    B   10    B    5

我们可以使用下面的 R 代码检查映射。如您所见,该函数的输出显示了因子之间的所有函数关系,它还告诉您哪些因子是“冗余的”(即其他因子的函数)。默认情况下,输出包括一个 DAG 图,显示因子之间的映射。

#Examine mappings in the data
library(utilities)
MAPS <- mappings(DATA)
MAPS


Mapping analysis for data-frame DATA containing 5 factors (analysis ignores NA values) 

There were 7 mappings identified: 
 
     VAR1 → VAR2 
     VAR3 → VAR1 
     VAR3 → VAR2 
     VAR3 → VAR4 
     VAR3 → VAR5 
     VAR4 → VAR1 
     VAR4 → VAR2 

Redundant factors: 
 
     VAR1 
     VAR2 
     VAR4 
     VAR5 

Non-Redundant factors: 
 
     VAR3

enter image description here

从输出和图中可以看出,数据框中唯一的非冗余因子是 VAR3;所有其他因子变量都是该变量的函数。 (这也可以通过查看数据框中的值来确认。)