【问题标题】:Finding patterns in a list of dataframes using R使用 R 在数据框列表中查找模式
【发布时间】:2017-03-28 21:56:23
【问题描述】:

我有一个数据帧列表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 的前两个元素并让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 的元素,并根据“成员数量”对组进行排序。因此,在此处的示例中,我想检测L[[1]]L[[2]] 在一个组中,这是成员最多的组,其次是下一组,在此示例中仅包含L[[3]]。我对 R 很陌生,任何指导都将不胜感激!

【问题讨论】:

  • 通过减去每行的最小值来规范化您的数据?

标签: r list dataframe equivalence-classes


【解决方案1】:

看起来您的“约束”定义了数学等价关系。这意味着您的组实际上是数学意义上的等价类,并且您可以为每个组定义一个唯一的代表。如果这样做,您可以通过比较它们的代表来轻松检查等价性(= 属于同一组的元素)。

让我们将代表定义为等价类中以“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

现在我们可以定义组,在您的示例中有两个组。我们称他们为group1group2

## 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),您可以计算每个组的成员数。

【讨论】:

  • 我们如何调整它,以便以数字n = {11,12,13,14,15} 开头的L 的元素也被考虑?谢谢!
  • 你说得对,我没有考虑到这一点。如果第一个元素在 {1,2,3,4,5} 中,您可以将代表定义为以“1”开头的元素,如果第一个元素在 {11,12,13,14 中,则可以定义为以“11”开头的元素,15}。您所要做的就是将representativesList 的定义替换为以下内容:representativesList &lt;- lapply(L2, function(myVec){ if (myVec[1] &lt; 11){ addConstant(myVec, 6 - myVec[1]) } else { addConstant(myVec, 16 - myVec[1]) } })
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-23
  • 1970-01-01
  • 2021-01-26
相关资源
最近更新 更多