看起来您的“约束”定义了数学等价关系。这意味着您的组实际上是数学意义上的等价类,并且您可以为每个组定义一个唯一的代表。如果这样做,您可以通过比较它们的代表来轻松检查等价性(= 属于同一组的元素)。
让我们将代表定义为等价类中以“1”开头的元素,即,对于每个列表元素,我们在 中添加整数1:5
,遵循您定义的约束,以便第一个元素等于一个。我们可以对列表中的每个元素执行此操作,L
然后比较哪些元素具有相同的代表。
R中的实现:
让我们从您的清单开始L
:
L <- list(structure(list(Var = c("3", "11", "1", "15")), .Names = "Var",
row.names = c(NA, -4L), class = "data.frame"),
structure(list(Var = c("5", "13", "3", "12")), .Names = "Var",
row.names = c(NA, -4L), class = "data.frame"),
structure(list(Var = c("4", "1", "2", "5")), .Names = "Var",
row.names = c(NA, -4L), class = "data.frame"))
首先,我们通过将列表转换为数值向量列表来简化列表:
## Simplify list: convert to list of numerical vectors:
L2 <- lapply(L, function(x) as.numeric(x$Var))
> L2
[[1]]
[1] 3 11 1 15
[[2]]
[1] 5 13 3 12
[[3]]
[1] 4 1 2 5
然后我们定义执行加法的函数,遵循您的约束并找到每个元素的代表:
## Function to implement the addition rules:
addConstant <- function(myVec, constant){
outVec <- myVec + constant
outVec <- ifelse(((outVec > 5) & (outVec < 11)) |(outVec > 15),
outVec - 5, outVec)
}
## Define representative of equivalence class as the one starting with a "1":
representativesList <- lapply(L2, function(myVec) addConstant(myVec, 6 - myVec[1]))
> representativesList
[[1]]
[1] 1 14 4 13
[[2]]
[1] 1 14 4 13
[[3]]
[1] 1 3 4 2
现在我们可以定义组,在您的示例中有两个组。我们将调用它们group1
并且group2
:
## Define groups: Unique representatives:
groupList <- unique(representativesList)
names(groupList) <- paste0("group", seq(along = groupList))
> groupList
$group1
[1] 1 14 4 13
$group2
[1] 1 3 4 2
最后,我们检查每个观察属于哪个组:
## Find group:
groupAffiliationVec <- vapply(representativesList, function(x){
flagVec <- vapply(groupList, function(y, x) identical(x,y), logical(1), x)
names(groupList[flagVec])
}, character(1))
> groupAffiliationVec
[1] "group1" "group1" "group2"
我们现在知道观察 1 和 2 属于同一组 ( group1
) 并且观察 3 属于group1
。使用table(groupAffiliationVec)
,您可以计算每个组的成员数。