1
votes

Échantillonnage d'une table de données secondaire à la table de données principale en fonction d'une condition

J'ai deux tables de données dt_main et dt_unit.

dt_main[,Unit:=sample(dt_unit[Group==Group]$Unit_id,size=1)]

dt_main ressemblent à ceci: p>

> dt_unit[Group==1]
   Group Unit_id
1:     1    2624
2:     1    2963
3:     1    1974
4:     1    1800
5:     1    1930
6:     1    1325

dt_unit ressemble à ceci:

> dt_unit
    Group Unit_id
 1:     1    2624
 2:     1    2963
 3:     1    1974
 4:     1    1800
 5:     2    1851
 6:     1    1930
 7:     1    1325
 8:     2    1329
 9:     2    1553
10:     2    2445

Je voudrais remplir le Colonne Unit dans dt_main en échantillonnant un Unit_id de dt_unit à dt_main avec le même Group .

Par exemple, pour la première ligne de dt_main (donc Group = 1), le code doit rechercher dt_unit et recherchez les lignes où Group vaut 1 (voir ci-dessous), puis sélectionnez un Unit_id et insérez-le dans Unit .

> dt_main
    ID Group Unit
 1:  4     1    0
 2:  7     1    0
 3:  1     1    0
 4:  2     2    0
 5: 13     2    0
 6: 19     2    0
 7: 11     2    0
 8: 17     3    0
 9: 14     1    0
10:  3     3    0

J'ai essayé quelque chose comme ça qui attribuait le même numéro à chaque ligne:

set.seed(1)
dt_main<-data.table(ID=sample(1:20,size=10),Group=sample(1:3,size=10,replace=TRUE),Unit=0)
dt_unit<-data.table(Group=sample(1:3,size=10,replace=TRUE),Unit_id=sample(1000:3000,size=10,replace=TRUE))

J'ai aussi essayé sapply mais pas bon.


2 commentaires

Voulez-vous le même Unit_id pour toutes les valeurs de Group ? Donc Group = 1 aurait la même valeur de dt_unit ?


Non, je veux des valeurs aléatoires à chaque fois.


4 Réponses :


0
votes

try:

sample_unit_id <- function(group) {sapply(group,function(g){sample(dt_unit[Group==g,Unit_id],1)})}

dt_main[,.(Group,Unit_id = sample_unit_id(Group))]

   Group Unit_id
 1:     3    2831
 2:     3    2133
 3:     2    2814
 4:     2    2814
 5:     2    1464
 6:     2    2752
 7:     1    1832
 8:     2    1464
 9:     2    2814
10:     2    2752


4 commentaires

Comment avez-vous obtenu les valeurs de Group = 3 ? Il n'y a pas de Group = 3 dans le bloc de données dt_unit ...


Regardez la source, c'est un dataframe généré aléatoirement


Quelque chose cloche ici. Pourriez-vous essayer de vérifier avec seed = 1


OK, j'ai oublié la graine :-)



1
votes

Voici une solution de base R où nous faisons correspondre les groupes et échantillonnons 1 valeur à chaque fois,

dt_main$Unit <- sapply(dt_main$Group, function(i) {
                                  v1 <- dt_unit$Unit_id[dt_unit$Group %in% i]; 
                                  if (length(v1) > 0) {sample(v1, 1) } else {NA}
                                  })


#    ID Group Unit
# 1:  4     1 1930
# 2:  7     1 1325
# 3:  1     1 1325
# 4:  2     2 1329
# 5: 13     2 2445
# 6: 19     2 2445
# 7: 11     2 1851
# 8: 17     3   NA
# 9: 14     1 1930
#10:  3     3   NA


2 commentaires

Je sais que cela change la question, mais y a-t-il une solution simple pour ce qui suit: Je veux ajouter une deuxième condition tout en recherchant la valeur. Par exemple, supposons qu'il y ait également une colonne Size dans chaque table et lorsque je recherche la deuxième table de données, je veux échantillonner à partir des lignes dont: la colonne Group correspond et dt_main $ Size> dt_unit $ Size .


Cela devrait être une solution facile. Une façon vous vient à l'esprit, vous pouvez ajouter un v2 sous v1 dans la fonction sapply () qui n'obtiendra que les unit_ids de ceux qui satisfont votre état. Ensuite, intersectez v1 et v2 et échantillonnez comme d'habitude



1
votes

Vous pouvez joindre dt_main et dt_unit par Group et sélectionner une ligne aléatoire pour chaque ID .

En utilisant dplyr , vous pouvez le faire en:

library(dplyr)
left_join(dt_main, dt_unit, by = 'Group') %>% group_by(ID) %>% sample_n(1)


#     ID Group Unit_id
#   <int> <int>   <int>
# 1     1     1    1800
# 2     2     2    2445
# 3     3     3      NA
# 4     4     1    2963
# 5     7     1    1800
# 6    11     2    1851
# 7    13     2    1553
# 8    14     1    1325
# 9    17     3      NA
#10    19     2    2445

J'ai supprimé la colonne Unit de data.table création.


0 commentaires

0
votes

Une autre réponse avec mapply , que j'ai utilisée pour le cas avec plusieurs conditions. Dans ce cas, en recherchant je vérifie si les colonnes du Groupe correspondent ET qu'une nouvelle colonne ( Size ) dans dt_main est plus grande que celle de dt_unit . En tant qu'OP, j'ai dû ajouter une autre condition au message d'origine et donc ajouter cette solution pour aider les futurs utilisateurs.

my_fun<-function(var1,var2)
{
  d<-dt_unit[(Group%in%var1)&(Size>=var2)]
  if(nrow(d)>=2){
  sample(x=d$Unit_id,size=1,replace=T)
  }else
  {d$Unit_id}
}
vars1<-dt_main$Group
vars2<-dt_main$Size
dt_main$Unit<-mapply(my_fun,vars1,vars2)


0 commentaires