使用 R 在数据帧列表中查找模式
Finding patterns in a list of dataframes using R
我有一个数据帧列表 L
,其中每个数据帧都包含变量 Var
和一个由不同数字组成的观察值。每个观察中的每个数字都属于集合 {1,2,3,4,5,11,12,13,14,15}
。例如,L
可能如下所示:
> L
[[1]]
Var
1 "3", "11", "1", "15",
[[2]]
Var
1 "5", 13", "3", "12",
[[3]]
Var
1 "4", "1", "2", "5",
我要解决的问题如下。我想知道是否有一个正数 x = {1,2,3,4,5}
使得当添加到给定观察中的每个数字时,该观察变得等同于另一个。例如,考虑 L
的前 2 个元素并让 x=2
,然后将 x
添加到 L
的第一个元素产生:
> L[[1]]
Var
1 "5", "13", "3", "17",
数字17不符合上面定义的集合条件。我希望将以下约束应用于 x
。让 y
表示 obs 中的数字。在 L
:
的数据框中
if y + x > 15 then subtract 5
if 5 < y + x < 11 then subtract 5
具有这些约束的相同示例将产生:
> L[[1]]
Var
1 "5", "13", "3", "12",
而 L[[1]]
将等同于 L[[2]]
。在我的世界里,L[[1]]
和 L[[2]]
共享相同的模式。我想要做的是根据等效(在上述意义上)模式匹配 L
的元素,并根据 "the number of members" 对组进行排序。因此,在此处的示例中,我想检测 L[[1]]
和 L[[2]]
在一个组中,并且这是成员最多的组,其次是下一组,在此示例中仅包含L[[3]]
。我是 R 的新手,如有任何指导,我们将不胜感激!
看起来你的"constraints"定义了一个数学等价关系。这意味着您的组在数学意义上确实是等价的 classes,并且您可以为每个组定义一个唯一的代表。如果这样做,您可以通过比较它们的代表来轻松检查等价性(=属于同一组的元素)。
让我们将代表定义为等价 class 中以“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)
,您可以计算每个组的成员数。
我有一个数据帧列表 L
,其中每个数据帧都包含变量 Var
和一个由不同数字组成的观察值。每个观察中的每个数字都属于集合 {1,2,3,4,5,11,12,13,14,15}
。例如,L
可能如下所示:
> L
[[1]]
Var
1 "3", "11", "1", "15",
[[2]]
Var
1 "5", 13", "3", "12",
[[3]]
Var
1 "4", "1", "2", "5",
我要解决的问题如下。我想知道是否有一个正数 x = {1,2,3,4,5}
使得当添加到给定观察中的每个数字时,该观察变得等同于另一个。例如,考虑 L
的前 2 个元素并让 x=2
,然后将 x
添加到 L
的第一个元素产生:
> L[[1]]
Var
1 "5", "13", "3", "17",
数字17不符合上面定义的集合条件。我希望将以下约束应用于 x
。让 y
表示 obs 中的数字。在 L
:
if y + x > 15 then subtract 5
if 5 < y + x < 11 then subtract 5
具有这些约束的相同示例将产生:
> L[[1]]
Var
1 "5", "13", "3", "12",
而 L[[1]]
将等同于 L[[2]]
。在我的世界里,L[[1]]
和 L[[2]]
共享相同的模式。我想要做的是根据等效(在上述意义上)模式匹配 L
的元素,并根据 "the number of members" 对组进行排序。因此,在此处的示例中,我想检测 L[[1]]
和 L[[2]]
在一个组中,并且这是成员最多的组,其次是下一组,在此示例中仅包含L[[3]]
。我是 R 的新手,如有任何指导,我们将不胜感激!
看起来你的"constraints"定义了一个数学等价关系。这意味着您的组在数学意义上确实是等价的 classes,并且您可以为每个组定义一个唯一的代表。如果这样做,您可以通过比较它们的代表来轻松检查等价性(=属于同一组的元素)。
让我们将代表定义为等价 class 中以“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)
,您可以计算每个组的成员数。