2017-03-28 2 views
0

J'ai une liste L d'unités de données où chaque trame est constituée de la variable Var et d'une observation composée de nombres différents. Chaque nombre dans chaque observation appartient à l'ensemble {1,2,3,4,5,11,12,13,14,15}. L pourrait, à titre d'exemple, ressemblent:Recherche de modèles dans une liste de données en utilisant R

> L 
[[1]] 
        Var 
1 "3", "11", "1", "15", 

[[2]] 
        Var 
1 "5", 13", "3", "12", 

[[3]] 
        Var 
1 "4", "1", "2", "5", 

Le problème que je tente de résoudre est le suivant. Je veux savoir s'il y a un nombre positif x = {1,2,3,4,5} de sorte que lorsqu'il est ajouté à chaque nombre dans une observation donnée, cette observation devient équivalente à une autre. Par exemple, considérons les 2 premiers éléments de L et laisser x=2, puis, en ajoutant x au premier élément de L rendements:

> L[[1]] 
        Var 
1 "5", "13", "3", "17", 

Le numéro 17 ne répond pas aux conditions de l'ensemble défini ci-dessus. Je veux que les contraintes suivantes s'appliquent sur x. Soit y dénote un nombre dans un obs. dans une trame de données de L:

if y + x > 15 then subtract 5 
if 5 < y + x < 11 then subtract 5 

Le même exemple avec ces contraintes produirait:

> L[[1]] 
        Var 
1 "5", "13", "3", "12", 

Et L[[1]] deviendrait équivalent à L[[2]]. Dans mon monde, L[[1]] et L[[2]] partagent le même modèle. Ce que je veux faire est de faire correspondre les éléments de L basés sur des modèles équivalents (dans le sens décrit ci-dessus) et de trier les groupes en fonction du "nombre de membres". Donc, dans l'exemple ici, je voudrais détecter que L[[1]] et L[[2]] sont dans un groupe et que c'est le groupe avec le plus de membres, suivi par le groupe suivant, qui dans cet exemple se compose uniquement de L[[3]]. Je suis très nouveau à R et toute direction serait appréciée!

+0

Normaliser vos données, en soustrayant le minimum de chaque ligne? –

Répondre

1

Il semble que vos "contraintes" définissent une relation d'équivalence mathématique. Cela signifie que vos groupes sont réellement des classes d'équivalence au sens mathématique et que vous pouvez définir un représentant unique pour chaque groupe. Si vous faites cela, vous pouvez facilement vérifier l'équivalence (= éléments appartenant au même groupe) en comparant leurs représentants. Définissons le représentant comme l'élément de votre classe d'équivalence qui commence par "1", c'est-à-dire, pour chaque élément de liste, nous ajoutons l'entier dans 1:5, suivant vos contraintes définies, de sorte que le premier élément soit égal à un. Nous pouvons le faire pour chaque élément de votre liste L et ensuite comparer les éléments qui ont le même représentant.

Mise en œuvre en R:

Commençons par votre liste 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")) 

En premier lieu, nous simplifions la liste en le convertissant en une liste de vecteurs numériques:

## 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 

Ensuite, nous définissons la fonction pour effectuer l'addition, en suivant vos contraintes et trouvez le représentant pour chaque élément:

## 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 

Maintenant, nous pouvons définir les groupes, dans votre exemple il y a deux groupes. Nous les appellerons group1 et 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 

Enfin, nous vérifions quel groupe chaque observation appartient à:

## 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" 

Nous savons maintenant que les observations 1 et 2 Belog au même groupe (group1) et cette observation 3 appartient à group1. En utilisant table(groupAffiliationVec), vous pouvez calculer le nombre de membres pour chaque groupe.

+0

Comment pouvons-nous ajuster cela afin que les éléments de 'L' qui commencent par un nombre' n = {11,12,13,14,15} 'soient considérés? Merci! – CHRD

+0

Vous avez raison, je n'ai pas considéré cela. Vous pouvez définir le représentant comme l'élément commençant par "1" si le premier élément est dans {1,2,3,4,5} ou commençant par "11" si le premier élément est dans {11,12,13,14 , 15}. Tout ce que vous auriez à faire est de remplacer la définition de '' representativesList ce qui suit: 'representativesList <- lapply (L2, fonction (myVec) { \t \t \t si (myVec [1] <11) { \t \t \t \t addConstant (myVec, 6 - myVec [1]) \t \t \t} else { \t \t \t \t addConstant (myVec, 16 - myVec [1]) \t \t \t} \t \t \t}) ' – ikop