9
votes

Comptez les éléments correspondants à la ligne entre deux tables de données dans R

J'ai deux cadres de données dans R, et j'ai besoin de compter l'élément correspond à la ligne à la ligne, à obtenir enfin une colonne avec la longueur du produit cartésien des tables et des ID des deux rangées. En outre, les tables sont assez grandes et avec un nombre différent de lignes, mais le même nombre de colonnes.

J'ai le code suivant, mais il est assez lent lorsque vous avez plusieurs exécutions. P>

   R
   ID_ap ID Ac
 1:     1  1  0
 2:     1  2  0
 3:     1  3  4
 4:     1  4  0
 5:     2  1  0
 6:     2  2  0
 7:     2  3  0
 8:     2  4  4
 9:     3  1  3
10:     3  2  0
11:     3  3  0
12:     3  4  0
13:     4  1  0
14:     4  2  3
15:     4  3  0
16:     4  4  0


5 commentaires

Quelles sont les dimensions de vos "données.frame" et quelles valeurs contiennent-elles?


Il y a environ 10 000 rangées et une matrice de 100 rangées, remplie de petits entiers positifs non nuls.


Dans une rangée, les valeurs sont toujours distinctes?


Oui, les valeurs sont toujours distinctes dans une rangée et les lignes sont toujours distinctes dans une matrice. Mais entre les deux matrices, il pourrait y avoir des rangées égales @frank


En ce qui concerne votre CJ.table, vous pourriez être intéressé par cette question: Stackoverflow.com/q/25888706


5 Réponses :


1
votes

Voici une possibilité:

> t1<-data.frame(matrix(c(1:24),nrow = 4))
> t2<-data.frame(matrix(c(11:34),nrow = 4))
> ret<-expand.grid(r1=1:nrow(t1),r2=1:nrow(t2))
> ret$matches<-apply(ret,1,function(a)sum(t1[a[1],] %in% t2[a[2],]))
> ret
   r1 r2 matches
1   1  1       0
2   2  1       0
3   3  1       4
4   4  1       0
5   1  2       0
6   2  2       0
7   3  2       0
8   4  2       4
9   1  3       3
10  2  3       0
11  3  3       0
12  4  3       0
13  1  4       0
14  2  4       3
15  3  4       0
16  4  4       0


2 commentaires

Merci @MriP, fonctionne bien avec de petites matrices, mais cela prend beaucoup plus de temps que le code d'origine lorsque vous utilisez des lignes plus grandes comme 10k, je vais essayer de regarder plus profondément dessus.


Si vous avez un gros jeu de données et que vous avez besoin de vitesse, je recommanderais (1) n'utilisez pas de données.frame ou data.table, mais utilisez simplement des matrices et (2) utilisez la RCPP pour écrire un correspondant plus efficace.



3
votes

En supposant que le produit du nombre de lignes et le nombre de valeurs uniques dans les deux tableaux n'est pas grand: xxx

avec des valeurs uniques communes: xxx < / pré>

et tabuler la présence de chaque valeur unique dans chaque ligne pour chaque table: xxx

finalement: < Pré> xxx

si tab1 et tab2 sont très grands, ils peuvent être construits comme des matrices clairsemées et une manière pourrait être: < Pré> xxx

edit

avoir (1) de petites valeurs entières positives et (2) des valeurs distinctes dans chaque ligne, créant des recherches avec match / unique / Union et tabulation peut être évité: xxx


0 commentaires

5
votes

Mettez les données en format long, car l'ordre de colonne n'a pas d'importance: xxx

(1) pour chaque valeur, identifiez les paires pertinentes; et

(2) pour paires, les valeurs de comptage: xxx

Tous les autres (ID1, ID2) Les combos sont nuls et Ne doit pas être explicitement énuméré, je pense.


si les valeurs sont distinctes dans chaque table , comme dans l'exemple de l'OP, nous pouvons simplifier: xxx


2 commentaires

une join simple peut reconstruire les zéros si OP a besoin d'eux


Nice, cela bat le code de OP (déjà un peu rapide) - J'ai regardé les horaires de ma réponse (qui comprenaient une solution de base r lente): Stackoverflow.com/a/36558985/4598520



2
votes

Que diriez-vous: xxx

ou, à partir de zéro: xxx


0 commentaires

2
votes

Les exigences de performance ne sont pas clairement énoncées dans le poste. Mais, j'ai créé une version plus grande de votre exemple reproductible (ci-dessous) et que le code de la question est déjà assez rapide.

Voici comment le faire à la base R, pour une bonne mesure: xxx

par exemple, pour le grand problème reproductible de ci-dessous ( DIM (OUT) = = C (1e6, 3) ), le code ci-dessus est exécuté en moins de 20 secondes. xxx

Modifier Grand problème reproductible: xxx

la solution de l'OP fonctionne beaucoup plus vite que cette réponse xxx

mais la solution dans La réponse de Frank est plus rapide toujours xxx


3 commentaires

Merci d'avoir posté une référence. J'espérais que quelqu'un le ferait. Je serais curieux de voir si l'une des autres performance bien, aussi. Il est difficile de savoir quoi inclure / exclure dans le system.time () appel. Je dirais que mes onglets appartiennent à l'extérieur (comme vous l'avez ici) car les données doivent être stockées de cette façon de commencer. Mais la création de l'OP de rejoindre et r appartiennent à l'intérieur de l'appel, car ils font partie du processus juste pour ce calcul (mais ils sont en dehors de l'appel ici). C'est assez subjectif, cependant.


Merci. Je suis impressionné par votre réponse et je veux apprendre certains data.table maintenant. Je suis également d'accord sur la subjectivité.


Si nous mettons le de l'OP, rejoindre et r dans System.Time qui heurte le temps utilisateur jusqu'à 0.590 . J'ai essayé Toeddi 'S Colsums LIGNE, et c'est presque aussi lent que le mien ( user = 10.581`).