2 votes

Filtrage d'une matrice en R par les valeurs des colonnes

Je me demande s'il existe un moyen de filtrer rapidement et efficacement les matrices sans avoir à les convertir en data frame ou data.table.

Veuillez considérer la matrice suivante :

# Choose control variables 
control_vars <- c("x1", "F_5", "F_7")
my_args = lapply(control_vars, function(x) c("", x))
# Create a matrix of all combinations of the control variables
all_combs = as.matrix(do.call("expand.grid", my_args))

Le résultat ressemble à ceci :

     Var1 Var2  Var3 
[1,] ""   ""    ""   
[2,] "x1" ""    ""   
[3,] ""   "F_5" ""   
[4,] "x1" "F_5" ""   
[5,] ""   ""    "F_7"
[6,] "x1" ""    "F_7"
[7,] ""   "F_5" "F_7"
[8,] "x1" "F_5" "F_7"

Je veux éliminer toute ligne de cette matrice où à la fois F_5 et F_7 sont présents. Il s'agit des lignes 7 et 8.

Pour situer le contexte, j'essaie d'effectuer des régressions pas à pas et je veux éliminer les lignes où il y a des effets fixes "redondants". En d'autres termes, je n'ai besoin que de F_5 ou F_7, mais pas les deux. Par exemple, supposons que F_5 et F_7 classent les pays en 5 et 7 groupes. Ce dernier est plus granulaire que le premier, mais je ne veux pas qu'ils soient tous les deux présents dans ma régression.

Il serait facile de le faire après l'avoir converti en data.frame en comptant le nombre de "F" dans une ligne et en les supprimant ensuite, mais je me demande s'il existe une solution plus rapide et plus propre en utilisant des matrices. Mon jeu de données réel comporte 8 effets fixes substituables différents, de sorte qu'il n'est pas possible de les supprimer manuellement.

Gracias.

1voto

akrun Points 148302

Créer un vecteur logique avec rowSums sur "F_5" et "F_7" séparément avec == créer une expression unique avec l'opérateur logique & sur les expressions logiques composées, la négation ( ! ) et l'utiliser comme index de ligne pour subdiviser les lignes

i1 <- !(rowSums(all_combs == 'F_5') > 0 & rowSums(all_combs == 'F_7') > 0)
all_combs[i1, ]
#   Var1 Var2  Var3 
#[1,] ""   ""    ""   
#[2,] "x1" ""    ""   
#[3,] ""   "F_5" ""   
#[4,] "x1" "F_5" ""   
#[5,] ""   ""    "F_7"
#[6,] "x1" ""    "F_7"

Ou, s'il y a plusieurs éléments à comparer, nous pouvons les passer en boucle dans lapply , faire le rowSums , Reduce en une seule expression logique avec & et la négation ( ! ) pour le sous-ensemble

all_combs[!Reduce(`&`, lapply(c("F_5", "F_7"),
         function(x) rowSums(all_combs == x) > 0)),]

Une autre option, moins efficace, consiste à parcourir les lignes en boucle à l'aide de la fonction apply (MARGIN = 1), vérifier si all les valeurs du vecteur ( c("F_5", "F_7") ) sont %in% la ligne, la négation ( ! ) au sous-ensemble

all_combs[!apply(all_combs, 1, function(x) all(c("F_5", "F_7") %in% x)),]

Ou utiliser dapply de collapse quelle est l'approche efficace pour les opérations en rangs serrés

library(collapse)
sbt(all_combs, !dapply(all_combs, function(x) 
       all(c("F_5", "F_7") %in% x), MARGIN = 1))
#    Var1 Var2  Var3 
#[1,] ""   ""    ""   
#[2,] "x1" ""    ""   
#[3,] ""   "F_5" ""   
#[4,] "x1" "F_5" ""   
#[5,] ""   ""    "F_7"
#[6,] "x1" ""    "F_7"

0voto

G. Grothendieck Points 40825

1) Nous supposons que les doublons potentiels ont un trait de soulignement dans leur nom et un préfixe commun, tandis que les autres variables n'ont pas de trait de soulignement dans leur nom. Utiliser sub pour supprimer tout ce qui se trouve après un trait de soulignement dans chaque élément de all_combs, en ne laissant que le préfixe et le trait de soulignement. Ensuite, sur chaque ligne, vérifiez s'il y a des doublons parmi les chaînes de caractères comportant un trait de soulignement et réduisez all_combs à celles qui ne correspondent pas.

have_dups <- function(x) anyDuplicated(x[grepl("_", x)]) > 0
ok <- !apply(sub("_.*", "_", all_combs), 1, have_dups)
all_combs[ok, ]

donner :

     Var1 Var2  Var3 
[1,] ""   ""    ""   
[2,] "x1" ""    ""   
[3,] ""   "F_5" ""   
[4,] "x1" "F_5" ""   
[5,] ""   ""    "F_7"
[6,] "x1" ""    "F_7"

2) Une autre approche consisterait à accepter le fait qu'il existe des doublons et à utiliser le logiciel ExhaustiveSearch pour effectuer les régressions. Il exécutera et comparera automatiquement tous les sous-modèles avec des combsUpTo ou moins de variables indépendantes. Ce logiciel est très rapide et il est probable que les modèles comportant des doublons ne sortiront pas vainqueurs de toute façon. Avec cette approche, nous n'avons pas besoin de all_combs ni du code associé, juste de ceci.

library(ExhaustiveSearch)
ExhaustiveSearch(y ~ ., mydata, combsUpTo = 2)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X