假设我在R
中有一个数据帧,其中有两个变量,我将分别称为A
和B
。我想检查这两个变量是否在一对一映射中。例如,考虑以下数据帧:
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
在此数据框中,通过检查我们可以看到A
和B
之间(与0 = H
,1 = W
和{{ 1}})。我想找到一种方法来使用不需要我检查每个元素的适当2 = M
代码对较大的数据帧执行此操作。代码应生成简单明了的声明,以说明指定变量之间是否存在一对一的关系;一个简单的R
/ TRUE
输出应该是理想的。
更新:一些现有的答案在某种程度上给了我一个答案,但是输出比原本应该的要复杂得多。该代码应产生一个简单而清晰的输出,以回答问题。
答案 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 的相同问题。)
您可以使用 mappings
中 utilities
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
从输出和图中可以看出,数据框中唯一的非冗余因子是 VAR3
;所有其他因子变量都是该变量的函数。 (这也可以通过查看数据框中的值来确认。)