R语言 检查变量是否处于一对一Map中

odopli94  于 2023-06-19  发布在  其他
关注(0)|答案(7)|浏览(112)

假设我在R中有一个 Dataframe ,其中有两个变量,我称之为AB。我想检查这两个变量是否在一对一的Map中)。例如,考虑以下 Dataframe :

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

在这个 Dataframe 中,我们可以通过检查看到,AB之间存在一一对应关系(0 = H1 = W2 = M)。我想找到一种方法,使用适当的R代码来处理更大的 Dataframe ,而不需要检查每个元素。代码应该产生一个简单明了的语句说明指定变量之间是否存在一对一的关系;简单的TRUE/FALSE输出应该是理想的。

xsuvu9jc

xsuvu9jc1#

如果我们想检查'A','B'是否有重复项,使用duplicated from base R

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

如果我们需要一个TRUE/FALSE,则使用all Package

all(i1)
#[1] TRUE

可以封装成函数

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

llew8vvj2#

下面是使用table函数的一个相对简单的方法

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

从这里你可以看到所有的0A对应于B中的H等等。
要将其 Package 在正式检查中,可以检查列总和是否匹配列max:

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

vcirk6k63#

我正在寻找一个类似的功能,也找不到一个。这是我的想法它返回一个包含任何不匹配的表。

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
qyswt5oh

qyswt5oh4#

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
gg58donl

gg58donl5#

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

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
pu3pd22g

pu3pd22g6#

我想知道是否有一个单独的项目的一对一Map。在你的例子中,我发现了一个小错误,所以谢谢你的提问。
基本思想是创建一个表(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,则Map为一对一。我最初的错误是没有检查两个方向上Map的唯一性。我知道我可以计算特征值来找出同样的东西,但这不是那么明显,在初步测试中慢得多。
这是我的功能。传入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

这对于只有几千行的小问题很有效。
在我的实际应用程序中,列的长度是10000行,我最终将它们分成几个部分,只要一个部分没有通过测试,我就返回一个false。

hs1rzwqc

hs1rzwqc7#

使用utilities包中的mappings函数

  • (注:这是对CV. SE上基本相同问题的回答的副本。)*

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

#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代码检查Map。如您所见,函数的输出显示了因子之间的所有函数关系,还告诉您哪些因子是“冗余”的(即,其他因子的函数)。默认情况下,输出包括显示因子之间Map的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

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

相关问题